(JS基础)Symbol 类型

Symbol 类型是 ES6 引入的一种数据类型,表示独一无二的值,是 JavaScript 语言的第七种数据类型。
javascript

目前我所了解的两个用途:java

  • 做为属性名或变量名,避免重名带来的问题;
  • 做为内置对象的特定方法的属性名,方便开发者对其改写。


Symbol 值的建立

Symbol 值建立的方法有两种,下面逐一介绍。函数

Symbol() 函数

Symbol 值能经过Symbol函数生成,要注意的是,Symbol 类型没有构造函数,即便用new Symbol()会报错。此方法建立的 Symbol 值永远不会有相等的
测试

let s1 = Symbol();
// let s = new Symbol(); // 错误例子
// 能够传入字符串做为参数
let s2 = Symbol('foo');
// 即便传入相同的字符串,获得的两个值仍然是不相等的
console.log(Symbol('foo') === Symbol('foo'));    // false
// 经过 toString() 方法能够获取该值的字符串量
console.log(s2.toString());     // 'Symbol(foo)'
// 经过实例属性 description 能够获取描述的字符串量
console.log(s2.description);    // 'foo'
复制代码

如例子中的s2所示,Symbol()能传入字符串值做为描述,且仅能做为描述,即便是传入相同的描述字符串,获得的值仍然不相等。
ui

Symbol.for() 函数

使用Symbol.for()方法能够获得一个"可能相同"的 Symbol 值,接受一个字符串做为参数(该值做为key,经过keyFor()方法能够获取该值),而后搜索有没有以该参数做为名称的 Symbol 值。若是有,就返回这个 Symbol 值,不然就新建并返回一个以该字符串为名称的 Symbol 值。看以下例子:spa

let s1 = Symbol.for('baz');
let s2 = Symbol.for('baz');
console.log(s1 === s2);    // true
// 获取 key 值
console.log(s1.keyFor());  // 'baz'
复制代码


Symbol 做为属性名的注意事项

遍历方法中的 Symbol 属性值

使用 Symbol 做为属性名时,该属性不会出如今for...in循环中、Object.entries()Object.keys()Object.values()(其对应的属性值)、Object.getOwnPropertyNames()JSON.stringify()的返回。但它也不是私有属性。有两个方法能够获取到有关 Symbol 值的属性:Object.getOwnPropertySymbols方法,能够获取指定对象的全部 Symbol 属性名(Symbol 类型的值,非字符串量);以及扩展运算符(...)。下面是测试的结果:prototype

let obj = {
  [Symbol()]: 'symbol',
  a: 1
}
// 【for...in】
for(let i in obj){
  console.log(i);                 // a (只有a)
}
// 【Object.entries】
let entries = Object.entries(obj);
console.log(entries);             // [ [ 'a', 1 ] ]
// 【Object.values】
let values = Object.values(obj);
console.log(values);              // [ 1 ]
// 【Object.keys】
let keys = Object.keys(obj);
console.log(keys);                // [ 'a' ]
// 【Object.getOwnPropertyNames】
let ownPropNames = Object.getOwnPropertyNames(obj);
console.log(ownPropNames);        // [ 'a' ]
// 【JSON.stringify】
console.log(JSON.stringify(obj)); // {"a":1}

// 【Object.getOwnPropertySymbols】
let ownPropSymbols = Object.getOwnPropertySymbols(obj);
console.log(ownPropSymbols);  // [ Symbol() ]
// 【展开运算符(...)】
let obj2 = {...obj}
console.log(obj2);            // { a: 1, [Symbol()]: 'symbol' }复制代码

只能使用"[]"运算符

以 Symbol 值做为属性名,必须使用[]运算符定义和获取属性值。例子以下:code

let mySymbol = Symbol('foo');
let obj = {
  [mySymbol]: 'Symbol',
  mySymbol: 'string'
}
console.log(obj.mySymbol);    // string
console.log(obj[mySymbol]);   // Symbol
console.log(obj['mySymbol']); // string复制代码


内置的 Symbol 值

ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法,当开发者须要修改指定的原生方法时会用到。下面简单列举,具体请查阅MDN文档对象

Symbol.hasInstance

对象的Symbol.hasInstance属性,指向一个内部方法。当其余对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法。ip

Symbol.isConcatSpreadable

对象的Symbol.isConcatSpreadable属性等于布尔值,表示该对象用于Array.prototype.concat()时,是否能够展开。

Symbol.species

对象的Symbol.species属性,指向一个构造函数。建立衍生对象时,会使用该属性。

Symbol.match

对象的Symbol.match属性,指向一个函数。当执行str.match(myObject)时,若是该属性存在,会调用它,返回该方法的返回值。

Symbol.replace

对象的Symbol.replace属性,指向一个方法,当该对象被String.prototype.replace方法调用时,会返回该方法的返回值。

Symbol.search

对象的Symbol.search属性,指向一个方法,当该对象被String.prototype.search方法调用时,会返回该方法的返回值。

Symbol.split

对象的Symbol.split属性,指向一个方法,当该对象被String.prototype.split方法调用时,会返回该方法的返回值。

Symbol.iterator

对象的Symbol.iterator属性,指向该对象的默认遍历器方法。

Symbol.toPrimitive

对象的Symbol.toPrimitive属性,指向一个方法。该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。

Symbol.toStringTag

对象的Symbol.toStringTag属性,指向一个方法。在该对象上面调用Object.prototype.toString方法时,若是这个属性存在,它的返回值会出如今toString方法返回的字符串之中,表示对象的类型。也就是说,这个属性能够用来定制[object Object][object Array]object后面的那个字符串。

Symbol.unscopables

对象的Symbol.unscopables属性,指向一个对象。该对象指定了使用with关键字时,哪些属性会被with环境排除。

相关文章
相关标签/搜索