首页 > 解决方案 > Ruby 和 JavaScript 中的符号是否具有相同的用途?

问题描述

Symbol从编程语言设计的角度来看,Ruby 和 JavaScript(也许其他一些也具有等效类型的编程语言)是否具有相同的目的?(问题 #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(..)无论参数是什么,总是返回一个新符号:

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

标签: javascriptrubytypescriptlanguage-design

解决方案


它们是彼此的对立面。RubySymbol保证它总是一样的。ECMAScriptSymbol保证它总是不同的。

RubySymbol用于表示“名称”或“标签”的Array概念,其方式与用于表示“一系列事物”的概念或String用于表示“文本”的概念的方式相同。Ruby 的Symbols 通常被描述为“不可变String的 s”,但实际上Integer它们与Strings 的距离比与 s 的距离更近。(Integers 也是不可变的,也是直接的,也是唯一的,并且Intege文字也对自己进行评估。)事实上,在早期版本的 Ruby 中,Symbols 和Fixnums(固定大小Integer的 s)密切相关,甚至可以转换为每个其他。使Symbols 更像String是一种最近(15 年)的现象。

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

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

如果您想实际重用 a Symbol,则必须确保明确“记住”它。这就是Symbol.for为您所做的:它会为您记住Symbol,并在您要求时将其返回给您。这样,它本质上实现了 Ruby 的语义Symbol,并且可以这样使用。

另一个例子是“知名Symbols”,例如Symbol.iterator. 这只是一个总是返回相同的方法Symbol ——它Symbol是不透明且不可伪造的,所以你永远无法自己重新创建它。这些方法本质上也只是Symbol为您“记住”一个特定的。

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


推荐阅读