Symbol 类型

1,518 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第26天,点击查看活动详情

ECMAScript 有 6 种简单数据类型(也称为原始类型):Undefined、Null、Boolean、Number、String 和 Symbol。Symbol(符号)是 ECMAScript 6 新增的。

symbol 是原始值,且符号实例是唯一、不可变的。symbol 用途是确保对象属性使用唯一标识符,不会发生属性冲突的危险。

所以常用的场景:创建唯一记号。

基本用法

  • 初始化
let sym = Symbol();
// 支持传递参数
let bsym = Symbol('BBB');

使用Symbol()函数时,也支持传递一个字符串参数,用途是对符号的描述(description),将来可以通过这个字符串来调试代码。但是这个参数跟 symbol 没有任何关系。

  • 只要创建就是一个唯一的记号
let asym = Symbol('nanlv')
let bsym = Symbol('nanlv')
​
console.log(asym==bsym) ;  // 输出 false
  • 创建即唯一:只要创建 Symbol()实例并将其用作对象的新属性,就可以保证它不会覆盖已有的对象属性。
  • 不能与 new 一起使用

使用全局符号注册表

创建全局 symbol

当有部分功能可能需要共享或者重用时,那么可以用一个字符串作为键,在全局符号注册表中创建并重用 symbol。常用 symbol.for() 方法。

symbol.for() 会先检查全局运行时注册表,如果不存在则创建一个 symbol 实例并将其添加到全局符号注册表中,如果存在则直接返回该 symbol 实例。

let asym = Symbol.for('nanlv')
let bsym = Symbol.for('nanlv')
​
console.log(asym==bsym) ;  // 输出 true

但是需要注意,如果仅使用 symbol() 初始化实例时不能和 Symbol.for() 的实例时不相等的。

let asym = Symbol('nanlv')
let bsym = Symbol.for('nanlv')
​
console.log(asym==bsym) ;  // 输出 false

Symbol.for() 必须使用加上参数,即使用字符串键来创建。

查询全局 symbol

使用 Symbol.keyFor()来查询全局符号注册表。通过接收参数为 symbol 类型,返回该 symbol 对应的字符串键,如果查询不到则返回 undefined

let s = Symbol.for('nanlv'); 
console.log(Symbol.keyFor(s)); // nanlvconsole.log(Symbol.keyFor(s2)); // 报错 TypeError: s2 is not a symbol

Symbol.keyFor 仅对 Symbol.for() 方法创建的 symbol 实例才可以查找到,如果是 symbol()方法创建将返回 undefined。

使用 symbol 作为属性

let sym = Symbol();
let obj = {
    [sym]: "value"
};
console.log(obj[sym]); // "value"

symbol 属性是对内存中符号的一个引用,所以无法通过 Object.keysObject.getOwnPropertyNames 返回,但是可以使用 Object.getOwnPropertySymbols 方法来返回对象所有的 Symbol 属性。

常用内置 symbol

  • Symbol.hasInstance方法,会被instanceof运算符调用。构造器对象用来识别一个对象是否是其实例。
  • Symbol.isConcatSpreadable布尔值,表示当在一个对象上调用Array.prototype.concat时,这个对象的数组元素是否可展开。
  • Symbol.iterator方法,被for-of语句调用。返回对象的默认迭代器。
  • Symbol.match方法,被String.prototype.match调用。正则表达式用来匹配字符串。
  • Symbol.replace方法,被String.prototype.replace调用。正则表达式用来替换字符串中匹配的子串。
  • Symbol.search方法,被String.prototype.search调用。正则表达式返回被匹配部分在字符串中的索引。
  • Symbol.species函数值,为一个构造函数。用来创建派生对象。
  • Symbol.split方法,被String.prototype.split调用。正则表达式来用分割字符串。
  • Symbol.toPrimitive方法,被ToPrimitive抽象操作调用。把对象转换为相应的原始值。
  • Symbol.toStringTag方法,被内置方法Object.prototype.toString调用。返回创建对象时默认的字符串描述。

  • Symbol.unscopables对象,它自己拥有的属性会被with作用域排除在外。