1、结论先行
Symbol 是在 ES6 中新增的基础数据类型,它的主要作用是创建一个唯一的标识符,用于对象属性名的命名、常量的定义等场景。避免属性名冲突的问题。
一个 Symbol 类型的变量只是为了标记一块唯一的内存而存在的。
2、例子
① 使用 Symbol 函数可以生成一个 Symbol 类型的值
使用 Symbol() 创建一个 Symbol 类型的值并赋值给 s1 变量后,就得到了一个在内存中独一无二的值。
现在除了通过变量s1,任何人在任何作用域内都无法重新创建出这个值。
const s1 = Symbol('foo');
console.log(s1); // Symbol(foo)
console.log(typeof s1 === "symbol"); // true
// 每次调用 Symbol() 函数都会创建一个新的唯一值
console.log(Symbol() === Symbol()); // false
② 每个 Symbol 都是唯一的,可以用作对象的属性名,这样就可以避免属性名冲突的问题。
const s1 = Symbol();
const s2 = Symbol();
const obj = {
[s1]: "hello",
[s2]: "小草莓",
};
console.log(obj[s1]); // hello
console.log(obj[s2]); // 小草莓
③ Symbol 还可以用于实现一些常量或枚举值,这些值是不可修改和重复的
const Colors = {
Red: Symbol("red"),
Yellow: Symbol("yellow"),
Blue: Symbol("blue"),
};
console.log(Colors.Red); // Symbol(red)
console.log(Colors.Yellow); // Symbol(yellow)
console.log(Colors.Blue); // Symbol(blue)
由于 Symbol 是一种基础数据类型,所以它具有很高的性能和可靠性,可以用于需要高效和安全的标识符创建和使用的场景。
3、注意事项
① 不能在调用 Symbol 时使用 new 关键字
因为 Symbol 是基本数据类型,而不是对象。比如下面的写法是会报错的:
const s3 = new Symbol(); // Symbol is not a constructor
② Symbol 它不会出现在 for...in、for...of、Object.keys()、Object.getOwnPropertyNames 等遍历对象属性的方法中
const s1 = Symbol("foo");
const s2 = Symbol();
const obj = {
[s1]: "hello",
[s2]: "小草莓",
s3: "非Symbol",
};
console.log(Object.keys(obj)); // ['s3']
因此可以用来定义一些不希望被遍历到属性,例如一些内部实现细节或隐藏属性。
③ 要获取对象的所有属性符号,可以使用 ES6 中添加的 Object.getOwnPropertySymbols() 方法。
const s1 = Symbol("foo");
const s2 = Symbol();
const obj = {
[s1]: "hello",
[s2]: "小草莓",
s3: "非Symbol",
};
console.log(Object.keys(obj)); // ['s3']
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(foo), Symbol()]
4、共享 symbol
① 创建共享的 symbol
ES6 为我们提供了一个全局符号注册表,允许我们在全球范围内共享 symbol。如果我们想创建一个将被共享的 symbol,我们可以使用 Symbol.for() 方法而不是调用 Symbol() 函数。
Symbol.for() 方法接受可用于符号描述的单个参数:
let Foo = Symbol.for('foo');
Symbol.for() 方法首先在全局符号注册表中使用 foo 键搜索符号。如果有一个,它返回现有的符号。否则,Symbol.for() 方法会创建一个新符号,使用指定键将其注册到全局符号注册表,然后返回该符号。
稍后,如果我们使用相同的键调用 Symbol.for() 方法,Symbol.for() 方法将返回现有符号。
let CitizenID = Symbol.for('foo');
console.log(Foo === CitizenID); // true
在此示例中,我们使用 Symbol.for() 方法通过 foo 键查找符号。由于全局符号注册表已包含它,因此 Symbol.for() 方法返回现有符号。
② 获取与符号关联的键
要获取与符号关联的键,我们可以使用 Symbol.keyFor() 方法,如以:
console.log(Symbol.keyFor(CitizenID)); // 'foo'
如果全局符号注册表中不存在的符号,则 Symbol
.keyFor() 方法返回未定义。
let systemID = Symbol('sys');
console.log(Symbol.keyFor(systemID)); // undefined