我正在尝试实现类似的方法,但是我不确定是否有可能。我认为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
可以(并且理想情况下将是)其他对象也将使用的全局符号,因此如果可以实现,则可以单独定义它。
答案 0 :(得分:0)
您可以导出符号,即
export const mySymbol = Symbol.for('internal.symbol')
,然后将其导入任何需要的文件中。这样,您就不会污染全局范围,并且只有在必要时才可以导入它。
答案 1 :(得分:0)
这就是我能够完成此操作的方式。
// 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
专门导出它。参见sample module.d.ts。
答案 2 :(得分:0)
... 我认为 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 says about Symbol.for()
:
与 Symbol() 相比,Symbol.for() 函数在全局符号注册表列表中创建一个可用的符号。 Symbol.for() 也不一定在每次调用时都创建一个新符号,但首先检查具有给定键的符号是否已存在于注册表中。在这种情况下,将返回该符号。如果没有找到具有给定键的符号,Symbol.for() 将创建一个新的全局符号。
关于这些全局管理符号的垃圾收集 - 我不知道以下哪些是正确的:
当一个全局管理的符号不再被任何用户代码引用(即,不包括来自不透明全局“虚拟”映射的引用)时,它可能会被垃圾回收。< /p>
创建后,全局管理的符号将保留在不透明的全局“虚拟”映射中,直到程序生命周期结束。
从用户代码“逻辑”的角度来看,两者之间没有区别 - 这完全是一个实现问题。但是,性能(包括内存使用情况)会有所不同。我的猜测是启用了一些垃圾收集。