ES6 Symbol 用法

[ES6] Symbol 用法

Symbol 是什么?

Symbol 是 ES6 新增的一个数据类型,也是 JS 原生数据类型(Number,String,Boolean,undefined,null,Object,Bigint,Symbol)之一,表示独一无二的值。

为什么要有 Symbol ?

防止对象的属性名冲突

以往对象的属性名都是字符串,在使用的过程中,可能会出现属性名重复导致冲突的情况,于是 ES6 引入了Symbol,表示独一无二的值,避免了属性名的重复。

用法

创建一个 Symbol

1
2
3
4
5
6
7
let foo = Symbol();

console.log(foo);
// Symbol()
console.log(typeof foo);
// symbol

可以看到,这里是调用了 Symbol() 函数创建了一个 Symbol ,不需要使用 new 操作符,注意区分。

Symbol() 可以接受一个字符串作为参数,表示对这个 Symbol 的描述:

1
2
3
4
let foo = Symbol("bar");

console.log(foo);
// Symbol(bar)

如果该参数为对象,则调用对象的toString()方法转为字符串。

这个参数只作为描述存在,相同描述的Symbol并不相等。

1
2
3
4
let s1 = Symbol("desc");
let s2 = Symbol("desc");

console.log(s1 === s2); // false

Symbol.prototype.description

可以通过这个方法,获取创建 Symbol 时的描述字符串:

1
2
3
let s1 = Symbol("desc");

console.log(s1.description); // desc

作为属性名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let s1 = Symbol();

// 1
let a = {
[s1]: "hello",
};
// 2
let a = {};
a[s1] = "hello";
// 3
let a = {};
Object.defineProperty(a, s1, { value: "hello" });

console.log(a[s1]); // hello

三种方式都可以。注意在使用 Symbol 作为属性名时,不能使用.操作符,例如a.s1这里的s1实际上是字符串s1,和我们定义的 Symbol 没关系。

在对象内部使用时,也需要用[]包裹,不然也会被当做字符串处理。

属性名的遍历

Symbol 作为属性名时,是公有属性而不是私有属性,但是不能通过常规方式遍历到,例如:

  • for...in

  • for...of

  • Object.keys()

  • Object.getOwnPropertyNames()

  • JSON.stringify()

可以通过以下方式获取到:

  • Object.getOwnPropertySymbols() 返回当前对象中所有用作属性名的 Symbol 值的数组

  • Reflect.ownKeys() 返回所有类型的键名,包括常规键名和 Symbol 键名

Symbol.for()

Symbol.for()接受一个字符串,然后会查找有没有使用这个字符串作为名称的 Symbol 值,如有有,就返回这个 Symbol 值,如果没有,则会以该字符串创建一个新的 Symbol 并注册到全局。并且,不论Symbol.for()在何处运行,注册的名字永远在全局环境中。

1
2
3
4
let s1 = Symbol.for("foo");
let s2 = Symbol.for("foo");

console.log(s1 === s2); // true

Symbol.keyFor()

Symbol.keyFor()接受一个 Symbol 参数,并返回这个 Symbol 注册时的 key,往往和 Symbol.for() 配合使用,因为通过 Symbol() 创建的 Symbol 并没有注册 key,只用通过 Symbol.for() 注册的 Symbol 才是有 key 的。

1
2
3
4
5
let s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo"

let s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined

上述代码中,s2并没有注册 key。

内置 Symbol 值

  • Symbol.hasInstance

  • Symbol.isConcatSpreadable

  • Symbol.species

  • Symbol.match

  • Symbol.replace

  • Symbol.search

  • Symbol.split

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

  • Symbol.toPrimitive

  • Symbol.toStringTag

  • Symbol.unscopables

参考文章

阮一峰 ES6


ES6 Symbol 用法
https://bald3r.wang/2023/07/25/Symbol用法/
作者
Allen
发布于
2023年7月25日
许可协议