新的基本数据类型——符号(Symbol)
在符号诞生之前,我们的对象属性名都是字符串,这不仅容易造成属性名的冲突,而且属性可以被轻易的更改。所以我们需要一种'私有名称'来创建非字符串类型的属性名来防止常规的更改。这就是JS已有的基本类型(字符串,数值,布尔,null,undefined)之外,新增基本类型(Symbol)的目的之一。
普通符号的创建
符号没有字面量形式,只可以使用Symbol()全局函数创建。例子如下:
let ex = Symbol('desc'),
a = {};
a[ex] = 'val';
console.log(ex); // Symbol(desc)
console.log(typeof ex); // symbol
Symbol()接受一个字符串参数,表示对生成符号的描述,描述信息存储在内部属性[[Description]]中,一般用于调试,只能通过String()方法读取。不同的符号可以使用相同的描述,但是符号值是不相等的,每个符号都是唯一的。可以通过typeof运算符来判断一个变量是否为符号。
共享符号的创建
由于我们创建的每个符号都是唯一的,换句话说,如果我们想在不同的代码段中使用相同的符号标识取到同一个属性,我们就必须到原始创建的代码中取到这个标识。跨代码追踪无疑是很麻烦的,为此,我们可以使用Symbol.for()方法创建一个全局共享符号。例子如下:
let a = Symbol.for('one');
let b =Symbol.for('one');
console.log(a === b); // true
console.log(Symbol.keyFor(a, b)) // one one
Symbol.for()方法接受单个字符串为描述键值参数,创建的符号都存放在全局符号注册表里。首先会根据该参数搜索全局符号表,看看是否存在参数相同的符号,若存在则返回该值,若不存在则新建。 可以使用Symbol.keyFor()方法根据符号值检索出对应的描述键值。
符号的使用
由于符号的唯一性,将符号作为对象的属性名是最常用的方式,可以防止某个属性被改写或覆盖。写法如下:
let sym = Symbol();
// 方法一
let a = {};
a[sym] = 'val';
// 方法二
let a = {
[sym]: 'val';
}
// 方法三
let a = {};
Object.defineProperty(a, sym, {value: 'val'});
注意将Symbol作为对象属性名时不能用点运算符,因为点运算符后读取的值为字符串。 除了当作唯一的属性名之外,我们在需要唯一的值作判定时,也可以用Symbol来代替字符串。最典型的应用就是switch语句了。对每一个case,我们都可以使用symbol值保证按照期待的值工作。
符号的类型转换和检索方法
虽然符号属于基本类型的一种,但由于它的独特唯一性,一般都很难进行转换。只能通过显式的String()方法输出,toString()方法会引发错误。console.log有效则是调用了String()。还可以通过Boolean()方法转化为布尔值,但不可以通过Number()转化为数值。 检索对象属性时,我们一般采用Object.keys()或Object.getOwnPropertyNames()。前者返回所有可枚举属性名称,后者返回所有属性名称。但两者都不能返回符号属性。ES6新增了Object.getOwnPropertySymbols()方法,该方法返回一个数组,包含了对象自有的符号值,但不包含从原型上继承的符号值。
知名符号
ES6在全局Symbol对象中定义了一些属性,这些属性统称为知名符号,目前共有11个,这些属性对原先属于语言内部逻辑的一些部分进行了接口暴露,允许用户来定义这些基础行为,增强了JS的灵活性。由于不同知名符号的用法涉及JS的各个部分,以下仅作概述,具体使用方法将分别整合在今后相关模块的文章中。
- Symbol.hasInstance: 该方法定义在Funcition.prototype上,用来检测值是否为函数的一个实例。使用instanceof操作符时调用。
- Symbol.isConcatSpreadable: 一个布尔值,在集合对象作为参数传递给Array.prototype.concat()方法时,表示该对象是否可以展开。
- Symbol.iterator: 返回迭代器。
- Symbol.species: 用于产生派生对象的构造器。
- Symbol.unscopables: 一个对象,指定了哪些属性名不允许被包含在with语句中。
- Symbol.toPrimitive: 隐式类型转换时,定义转换规则。
- Symbol.match:定义String.prototype.match()的规则。用于比较字符串。
- Symbol.replace:定义String.prototype.replace()的规则。用于替换字符串。
- Symbol.search:定义String.prototype.search()的规则。用于定位字符串。
- Symbol.split: 定义String.prototype.split()的规则。用于分割字符串。
- Symbol.toStringTag: 定义String.prototype.toString()的规则。用于创建描述信息。
-- EOF --
前端开发
」下,并被添加
「JavaScript」
标签。