为什么 JavaScript 使用符号而不是字符串?

Why does JavaScript use Symbols instead of just strings?

"Iterables" in JavaScript 是带有 Symbol.iterator 属性 的对象。例如:

let x = { 
  [Symbol.iterator]: function * () { 
    yield * [ 1, 2, 3]; 
  } 
};

[ ...x ] // Array [ 1, 2, 3 ]

所以Symbol.iterator只是一个约定。

但是,为什么 Symbol 这个概念在 string 可以完成类似工作的情况下发明?

let x = { 
  iterator: function * () { 
    yield * [ 1, 2, 3 ]; 
  } 
};

// Invalid, but would be equivalent to [ ...x['iterator']() ]
[ ...x ] 

Symbol.iterator 是一个符号,因此您无法复制或重新创建它。这消除了您可能意外覆盖它的可能性。

我鼓励您观看 this video 关于 JavaScript 中的符号。

符号提供了一种可靠的方法来保证不会发生意外的 属性 名称冲突。字符串 属性 名称总是有可能无意中被用于完全不同的目的。保证符号实例是唯一的;不可能创建两个相互比较为 === 的 Symbol 实例。

符号在 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol

中有详细解释

特别是:

Note that Symbol("foo") does not coerce the string "foo" into a symbol. It creates a new symbol each time:

Symbol('foo') === Symbol('foo'); // false

假设我有一些数据要存储在某个 widely-visible 对象中。我可以想出一个字符串,比如 "foo",并将其用作将我的数据存储在对象中的键。稍后,我可以使用相同的字符串(hard-coded 或存储在某处)从对象中取回我的数据。

如果我们这样做,有两件事要记住:任何其他代码都可以查找我们的数据,任何其他代码都可以有意或无意地覆盖我们的数据(例如,他们恰好选择了与我们相同的字符串)。

如果我们改用符号作为键,那么其他代码就无法查找或修改数据,除非我们明确地给它们符号(例如作为参数)。这样,就不会发生冲突,因为许多不同的代码都可以使用相同的字符串(如 MDN 示例中的 "foo"),但它们总是以不同的符号结尾,因此不会发生冲突。

我们可能想要这样做的一个原因是,如果我们有一个单独的 "state" 对象,不同的代码段将对其进行修改。如果我们想让每段代码保持模块化,那么重要的是它们不会通过状态间接地相互依赖:通过使用符号,我们确保一段代码不仅不会改变其他人的一部分状态,但他们也不能依赖其他人的状态(即根据阅读某人的状态来选择要做什么)。