我正在尝试实现这样的东西,但我不确定这是否可能。 我认为 Typescript 只允许使用唯一符号,而不允许使用全局符号。 这是对的吗?
有没有更好的方法来使用全局符号?
// sample.d.ts
const mySymbol = Symbol.for('internal.symbol')
interface Sample{
[mySymbol]: string
a: number
b: number
}
// sample.js
class SampleClass implements Sample {
[mySymbol]: string
a: number
b: number
constructor(a: number, b: number){
this.a = a;
this.b = b;
this[mySymbol] = `${a}-${b}`
}
}
let mySample = new SampleClass(1, 2)
有没有办法做到这一点?mySymbol
可以(理想情况下)是一个全局符号,也可以由其他对象使用,因此如果可以做到这一点,可以单独定义它。
以下是我能够做到这一点的方法。
// misc.ts
export const mySymbol = Symbol.for('internal.symbol')
// sample.d.ts
import {mySymbol} from './misc'
export as namespace Sample
export = Sample
interface Sample{
[mySymbol]: string
a: number
b: number
}
// sample.js
class SampleClass implements Sample {
[mySymbol]: string
a: number
b: number
constructor(a: number, b: number){
this.a = a;
this.b = b;
this[mySymbol] = `${a}-${b}`
}
}
let mySample = new SampleClass(1, 2)
一旦mySymbol
导入到声明文件中,它就会变成一个模块。 因此,它需要专门与export = Sample
一起导出export as namespace Sample
. 请参阅示例模块.d.ts。
您可以导出您的符号,即
export const mySymbol = Symbol.for('internal.symbol')
然后将其导入到需要它的任何文件中。这样您就不会污染全局范围,并且只能在必要时导入它。
...我认为 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)
的每个 UNIQUE 全局键创建一个唯一的全局符号 - 从任何文件。 符号实例存储在不透明的全局空间中,就好像有一个不透明的全局映射一样:
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对Symbol.for()
的评价:
) 相反,Symbol.for() 函数创建一个在全局符号注册表列表中可用的符号。Symbol.for() 也不一定在每次调用时创建一个新符号,但首先检查注册表中是否已经存在具有给定键的符号。在这种情况下,将返回该符号。如果没有找到具有给定键的符号,Symbol.for() 将创建一个新的全局符号。
关于这些全局管理的符号的垃圾回收 -我不知道以下哪项是正确的:
当全局管理的符号不再被任何用户代码引用时(即,不包括来自不透明全局"虚拟"映射的引用),那么它可能会被垃圾回收。
创建后,全局管理的符号将保留在不透明的全局"虚拟"映射中,直到程序生命周期结束。
从用户代码"逻辑"的角度来看,两者之间没有区别 - 这完全是一个实现问题。 但是,性能(包括内存使用情况)会有所不同。 我的猜测是启用了一些垃圾收集。