它是JS
的第七种类型,属于基本类型。
它表示一个独一无二的值,行为相似字符串。
它是直接经过Symbol
函数生成的,能够传入字符做为该值的描述。api
const symbol1 = Symbol('unique'); const symbol2 = Symbol('unique'); console.log(symbol1 === symbol2); // false
替代用于识别的字符串常量数组
--- 以前 const MY_ONE = 'unique-one'; if (MY_ONE === 'unique-one') { ... } 虽然定义了保存值的常量,但直接使用值或再定义相同值的变量也是没有问题的。 --- 如今 const MY_ONE = Symbol('one'); if (MY_ONE === MY_ONE) { ... } 若是想使用该常量,必须直接使用该常量或其一个副本,由于 Symbol('one') 是绝对惟一的。
做为间接实现私有属性和方法的途径函数
只有使用 private_a / private_b 变量所指向的值才能访问到相应的属性值。 const private_a = Symbol('private_a'); const private_b = Symbol('private_b'); function Class() { this[private_a] = 'private_a'; } Class.prototype[private_b] = function() { console.log('private_b'); }
做为自定义接口或不一样数据集合统一接口的名称this
示例:为 Array 增长并集的计算方法,使用此方法能够避免将来可能的命名冲突。 const CusArrayAPIMap = { union: Symbol('cus-array-api-union') }; Array[CusArrayAPIMap.union] = function() { return [...new Set([...arguments].reduce((a, b) => a.concat(b), []))]; }; Array[CusArrayAPIMap.union]([1, 3], [2, 3]); // [1, 3, 2]
symbol
值不可转化成数字(做为一个惟一值无对应的数值)。 symbol
值能够转化成布尔值(无论怎样,它是有值的,因此恒为true
)。 symbol
值不可被隐式转化成字符串,可是能够显示转化(隐式即计算,拿一个惟一值计算没意义,但直接打印成字符串查看是能够的)。prototype
Symbol() + 2; // 报错 Number(Symbol()); // 报错 Boolean(Symbol()); // 恒为 true if (Symbol()) { ... } // 恒执行 Symbol() + '-'; // 报错 String(Symbol()); // "Symbol()" Symbol().toString(); // "Symbol()"
Symbol.for(key)
与Symbol()
同样,用来返回一个惟一值。
不过其传入的key
与生成的值会造成映射存储在全局的symbol
注册表中。
便是说,Symbol.for(key)
是先根据key
在注册表中寻找,有直接返回,没有建立并返回。
也便是说,在相同的全局空间中(包括不一样的iframe
或service worker
)传入相同的key
取出来的是同一值。code
Symbol('one') === Symbol('one'); // false Symbol('one') === Symbol.for('one'); // false Symbol.for('one') === Symbol.for('one'); // true Symbol.for('one') === Symbol.for('two'); // false
相配套的还有方法Symbol.keyFor()
。
它会根据传入的Symbol
值,去注册表中查找并返回对应的key
。对象
let o = Symbol.for('one'); Symbol.keyFor(o); // 'one' Symbol.keyFor(Symbol('two')); // undefined Symbol.keyFor(Symbol.for('two')); // 'two'
ES6
规定了11个内置接口的统一名称。
能够将这些接口部署到自定义对象或构造函数上,同步原生操做。继承
Symbol.toStringTag
指向一个字符串,表示该对象的类型标签。
通俗的说,就是使用Object.prototype.toString.call(target)
获取到的[object Name]
中的Name
。接口
let obj = { [Symbol.toStringTag]: 'MyTag' }; console.log( Object.prototype.toString.call(target) ); // '[object MyTag]'
Symbol.toPrimitive
指向一个方法,当该对象被转化成Number
或String
型时会被调用。
该方法会接受一个字符串参数,表示当前场合须要转化成什么类型,一共有三种模式:number
,string
和default
(转化成二者都行)。ci
let obj = { [Symbol.toPrimitive](type) { switch(type) { case 'number': return 3; break; case 'string': return 's'; break; case 'default': return 'd'; break; } } }; console.log( Number(obj) ); // 3 console.log( String(obj) ); // 's' console.log( obj + 1 ); // 'd1'
Symbol.hasInstance
指向一个方法,是instanceof
命令实际调用的方法。
[] instanceof Array; // true 实际是执行下面代码。 Array[Symbol.hasInstance]([]); // true 可自行为自定义对象添加此接口。 let OBJ = { [Symbol.hasInstance](arr) { return arr.length === 2 ? true : false; } }; [1] instanceof OBJ; // false [1, 2] instanceof OBJ; // true
Symbol.iterator
指向对象的默认遍历器方法(关于遍历器可看Iterator
章节)。
数组默认的遍历器方法为:Array.prototype[Symbol.iterator]
。
Symbol.species
指向一个方法,该方法返回一个构造函数。当实例须要调用自身的构造函数时方法会被调用。
有些类库是在基类的基础上修改的,当子类使用继承的方法时,做者但愿返回基类的实例,而不是子类的实例。
class MyArray extends Array { static get [Symbol.species]() { return Array } } let a = new MyArray(1, 2, 3); let b = a.map(x => x); console.log(b instanceof Array); // true console.log(b instanceof MyArray); // false b 是 a 的衍生对象,或称派生对象。 若是没有 [Symbol.species] ,b 原型链中第一个对象应为 MyArray 原型。 但如今第一个对象为 Array 的原型,即 b 直接为 Array 的实例。
Symbol.split, Symbol.match, Symbol.search, Symbol.replace
四者都是针对字符串与正则(对象)的关系,指向一个方法,具备相同行为。
let reg = /m/g; let str = 'Hi, I\'m programmer monkey'; str.replace(reg, 'M'); 实际是执行下面的代码。 reg[Symbol.replace](str, 'M');
Symbol.isConcatSpreadable
指向一个布尔值,表示该对象用于Array.prototype.concat()
时是否能够展开。
默认没有该属性,即为undefined
,等同于true
。设置为false
则不展开。
let arr = [1, 2]; arr[Symbol.isConcatSpreadable] = false; [3].concat(arr); // [3, [1, 2]]
Symbol.unscopables
指向一个对象,该对象指定了使用with
关键字时,哪些属性会被with
环境排除。
let obj = { id: '123', name: 'limo', [Symbol.unscopables]: { id: true } }; let id = 'id'; let name = 'name'; with (obj) { console.log(id); // 'id' console.log(name); // 'limo' }