Mik*_*uel 4 javascript weakmap ecmascript-6 template-strings tagged-templates
while (c) {
tag`str0 ${e} str1`
}
Run Code Online (Sandbox Code Playgroud)
JavaScript运行时创建一个冻结的数组,Object.freeze(['str0 ', ' str1'])但具有附加.raw属性.
是否可以将该对象用作a中的键,WeakMap以避免每次循环时都必须基于数组重做工作?
const memoTable = new WeakMap
function tag(templateStrings, ...values) {
let cached = memoTable.get(templateStrings)
if (!cached) {
// Compute cached and put it in the table for next time.
}
// Do something with cached and values
}
Run Code Online (Sandbox Code Playgroud)
第12.2.9.3节运行时语义:GetTemplateObject(templateLiteral)描述了如何缓存此值:
- 让领域成为当前的领域记录.
- 让templateRegistry成为领域.[[TemplateMap]].
所以从tag上面的循环中使用它应该是相同的,这将是一个很好的属性的密钥.
在我看来,[[TemplateMap]]必须弱引用模板对象数组,否则
for (let i = 0; i < 1e6; ++i) {
eval('(() => {})`' + i + '`');
}
Run Code Online (Sandbox Code Playgroud)
会泄漏记忆.
我没有在规范中看到任何内容,但是对于广泛使用的JavaScript引擎来说,标记字符串模板的WeakMap条目最终会被收集,而不是可重新进入的范围?
我问,因为我已经基于这个假设实现了一些东西,但还没弄清楚如何测试它.
是否可以将该对象用作WeakMap中的键,以避免每次循环时都必须基于数组重做工作?
是的,这正是你要做的事情,这是模板文字的一大特色.
在我看来,[[TemplateMap]]必须弱引用模板对象数组,否则
Run Code Online (Sandbox Code Playgroud)for (let i = 0; i < 1e6; ++i) { eval('(() => {})`' + i + '`'); }会泄漏记忆.
它确实泄漏,因为[[TemplateMap]]它并不弱.:(
这是对当前规范的讨论的开放点.目前的讨论是规范是否应该改为,而不是具有[[TemplateMap]]全局状态,而是将其改为每个源文本位置.例如,现在
var id = v => v;
id`tpl` === id`tpl` // true
Run Code Online (Sandbox Code Playgroud)
是否可以打破这样创建两个单独的模板?如果是这样,那么至少有可能eval允许您的示例收集模板.
你可以在这里看到一些讨论,https://github.com/tc39/ecma262/issues/840,其中至少暂时可以解决这个问题.