【问题标题】:Understanding ES6 Symbols理解 ES6 符号
【发布时间】:2016-02-24 16:52:47
【问题描述】:

在语言方面,我一直在使用各种语言,从 C# 到 Lisp 到 Scala 到 Haskell,在所有支持它们的语言中,符号的作用几乎相同;也就是说,任何两个同名的符号都保证是相同的,因为它们是单例对象。

球拍:(equal? 'foo 'foo)true

普通 Lisp:(eq 'foo 'foo)true

鲁比::foo == :footrue

Scala:'foo == 'footrue

ES6:Symbol('foo') === Symbol('foo') false

符号作为单例的好处是显而易见的:您可以在地图/字典中使用它们,而不会冒着密钥不等于输入的风险,因为语言突然决定以不同的方式对它进行散列(看看你,Ruby)

那么,为什么 ECMAScript 6 对此采取了不同的方法,我该如何解决呢?

【问题讨论】:

    标签: javascript ecmascript-6 symbols


    【解决方案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?”在我看来,问题并不是真正高质量的 Stackoverflow 问题。它们并非无趣,但真正的答案只能在委员会会议记录、电子邮件或语言设计师的博客文章中找到,它们与特定的编程问题无关。
    猜你喜欢
    • 2019-05-28
    • 2016-07-19
    • 1970-01-01
    • 2011-09-11
    • 1970-01-01
    • 2012-11-14
    • 2014-04-23
    • 2010-10-05
    相关资源
    最近更新 更多