编辑:这个问题的上下文是,参数是正在加载的模块的源字符串,它可能很大,并且有很多模块以这种方式加载,每个模块都有一个带有模块原始源代码的闭包当不需要或不需要时,使用内存将其保存在其中。
具体来说,我正在尝试修复此https://github.com/dojo/dojo/blob/master/dojo.js#L367代码,该代码将模块源泄漏到闭包中。
<script>
function closureTest(n) {
function eval_(__text) {
return eval(__text);
}
for (var i = 0; i < n; i++) {
var m = eval_("(function(){ var x = 10; return function(n) { return x+n; }; })(window);");
m(5);
}
}
</script>
<button onclick="closureTest(1000)">Run</button>
在上面的代码中,如果在匿名函数中放置了一个断点,并且检查了存在的闭包,我们可以看到其中一个闭包包含 __text 和 arguments[0],其中包含模块的原始源代码传递给 eval_
以下是上述内容的变体:
<script>
function closureTest(n) {
function eval_() {
return eval(arguments[0]);
}
for (var i = 0; i < n; i++) {
var m = eval_("(function(){ var x = 10; return function(n) { return x+n; }; })(window);");
m(5);
}
}
</script>
<button onclick="closureTest(1000)">Run</button>
在这种情况下,闭包不再包含 __text,但仍然包含 arguments[0] 以及传递给 eval_ 的字符串。
我能想到的最好的方法是以下内容,它在处理后删除 eval_ 的参数,副作用是现在正在定义的模块也作为名为 module 的变量出现在闭包中。
<script>
function closureTest(n) {
function eval_() {
var module = eval(arguments[0]);
delete arguments[0];
return module;
}
for (var i = 0; i < n; i++) {
var m = eval_("(function(){ var x = 10; return function(n) { return x+n; }; })(window);");
m(5);
}
}
</script>
<button onclick="closureTest(1000)">Run</button>
有没有更好的方法来防止闭包保留传递给 eval_ 的参数副本?