[英]Are TemplateObject arrays for tagged template literals weakly referenced by their realm?
while (c) {
tag`str0 ${e} str1`
}
JavaScript运行时创建一个冻结的数组,如Object.freeze(['str0 ', ' str1'])
但带有一个额外的.raw
属性。
是否可以将该对象用作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
}
第12.2.9.3节运行时语义:GetTemplateObject( templateLiteral )描述了如何缓存此值:
- 让领域成为当前的领域记录。
- 让templateRegistry成为领域 。[[TemplateMap]]。
所以它应该是相同的,从使用上面的循环中的tag
,这将是一个很好的属性的密钥。
在我看来,[[TemplateMap]]必须弱引用模板对象数组,否则
for (let i = 0; i < 1e6; ++i) {
eval('(() => {})`' + i + '`');
}
会泄漏记忆。
我没有在规范中看到任何内容,但是对于广泛使用的JavaScript引擎来说,标记字符串模板的WeakMap条目最终会被收集,而不是可重新进入的范围?
我问,因为我已经基于这个假设实现了一些东西 ,但还没弄清楚如何测试它。
是否可以将该对象用作WeakMap中的键,以避免每次循环时都必须基于数组重做工作?
是的,这正是你要做的事情,这是模板文字的一大特色。
在我看来,[[TemplateMap]]必须弱引用模板对象数组,否则
for (let i = 0; i < 1e6; ++i) { eval('(() => {})`' + i + '`'); }
会泄漏记忆。
它确实泄漏,因为[[TemplateMap]]
并不弱。 :(
这是对当前规范的讨论的开放点。 目前的讨论是规范是否应该改为,而不是让[[TemplateMap]]
成为全局状态,而是将其改为每个源文本位置。 例如,现在
var id = v => v;
id`tpl` === id`tpl` // true
是否可以打破这样创建两个单独的模板? 如果是这样,那么至少有可能允许您的eval
示例收集模板。
你可以在这里看到一些讨论, https://github.com/tc39/ecma262/issues/840 ,其中至少暂时可以解决这个问题。
在我看来,[[TemplateMap]]必须弱引用模板对象数组
我不知道这里实际做了什么,但是规范确实描述了[[TemplateMap]]从未被清空的领域[[TemplateMap]]。 在循环中评估许多不同的模板标签确实会严重泄漏内存,所以不要这样做 。
是否可以将该对象用作WeakMap中的键以避免重做工作?
是的,那很好。 如果全局[[TemplateMap]]确实泄漏内存,这将加剧问题,但是当它没有时,那么通过使用弱映射你不会导致问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.