ES6 内置的 Symbol 值
-
Symbol.hasInstance
对象的Symbol.hasInstance
属性,指向一个内部方法。当其他对象使用instanceof
运算符,判断是否为该对象的实例时,会调用这个方法。比如,foo instanceof Foo 在语言内部,实际调用的是 Foo[Symbol.hasInstance](foo)。上面代码中,MyClass
是一个类,new MyClass() 会返回一个实例。该实例的Symbol.hasInstance
方法,会在进行instanceof
运算时自动调用,判断左侧的运算子是否为 Array 的实例。下面是另一个例子。 -
Symbol.isConcatSpreadable
对象的Symbol.isConcatSpreadable
属性等于一个布尔值,表示该对象用于Array.prototype.concat()
时,是否可以展开。上面代码说明,数组的默认行为是可以展开,Symbol.isConcatSpreadable
默认等于 undefined。该属性等于 true 时,也有展开的效果。类似数组的对象正好相反,默认不展开。它的Symbol.isConcatSpreadable
属性设为 true,才可以展开。Symbol.isConcatSpreadable
属性也可以定义在类里面。上面代码中,类 A1 是可展开的,类 A2 是不可展开的,所以使用 concat 时有不一样的结果。注意,Symbol.isConcatSpreadable
的位置差异,A1 是定义在实例上,A2 是定义在类本身,效果相同。 -
Symbol.species
对象的Symbol.species
属性,指向一个构造函数。创建衍生对象时,会使用该属性。上面代码中,子类 MyArray 继承了父类 Array,a 是 MyArray 的实例,b 和 c 是 a 的衍生对象。你可能会认为,b 和 c 都是调用数组方法生成的,所以应该是数组(Array的实例),但实际上它们也是 MyArray 的实例。Symbol.species
属性就是为了解决这个问题而提供的。现在,我们可以为 MyArray 设置Symbol.species
属性。上面代码中,由于定义了Symbol.species
属性,创建衍生对象时就会使用这个属性返回的函数,作为构造函数。这个例子也说明,定义Symbol.species
属性要采用 get 取值器。默认的Symbol.species
属性等同于下面的写法。现在,再来看前面的例子。上面代码中,a.map(x => x)
生成的衍生对象,就不是 MyArray 的实例,而直接就是 Array 的实例。再看一个例子。上面代码中,T2 定义了Symbol.species
属性,T1 没有。结果就导致了创建衍生对象时(then方法),T1 调用的是自身的构造方法,而 T2 调用的是Promise
的构造方法。总之,
Symbol.species
的作用在于,实例对象在运行过程中,需要再次调用自身的构造函数时,会调用该属性指定的构造函数。它主要的用途是,有些类库是在基类的基础上修改的,那么子类使用继承的方法时,作者可能希望返回基类的实例,而不是子类的实例。 -
Symbol.match
对象的Symbol.match
属性,指向一个函数。当执行str.match(myObject)
时,如果该属性存在,会调用它,返回该方法的返回值。 -
Symbol.replace
对象的Symbol.replace
属性,指向一个方法,当该对象被String.prototype.replace
方法调用时,会返回该方法的返回值。下面是一个例子。Symbol.replace
方法会收到两个参数,第一个参数是 replace 方法正在作用的对象,上面例子是 Hello,第二个参数是替换后的值,上面例子是 World。 -
Symbol.search
对象的Symbol.search
属性,指向一个方法,当该对象被String.prototype.search
方法调用时,会返回该方法的返回值。 -
Symbol.split
对象的Symbol.split
属性,指向一个方法,当该对象被String.prototype.split
方法调用时,会返回该方法的返回值。下面是一个例子。上面方法使用Symbol.split
方法,重新定义了字符串对象的split
方法的行为, -
Symbol.iterator
对象的Symbol.iterator
属性,指向该对象的默认遍历器方法。对象进行for...of
循环时,会调用Symbol.iterator
方法,返回该对象的默认遍历器,详细介绍参见《Iterator 和 for...of 循环》一章。 -
Symbol.toPrimitive
对象的Symbol.toPrimitive
属性,指向一个方法。该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。Symbol.toPrimitive
被调用时,会接受一个字符串参数,表示当前运算的模式,一共有三种模式。- Number:该场合需要转成数值
- String:该场合需要转成字符串
- Default:该场合可以转成数值,也可以转成字符串
-
Symbol.toStringTag
对象的Symbol.toStringTag
属性,指向一个方法。在该对象上面调用Object.prototype.toString
方法时,如果这个属性存在,它的返回值会出现在toString
方法返回的字符串之中,表示对象的类型。也就是说,这个属性可以用来定制 [object Object] 或 [object Array] 中 object 后面的那个字符串。ES6 新增内置对象的Symbol.toStringTag
属性值如下。JSON[Symbol.toStringTag]
:'JSON'Math[Symbol.toStringTag]
:'Math'- Module 对象
M[Symbol.toStringTag]
:'Module' ArrayBuffer.prototype[Symbol.toStringTag]
:'ArrayBuffer'DataView.prototype[Symbol.toStringTag]
:'DataView'Map.prototype[Symbol.toStringTag]
:'Map'Promise.prototype[Symbol.toStringTag]
:'Promise'Set.prototype[Symbol.toStringTag]
:'Set'%TypedArray%.prototype[Symbol.toStringTag]
:'Uint8Array'等WeakMap.prototype[Symbol.toStringTag]
:'WeakMap'WeakSet.prototype[Symbol.toStringTag]
:'WeakSet'%MapIteratorPrototype%[Symbol.toStringTag]
:'Map Iterator'%SetIteratorPrototype%[Symbol.toStringTag]
:'Set Iterator'%StringIteratorPrototype%[Symbol.toStringTag]
:'String Iterator'Symbol.prototype[Symbol.toStringTag]
:'Symbol'Generator.prototype[Symbol.toStringTag]
:'Generator'GeneratorFunction.prototype[Symbol.toStringTag]
:'GeneratorFunction'
-
Symbol.toStringTag
对象的Symbol.unscopables
属性,指向一个对象。该对象指定了使用 with 关键字时,哪些属性会被 with 环境排除。上面代码说明,数组有 7 个属性,会被 with 命令排除。上面代码通过指定Symbol.unscopables
属性,使得 with 语法块不会在当前作用域寻找 foo 属性,即 foo 将指向外层作用域的变量。