一、介绍
Symbol
是ES6中新加的基本数据类型。可以用于解决对象属性名称冲突的问题,以及提供一种唯一的标识符。还是不清楚?别急,先看看下面的场景:
- 现在我要用一个
User
类来表示用户对象,每个用户对象都有一个唯一的userId
,并且我希望能够将这个对象的一些属性标记为私有属性,例如密码userPassword
。用Symbol
可以这样实现:
// 使用 Symbol 来定义私有属性和唯一标识符
const userId = Symbol('userId');
const userPassword = Symbol('userPassword');
class User {
constructor(id, password) {
this[userId] = id;
this[userPassword] = password;
}
// 公有方法可以访问私有属性
getId() {
return this[userId];
}
}
// 创建用户对象
const user1 = new User(1, 'password123');
// 无法直接访问私有属性
console.log(user1.userId); // undefined
console.log(user1.userPassword); // undefined
// 可以通过公有方法访问私有属性
console.log(user1.getId()); // 输出 1
二、用法
现在你应该可以大概感受到Symbol
的意义了,但是他的意义不止于此,可以再通过他的其他用法再来体会一下:
1. 唯一标识:
// 创建一个 Symbol 值
const mySymbol = Symbol(); // 有时候会看到Symbol('标识符'),()里面的字符串并没有实际用途,只是作为一个标识符,后期调试可能会有用处
// 使用 Symbol 作为对象属性的键
const obj = {};
obj[mySymbol] = 'Hello';
// 使用 Symbol 作为属性名
console.log(obj[mySymbol]); // 输出 'Hello'
// 创建另一个 Symbol 值
const mySymbol2 = Symbol();
// Symbol 值是唯一的
console.log(mySymbol === mySymbol2); // 输出 false
2. 不能用for…in遍历
// 接着上面的代码继续写
for (let key in obj) {
console.log(key); // 不会输出任何内容
}
// 可以使用 Object.getOwnPropertySymbols 获取所有 Symbol 属性
const symbols = Object.getOwnPropertySymbols(obj);
console.log(symbols); // 输出 [Symbol()]
3. 定义对象的属性并访问
// 创建两个不同的 Symbol
const prop1 = Symbol('prop1');
const prop2 = Symbol('prop2');
// 定义一个对象,并使用 Symbol 定义其属性
const obj = {
// 使用 Symbol 定义属性1
[prop1]: 'value1',
// 使用 Symbol 定义属性2
[prop2]: 'value2'
};
// 访问对象的属性1和属性2
console.log(obj[prop1]); // 输出 'value1'
console.log(obj[prop2]); // 输出 'value2'
- 注意到这里的写法是有用
[]
括起来的,这是为了跟普通的属性区分开。 - 如果用
obj.prop1
访问还是会返回undefined
,因为Symbol
类型是基本类型,而点运算符操作的是一个以属性名称命名的简单标识符,不能是一个数据类型,方括号运算符后面则可以放字符型属性甚至可以放表达式。
4. Symbol自带的方法
-
Symbol.for(key):
- 这个方法接受一个字符串参数
key
,用于在全局 Symbol 注册表中查找是否存在对应键为key
的 Symbol。 - 如果存在则返回已经存在的 Symbol。
- 如果不存在则创建一个新的 Symbol,并将其注册到全局 Symbol 注册表中,以
key
作为键关联起来。 - 该方法保证了全局的唯一性,即相同的
key
会对应同一个 Symbol,可以使得你可以在不同的地方获取到同一个 Symbol。
const sym1 = Symbol.for('sharedSymbol'); const sym2 = Symbol.for('sharedSymbol'); console.log(sym1 === sym2); // 输出 true,因为它们引用了同一个 Symbol
- 这个方法接受一个字符串参数
-
Symbol.keyFor(sym):
- 这个方法接受一个 Symbol 参数
sym
,用于查找与该 Symbol 相关联的键。 - 如果该 Symbol 已经被注册过(使用
Symbol.for
方法),则返回与之关联的键。 - 如果该 Symbol 没有被注册过,则返回
undefined
。
const sym = Symbol.for('sharedSymbol'); const key = Symbol.keyFor(sym); console.log(key); // 输出 'sharedSymbol'
- 这个方法接受一个 Symbol 参数