思维导图
通过下面的思维导图,我们先对JavaScript的Symbol有一些基本的了解。
Symbol是什么?
和string
、number
一样,Symbol
也是一种基本数据类型。
Symbol
的作用是作为一个唯一的标识符。
Symbol的特点
Symbol没有字面量,只能用Symbol()函数创建
创建时,我们可以选择给Symbol一个描述,但这个描述只是用于调试,没有实质的作用。
代码语言:javascript复制// id 是 symbol 的一个实例化对象
let id = Symbol();
// id 是描述为 "id" 的 Symbol
let id = Symbol("id");
怎么获取这个描述呢,下面有两种方式。
代码语言:javascript复制let id = Symbol("id");
alert(id.toString()); // Symbol(id),现在它有效了
alert(id.description); // id
Symbol是唯一的
即使描述一样,两个Symbol也是不相等的。
代码语言:javascript复制let id1 = Symbol("id");
let id2 = Symbol("id");
alert(id1 == id2); // false
Symbol创建的属性,会被for-in跳过
同理,Object.keys也会跳过Symbol。
但是Object.assign拷贝时,Symbol还是会被复制。
代码语言:javascript复制let id = Symbol("id");
let user = {
name: "John",
age: 30,
[id]: 123
};
for (let key in user) alert(key); // name, age (no symbols)
Symbol.for(key)创建全局Symbol
全局Symbol,key相同的时候,值也是相同的。
Symbol.for,如果同名Symbol已存在,就返回,如果不存在,就创建一个。
代码语言:javascript复制// 从全局注册表中读取
let id = Symbol.for("id"); // 如果该 Symbol 不存在,则创建它
// 再次读取(可能是在代码中的另一个位置)
let idAgain = Symbol.for("id");
// 相同的 Symbol
alert( id === idAgain ); // true
Symbol.keyFor(sym)获取Symbol的key
如果Symbol是全局的,返回key,否则返回undefined
。
let globalSymbol = Symbol.for("name");
let localSymbol = Symbol("name");
alert( Symbol.keyFor(globalSymbol) ); // name,全局 Symbol
alert( Symbol.keyFor(localSymbol) ); // undefined,非全局
alert( localSymbol.description ); // name
Symbol的适用场景
Symbol做唯一值
Symbol做唯一值,可以替换字符串和整型(魔法数)。
代码语言:javascript复制log.levels = {
DEBUG: Symbol('debug'),
INFO: Symbol('info'),
WARN: Symbol('warn'),
};
log(log.levels.DEBUG, 'debug message');
log(log.levels.INFO, 'info message');
Symbol用于创建对象的“隐藏属性“
对象的属性的key,可以是字符串和Symbol,Symbol属性在很多情况下,是不可见的。
代码语言:javascript复制let user = { // 属于另一个代码
name: "John"
};
let id = Symbol("id");
user[id] = 1;
alert( user[id] ); // 我们可以使用 Symbol 作为键来访问数据
注意,在对象字面量中使用Symbol,需要把它用方括号括起来。
代码语言:javascript复制let id = Symbol("id");
let user = {
name: "John",
[id]: 123 // 而不是 "id":123
};
用系统Symbol来微调对象。
JavaScript内置了一些内部的系统Symbol,通过这些Symbol,我们可以修改对象的一些行为。
比如下面这个例子,我们用Symbol.ierator
重写 of
运算符。
class Collection {
*[Symbol.iterator]() {
var i = 0;
while(this[i] !== undefined) {
yield this[i];
i;
}
}
}
var myCollection = new Collection();
myCollection[0] = 1;
myCollection[1] = 2;
for(var value of myCollection) {
console.log(value); // 1, then 2
}