如何防止闭包保留javascript函数的参数?
编辑:这个问题的上下文是,参数是正在加载的模块的源字符串,可能很大,并且有许多模块以这种方式加载,每个模块都有一个闭包,其中包含模块的原始源代码,在不需要或不需要时使用内存。如何防止闭包保留javascript函数的参数?,javascript,closures,Javascript,Closures,编辑:这个问题的上下文是,参数是正在加载的模块的源字符串,可能很大,并且有许多模块以这种方式加载,每个模块都有一个闭包,其中包含模块的原始源代码,在不需要或不需要时使用内存。 <script> function closureTest(n) { function eval_(__text) { return eval(__text); } for (var i = 0; i < n; i++) { var m = eval
<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>
具体来说,我正在尝试修复将模块源代码泄漏到闭包中的代码。
<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>
功能关闭测试(n){
函数求值(文本){
返回eval(文本);
}
对于(变量i=0;i
在上面的代码中,如果在匿名函数中放置断点,并检查存在的闭包,我们可以看到其中一个闭包包含_文本和参数[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>
功能关闭测试(n){
函数求值(){
返回eval(参数[0]);
}
对于(变量i=0;i
在本例中,闭包不再包含_文本,但仍然包含传递给eval__的字符串的参数[0]
我能想到的最好的方法是下面的方法,它删除了eval_uu的参数。在处理它之后,一个副作用是,正在定义的模块现在也作为一个名为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>
功能关闭测试(n){
函数求值(){
var模块=eval(参数[0]);
删除参数[0];
返回模块;
}
对于(变量i=0;i
有没有更好的方法来防止闭包保留传递给eval_979;的参数副本?[EDIT]完全没有抓住问题的关键。
<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>
简短回答:您不能。正如您所知,闭包维护创建它的环境状态;没有办法“突破”闭包范围层次结构
当您调用m()
时,您并不是在全局上下文中调用它,而是在一系列环境中调用它,不仅是eval\uu
闭包,还有closureTest
——您可以看到返回的eval'ed函数还可以访问closureTest
中定义的i
和n
变量
因此,您不能限制或打破闭包。但是,如果您在新范围中定义了一个与以前闭包中的变量同名的新变量,您将无法直接访问该变量。因此,您的中间示例尽可能接近:
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);
}
}
功能关闭测试(n){
函数求值(){
返回eval(参数[0]);
}
对于(变量i=0;i
在这里,返回的eval'ed函数无法访问eval\uu
的参数,因为它自己的参数已经覆盖了它(但是,它仍然可以从for循环访问i
和n
)。这意味着,从功能上讲,求值字符串不能访问传递给eval\uu
的参数
注:
- 是的,当您在DevTools中设置断点时,您可以检查父闭包,但这不会影响执行函数无法直接访问
eval\ucode>的`参数[0]这一事实
- 此外,该函数还可以使用
arguments.callee.caller.toString()获取上层函数的字符串代码>等等。这仍然不允许函数直接访问重新定义的变量,但认为值得一提
我不完全确定您在这里想要完成什么。为什么要删除参数[0]
?你能提供更多的细节吗?谢谢这是一件非常奇怪的事情,我们需要在问题中提供一些上下文。为什么要直接使用eval_uu函数而不是本机eval函数?您是否计划在该函数上实现更多逻辑?您错过了问题的重点,忘记了返回的值,问题的重点是如何避免传递给eval的源代码保留在closureNice答案中,但我不想隐藏参数,我想释放它,从内存中释放它。我应该在问题中说得更清楚。