重学JS-4-Symbol

2023-04-22 16:16:53 浏览数 (2)

思维导图

通过下面的思维导图,我们先对JavaScript的Symbol有一些基本的了解。

Symbol是什么?

stringnumber一样,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

代码语言:javascript复制
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 运算符。

代码语言:javascript复制
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
}

0 人点赞