理解 ES6 符号
Posted
技术标签:
【中文标题】理解 ES6 符号【英文标题】:Understanding ES6 Symbols 【发布时间】:2016-02-24 16:52:47 【问题描述】:在语言方面,我一直在使用各种语言,从 C# 到 Lisp 到 Scala 到 Haskell,在所有支持它们的语言中,符号的作用几乎相同;也就是说,任何两个同名的符号都保证是相同的,因为它们是单例对象。
球拍:(equal? 'foo 'foo)
true
普通 Lisp:(eq 'foo 'foo)
true
鲁比::foo == :foo
true
Scala:'foo == 'foo
true
ES6:Symbol('foo') === Symbol('foo')
false
符号作为单例的好处是显而易见的:您可以在地图/字典中使用它们,而不会冒着密钥不等于输入的风险,因为语言突然决定以不同的方式对它进行散列(看看你,Ruby)
那么,为什么 ECMAScript 6 对此采取了不同的方法,我该如何解决呢?
【问题讨论】:
【参考方案1】:您可以(某种程度上)通过使用注册的(全局)符号获得符号“可识别”的效果:
var s1 = Symbol.for("foo");
var s2 = Symbol.for("foo");
s1 === s2; // true
当然,您也可以使用 Map 实例或普通对象创建自己的符号注册表。
edit — 我将补充一点,在创建新的 Symbol 实例时,可选字符串参数的目的是为程序员提供一种识别符号含义和用途的方法 。没有那个字符串,符号就可以像符号一样工作,但是如果您在调试器中转储对象,则此类匿名符号实例所键入的属性只是值。如果您使用符号键在对象上保留数字属性,那么您只会看到一些数字,这会令人困惑。与 Symbol 实例关联的描述字符串为程序员提供了参考信息,同时又不损害 Symbol 作为键值的唯一性。
最后,您始终可以比较在两个类似构造的 Symbol 实例上调用 .toString()
的结果。我怀疑这种做法会被认为是有问题的,但你当然可以这样做。
edit more — 我突然想到,javascript 中 Symbol 创建的 默认 行为使得类型 更有用,比如 Erlang 中的 atom 或 Clojure 中的键。因为该语言默认提供了一个保证唯一的值,所以命名空间冲突的基本问题得到了很好的解决。仍然可以使用“知名”符号,但是拥有可用的唯一值而不必担心与其他可能也希望避免冲突的代码发生冲突是很好的。 JavaScript 有一个有点独特,而且肯定是独一无二的普遍且无法控制的问题,即全局命名空间可能会被程序员甚至不知道存在的代码污染,因为代码可能会由于一方的行为而在浏览器环境中发生冲突,并且不为任意数量的软件架构师所知。
【讨论】:
@JaromandaX 好吧,它们没有以任何方式限定范围,但我想我知道的任何其他语言的符号都是这种情况(Erlang,Clojure,......这就是我能想到的时刻)。 这个答案没有解决“为什么”。 @BenAston “语言设计师为什么要做 X?”在我看来,问题并不是真正高质量的 *** 问题。它们并非无趣,但真正的答案只能在委员会会议记录、电子邮件或语言设计师的博客文章中找到,它们与特定的编程问题无关。 也就是说,here is a good article about Symbols.以上是关于理解 ES6 符号的主要内容,如果未能解决你的问题,请参考以下文章