Ruby 和 JavaScript 中的符号是否具有相同的用途?

Is symbol in Ruby and JavaScript have the same purpose?

Ruby 和 JavaScript 中的 Symbol(也许其他一些也具有等效类型的编程语言)从编程语言设计的角度来看具有相同的目的吗? (问题 #1)

我知道这两种语言都有 Symbol 类型。

Symbol 两种语言均可用于从对象中检索方法:

const a = [];
a[Symbol.iterator] // [Function: values]
a = []
a.method(:at) => #<Method: Array#at(_)>

Ruby 中的符号是唯一的:

:a.object_id => 776028
:a.object_id => 776028

在JavaScript中,用Symbol.for创建的符号保存在一个内部字典中,这使得它有点像unique:

Symbol.for('a') === Symbol.for('a') // true

但是 Symbol(..) 总是 return 一个新的符号,不管参数是什么:

// Why this is designed this way? Question #2
Symbol('a') === Symbol('a') // false

他们是彼此的对立面。 Ruby 的 Symbol 保证它 始终相同 。 ECMAScript 的 Symbol 保证它总是不同的

Ruby的Symbol用来表示“名称”或“标签”的概念,与Array用来表示的概念相同“a sequence of things”或String用来表示“文本”的概念。 Ruby 的 Symbol 通常被描述为“不可变的 String”,但实际上它们更接近 Integer 而不是 String . (Integer 也是不可变的,也是直接的,也是唯一的,并且 Intege 字面量也对它们自己求值。)事实上,在 Ruby 的早期版本中,Symbol s 和 Fixnums(固定大小 Integers)密切相关,甚至可以相互转换。让 Symbol 更像 String 的动力是最近(15 年)的现象。

ECMAScript 的 Symbol 是一个 不可伪造的令牌 。这个概念来自基于能力的安全。 Mark Miller 是基于能力的安全性和基于对象能力的安全性领域最重要的研究人员之一,也是基于 E 能力的编程语言的设计者,也是推动 ECMAScript 设计安全方面(包括领域)的 TC39 委员会成员之一和符号,所以这并不奇怪。

因为 ECMAScript Symbol 总是不同的,所以 不可能 你生成一个 Symbol 等于我的 Symbol . (这就是“不可伪造的令牌”的意思。)所以,如果我使用 Symbol 来保护对某些东西的访问,我可以 100% 确定 没有人 可以访问,除非我明确地把“我的”交给了他们SymbolSymbol 成为“访问能力”,因此成为“基于能力的安全性”。

如果您想真正重复使用 Symbol,您必须确保明确地“记住”它。这就是 Symbol.for 为您所做的:它会为您记住 Symbol,并在您需要时将其还给您。这样,它基本上实现了 Ruby 的 Symbol 的语义,并且可以那样使用。

又如“家喻户晓的Symbols”,如Symbol.iterator。这只是一个始终 returns 相同 Symbol 的方法 – Symbol 是不透明且不可伪造的,因此您永远无法自己重新创建它。这些方法本质上也只是为您“记住”特定的 Symbol

但这不是 ECMAScript 中 Symbols 的主要用例。主要用例是基于功能的安全性。 (你可以把它想象成一把钥匙,但这也是一个有缺陷的类比,因为钥匙可以被复制,而且它们可以被伪造——Symbols 不能。)