javascript symbol

根据规范,对象的属性键只能是字符串类型或者 Symbol 类型,到目前为止,我们只见过字符串。现在我们来看看 Symbol 能给我们带来什么好处。

1、symbol值表示唯一的标识符,即使创建了许多具有相同描述的symbol,它们的值也不相同,描述只是一个标签,不影响任何东西

let id1 = Symbol("id")

let id2 = Symbol("id")

alert(id1==id2) // false

2、symbol不会被自动转换为字符串

let id = Symbol("id")

alert(id) // Cannot convert a Symbol value to a string

这是一种防止混乱的“语言保护”,因为字符串和 Symbol 有本质上的不同,不应该意外地将它们转换成另一个。

let id = Symbol("id")

alert(id.toString())  // Symbol(id)

或者获取 symbol.description 属性,只显示描述(description):

let id = Symbol("id")

alert(id.description) // id

3、隐藏属性

Symbol 允许我们创建对象的“隐藏”属性,代码的任何其他部分都不能意外访问或重写这些属性。

let user = { // 属于另一个代码

    name: "John",

    id: '7777777777'

  };

  let id = Symbol("id");

  user[id] = 1;

  console.log(user) // {name: "John", id: '7777777777', Symbol(id): 1}

  console.log(user[id]) // 1 

  console.log(user.id) // 7777777777

使用 Symbol("id") 作为键,比起用字符串 "id" 来有什么好处呢?

因为 user 对象属于其他的代码,那些代码也会使用这个对象,所以我们不应该在它上面直接添加任何字段,这样很不安全。但是你添加的 Symbol 属性不会被意外访问到,第三方代码根本不会看到它,所以使用 Symbol 基本上不会有问题。

另外,假设另一个脚本希望在 user 中有自己的标识符,以实现自己的目的。这可能是另一个 JavaScript 库,因此脚本之间完全不了解彼此。

然后该脚本可以创建自己的 Symbol("id")

我们的标识符和它们的标识符之间不会有冲突,因为 Symbol 总是不同的,即使它们有相同的名字。

……但如果我们处于同样的目的,使用字符串 "id" 而不是用 symbol,那么 就会 出现冲突

4、对象字面量中的Symbol,如果我们要在对象字面量 {...} 中使用 Symbol,则需要使用方括号把它括起来。

let id = Symbol("id")

let user = { name: "John",[id]:123}

5、Symbol 属性不参与 for..in 循环

Object.keys(user) 也会忽略它们。这是一般“隐藏符号属性”原则的一部分。如果另一个脚本或库遍历我们的对象,它不会意外地访问到符号属性。

相反,Object.assign 会同时复制字符串和 symbol 属性:

let id = Symbol("id")

let user = { [id]: 123}

let clone = Object.assign({}, user)

alert( clone[id] ); // 123

6、全局Symbol

// 从全局注册表中读取

let id = Symbol.for("id")// 如果该 Symbol 不存在,则创建它

// 再次读取(可能是在代码中的另一个位置)

let idAgain = Symbol.for("id") // 相同的 

Symbolalert( id === idAgain ); // true

注册表内的 Symbol 被称为 全局 Symbol。如果我们想要一个应用程序范围内的 Symbol,可以在代码中随处访问 —— 这就是它们的用途。

7、Symbol.keyFor

对于全局 Symbol,不仅有 Symbol.for(key) 按名字返回一个 Symbol,还有一个反向调用:Symbol.keyFor(sym),它的作用完全反过来:通过全局 Symbol 返回一个名字。

// 通过 name 获取 Symbol

let sym = Symbol.for("name")

let sym2 = Symbol.for("id") // 通过 Symbol 获取 name

alert( Symbol.keyFor(sym) ); // name

alert( Symbol.keyFor(sym2) ); // id

Symbol.keyFor 内部使用全局 Symbol 注册表来查找 Symbol 的键。所以它不适用于非全局 Symbol。如果 Symbol 不是全局的,它将无法找到它并返回 undefined。

也就是说,任何 Symbol 都具有 description 属性。

let globalSymbol = Symbol.for("name");

let localSymbol = Symbol("name");

alert( Symbol.keyFor(globalSymbol) ); // name,全局 Symbol

alert( Symbol.keyFor(localSymbol) ); // undefined,非全局

alert( localSymbol.description ); // name

8、系统Symbol

JavaScript 使用了许多系统 Symbol,这些 Symbol 可以作为 Symbol.* 访问。我们可以使用它们来改变一些内置行为。

你可能感兴趣的:(javascript symbol)