【问题标题】:Why does JavaScript use Symbols instead of just strings? [duplicate]为什么 JavaScript 使用符号而不是字符串? [复制]
【发布时间】:2018-09-15 12:52:35
【问题描述】:

JavaScript 中的“Iterables”是具有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 ] 

【问题讨论】:

  • 我的猜测是符号保证是唯一的并且不会导致名称冲突,也可能比字符串更有效。不过,这纯粹是我的猜测。

标签: javascript symbols


【解决方案1】:

符号在https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol有详细解释

特别是:

请注意,Symbol("foo") 不会将字符串 "foo" 强制转换为符号。它每次都会创建一个新符号:

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

假设我有一些数据想要存储在某个广泛可见的对象中。我可以想出一个字符串,比如"foo",并使用它作为将我的数据存储在对象中的键。稍后,我可以使用相同的字符串(硬编码或存储在某处)将数据从对象中取回。

如果我们这样做,有两件事要记住:任何其他代码都可以查找我们的数据,并且任何其他代码都可以有意或无意地覆盖我们的数据(例如,它们只是这样碰巧选了和我们一样的字符串)。

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

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

【讨论】:

  • “如果我们使用符号作为键,那么其他代码就无法查找或修改数据,除非我们明确地给它们符号”这并不严格。 Object.getOwnPropertySymbols 存在,因此使用符号保证不会发生恶意更改,只是意外更改。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    我鼓励您观看 this video 了解 JavaScript 中的符号。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-16
      • 1970-01-01
      • 2011-11-24
      • 2014-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多