Skip to content

Symbol

Symbol 值通过 Symbol() 函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突

js
let s = Symbol();

typeof s;
// "symbol"

注意,Symbol() 函数前不能使用 new 命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象,所以不能使用 new 命令来调用。另外,由于 Symbol 值不是对象,所以也不能添加属性。基本上,它是一种类似于字符串的数据类型

Symbol() 函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述。这主要是为了在控制台显示,或者转为字符串时,比较容易区分

js
let s1 = Symbol("foo");
let s2 = Symbol("bar");

s1; // Symbol(foo)
s2; // Symbol(bar)

s1.toString(); // "Symbol(foo)"
s2.toString(); // "Symbol(bar)"

如果 Symbol 的参数是一个对象,就会调用该对象的 toString() 方法,将其转为字符串,然后才生成一个 Symbol 值

js
const obj = {
  toString() {
    return "abc";
  },
};
const sym = Symbol(obj);
sym; // Symbol(abc)

注意,Symbol() 函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的 Symbol 函数的返回值是不相等的

js
let s1 = Symbol("foo");
let s2 = Symbol("foo");

s1 === s2; // false

Symbol 值不能与其他类型的值进行运算,会报错

js
let sym = Symbol("My symbol");

"your symbol is " + sym;
// TypeError: can't convert symbol to string
`your symbol is ${sym}`;
// TypeError: can't convert symbol to string

但是,Symbol 值可以显式转为字符串

js
let sym = Symbol("My symbol");

String(sym); // 'Symbol(My symbol)'

另外,Symbol 值也可以转为布尔值,但是不能转为数值

js
let sym = Symbol();
Boolean(sym); // true
!sym; // false

if (sym) {
  // ...
}

Number(sym); // TypeError
sym + 2; // TypeError