...我认为 Typescript 只允许唯一符号,而不是全局符号。这是正确的吗?
所有符号都是唯一的。这是不变的。
如何界定和访问符号是另一个问题。
有两种创建符号的方法:
第一种方式:Symbol(mnemonic?:string),例如
const x = Symbol('optional name')
const y = Symbol('optional name')
assert(x!==y) // pass
每次调用Symbol(...) 都会创建一个独特的符号。
mnemonic 只是调试等的便利属性。
两个符号可以有相同的助记符,但不是相同的符号。
console.log(x.toString()) // 'Symbol(optional name)'
assert(x.toString()===y.toString()) // pass
assert(x!==y) // pass
当以这种方式创建符号时,它们只有在用户代码中被引用时才存在 - 就像其他对象一样,它们可以被垃圾回收。
第二种方式:Symbol.for(globalKey:string),例如
在文件“x.js”中,根本没有 import/require 语句
const x = Symbol.for('my.global.symbols.1')
export x
在文件 'y.js' 中,根本没有 import/require 语句
const x = Symbol.for('my.global.symbols.1')
export y
在文件'z.js'中
import {x} from './x'
import {y} from './y'
assert(x===y) // pass
const z = Symbol.for('my.global.symbols.1')
assert(x===z) // pass
在这种情况下,为从任何文件作为globalKey 参数传递给Symbol.for(globalKey:string) 的每个唯一全局键创建一个唯一全局符号。
符号实例存储在不透明的全局空间中,就好像有一个不透明的全局地图:
Symbol.for(globalKey:string):symbol{
if (globalSymbolMap.has(globalKey)
return globalSymbolMap.get(globalKey)
else{
const s=Symbol(globalKey)
globalSymbolMap.set(globalKey,s)
return s
}
}
(尽管它可能不是实际实现的方式)。
这是 MDN says about Symbol.for():
与 Symbol() 相比,Symbol.for() 函数在全局符号注册表列表中创建一个可用的符号。 Symbol.for() 也不一定在每次调用时都创建一个新符号,但首先检查具有给定键的符号是否已存在于注册表中。在这种情况下,将返回该符号。如果没有找到具有给定键的符号,Symbol.for() 将创建一个新的全局符号。
关于这些全局管理符号的垃圾回收 - 我不知道以下哪些是正确的:
从用户代码“逻辑”的角度来看,两者之间没有区别 - 这完全是一个实现问题。但是,性能(包括内存使用)会有所不同。我的猜测是启用了一些垃圾收集。