Javascript 我们可以在Typescript声明文件中使用全局符号吗?
我正在尝试实现类似的东西,但我不确定这是否可能。我认为Typescript只允许使用唯一的符号,而不允许使用全局符号。这是正确的吗 有没有更好的方法来实现使用全局符号Javascript 我们可以在Typescript声明文件中使用全局符号吗?,javascript,typescript,global-variables,global,typescript-declarations,Javascript,Typescript,Global Variables,Global,Typescript Declarations,我正在尝试实现类似的东西,但我不确定这是否可能。我认为Typescript只允许使用唯一的符号,而不允许使用全局符号。这是正确的吗 有没有更好的方法来实现使用全局符号 // sample.d.ts const mySymbol = Symbol.for('internal.symbol') interface Sample{ [mySymbol]: string a: number b: number } // sample.js class SampleClass
// 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
可以(理想情况下会)是一个全局符号,其他对象也会使用它,因此如果可以实现,可以单独定义它。您可以导出符号,即
export const mySymbol = Symbol.for('internal.symbol')
然后将其导入任何需要的文件中。这样,您就不会污染全局范围,只有在必要时才能导入它。以下是我如何做到这一点的
// 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
专门导出它。看
。。。我认为Typescript只允许使用唯一的符号,而不允许使用全局符号。这是正确的吗
所有符号都是唯一的。这是不变的
如何界定和访问符号是另一个问题
有两种方法可以创建符号:
第一种方式:符号(助记符?:字符串)
,例如
const x = Symbol('optional name')
const y = Symbol('optional name')
assert(x!==y) // pass
每次调用Symbol(…)
都会创建一个唯一的符号。
助记符
只是调试等的便利属性。
两个符号可以具有相同的助记符,而不是相同的符号
console.log(x.toString()) // 'Symbol(optional name)'
assert(x.toString()===y.toString()) // pass
assert(x!==y) // pass
当符号以这种方式创建时,它们只在用户代码中引用时才存在——就像其他对象一样,它们可以被垃圾收集
第二种方式:符号。用于(globalKey:string)
,例如
const x = Symbol('optional name')
const y = Symbol('optional name')
assert(x!==y) // pass
在文件“x.js”中,没有任何import
/require
语句
const x = Symbol.for('my.global.symbols.1')
export x
const x = Symbol.for('my.global.symbols.1')
export y
在文件“y.js”中,没有任何import
/require
语句
const x = Symbol.for('my.global.symbols.1')
export x
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的内容:
与Symbol()相反,Symbol.for()函数创建一个全局符号注册表列表中可用的符号。Symbol.for()也不一定在每次调用时都创建一个新符号,而是首先检查注册表中是否已经存在具有给定键的符号。在这种情况下,将返回该符号。如果找不到具有给定键的符号,symbol.for()将创建一个新的全局符号
关于这些全局管理符号的垃圾收集-我不知道以下哪项是正确的:
- 当任何用户代码不再引用全局管理的符号时(即,不包括来自不透明全局“虚拟”映射的引用),它可能会被垃圾收集
- 一旦创建,全局管理的符号将保留在不透明的全局“虚拟”映射中,直到程序生命周期结束
从用户代码“逻辑”的角度来看,两者之间没有区别——这完全是一个实现问题。但是,性能(包括内存使用)会有所不同。我的猜测是启用了一些垃圾收集。我希望从.d.ts文件(如类型或接口)执行此操作。但它似乎必须从常规的.ts文件导出,然后导入到.d.ts文件中?是吗?@tagyoureit d.ts文件是编译您的TypeScript文件的产品,您不应该在开发过程中直接使用它们。..d.ts文件是声明文件,在TypeScript中非常标准()是的,它们是标准的,但是在实践中,当使用捆绑程序(如webpack)时,您不需要直接使用d.ts文件。另见。我想如果你没有使用bundler,我可以理解你为什么要问这个问题。没错,我没有使用Webpack和声明文件来确保我应用程序不同部分的一致性。但你的回答确实帮助我找到了一些可行的方法。我会把它贴在下面。谢谢。这就是我在回答中所说的。导出符号,然后将其导入任何需要的文件。是的,谢谢。我仍然需要对实现进行一些挣扎(下次代码示例会更好),所以我在这里记录了它,以便其他人轻松地重新创建。