[英]How do I prevent an argument to a javascript function being retained by a closure?
EDIT: The context for this question is, the argument is the source string for a module being loaded which could be huge, and there are many many modules being loaded this way, and each one has a closure with the original source code of the module held within it, using memory, when its not needed or wanted. 编辑:此问题的上下文是,参数是正在加载的模块的源字符串,该字符串可能很大,并且以这种方式加载了许多模块,每个模块都有一个与模块原始源代码一起的闭包当不需要或不需要内存时,使用内存将其保留在内存中。
Specifically, I am trying to fix this https://github.com/dojo/dojo/blob/master/dojo.js#L367 code which leaks the module source into the closure. 具体来说,我正在尝试修复此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>
In the above code, if a breakpoint is placed inside the anonymous function, and the closures that exist are examined, we can see that one of the closures contains __text and arguments[0] that contains the original source code of the module as it was passed to eval_ 在上面的代码中,如果在匿名函数内部放置了一个断点,并且检查了存在的闭包,我们可以看到其中一个闭包包含__text和arguments [0],该文本原样包含模块的原始源代码传递给eval_
Here is a variation of the above: 这是上述内容的一种变体:
<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>
In this case, the closure no longer contains __text but does still contain arguments[0] with the string passed to eval_. 在这种情况下,闭包不再包含__text,但仍包含带有传递给eval_的字符串的arguments [0]。
About the best I could come up with is the following, which deletes the argument to eval_ after processing it, a side effect is that the module being defined now also appears in the closure as a variable called module. 我能想到的最好的方法是,在处理完后删除eval_的参数,其副作用是现在正在定义的模块在闭包中也显示为称为模块的变量。
<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>
Is there a better way to prevent the closure retaining a copy of the argument passed to eval_? 有没有更好的方法来防止闭包保留传递给eval_的参数的副本?
[EDIT] Completely missed the point of the question. [编辑]完全错过了问题要点。
Short answer: You cannot. 简短答案:您不能。 As you are aware, a closure maintains the environment state from which it was created;
如您所知,闭包会维护从中创建闭包的环境状态。 there's no way to "break out" of a closure scope hierarchy.
没有办法“突破”闭包作用域层次结构。
When you call m()
you are not calling it within a global context, but rather part of a chain of environments of, not only the eval_
closure but also closureTest
as well -- You can see your returned eval'ed function also has access to the i
and n
vars defined in closureTest
. 当您调用
m()
您不是在全局上下文中调用它,而是一系列环境的一部分,不仅是eval_
闭包,而且还有闭包closureTest
-您都可以看到返回的eval'ed函数也具有访问权限到closureTest
定义的i
和n
var。
So, you cannot restrict or break out of a closure. 因此,您不能限制或打破封闭。 However, if you define a new variable in your new scope with the same name as a variable from a previous closure you lose direct access to that.
但是,如果您在新作用域中定义了与先前闭包中的变量同名的新变量 ,则将无法直接访问该变量。 Therfore, your middle example is as close as you can get:
因此,您的中间示例尽可能接近:
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);
}
}
Here, your returned eval'ed function cannot access eval_
's arguments since it's own arguments
have overridden it (it does, however, still have access to i
and n
from the for loop). 在这里,您返回的eval'ed函数无法访问
eval_
的参数,因为它自己的arguments
已覆盖它(但是,确实可以从for循环访问i
和n
)。 This means, functionally, that eval'ed string cannot access the arguments passed to eval_
. 从功能上讲,这意味着评估字符串无法访问传递给
eval_
的参数。
Notes: 笔记:
eval_
's `arguments[0] . eval_
的`arguments [0]的事实 。 arguments.callee.caller.toString();
arguments.callee.caller.toString();
获取上层函数的字符串arguments.callee.caller.toString();
etc. This still doesn't allow the function direct access to redefined vars, but thought it was worth mentioning.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.