![](/img/trans.png)
[英]How to access values from <function scope>'s Closure in Chrome Developer tool's Watch panel?
[英]How to avoid access mutable variable from closure
我有一些像这样的代码:
for(var id=0; id < message.receiver.length; id++){
var tmp_id = id;
zlib.gzip(JSON.stringify(message.json), function(err, buffer){
...
pushStatusPool[message.receiver[tmp_id]] = null; // fix memory leak
delete pushStatusPool[message.receiver[tmp_id]];
...
});
}
我得到一个警告,在闭包中使用tmp_id
可能会导致问题,因为它是一个可变变量。
我怎么能避免这种情况? 我的意思是我怎么能发送一个不可变的变量来回调,因为这是一个for循环,我不能改变zlib.gzip
代码? 或者换句话说,我怎么能把一个参数传递给一个闭包?
您需要创建一个范围,以使用自执行功能正确捕获tmp_id
。 那是因为整个for循环是一个范围,意味着每次通过,你都捕获相同的变量。 因此回调将以错误的ID结束,因为temp_id
的值将在调用回调之前被更改。
我忽略(或关闭)警告,但似乎抱怨因为temp_id
是可变的,你可能会重新分配它。 那有点傻。 如果你真的想修复它,请尝试使用const
关键字而不是var
。
for(var id=0; id < message.receiver.length; id++){
(function(){
const tmp_id = id;
zlib.gzip(JSON.stringify(message.json), function(err, buffer){
...
pushStatusPool[message.receiver[tmp_id]] = null; // fix memory leak
delete pushStatusPool[message.receiver[tmp_id]];
...
});
})();
}
我遇到了同样的问题并通过将id传递给闭包来解决它稍微修改user24359的答案:
for(var id=0; id < message.receiver.length; id++){
(function(tmp_id){
zlib.gzip(JSON.stringify(message.json), function(err, buffer){
...
pushStatusPool[message.receiver[tmp_id]] = null; // fix memory leak
delete pushStatusPool[message.receiver[tmp_id]];
...
});
})(id);
}
这里简化了user24359的绝佳答案。 这是解决方案:
var object = {a:1,b:2};
for (var y in object){
(function(){const yyy = y;
setTimeout(function(){console.log(yyy)},3000);})();
}
上面的代码记录了ab并且是解决方案。 以下代码记录bb:
var object = {a:1,b:2};
for (var y in object){
setTimeout(function(){console.log(y)},3000);
}
我在量角器中遇到了同样的问题。 使用以下代码解决它 -
(function(no_of_agents){
ptor.element.all(by.repeater('agent in agents').column('displayName')).then(function(firstColumn){
console.log(i, '>>>>>Verifying the agent Name');
var agentsSorted = sortAgentsByName();
//verify the agent name
expect(firstColumn[no_of_agents].getText()).toEqual(agentsSorted[no_of_agents].name);
//now click on the agent name link
firstColumn[no_of_agents].click();
ptor.sleep(5000);
});
})(no_of_agents);
@ user24359 answer是一个很好的解决方案,但你可以简单地用let
关键字替换var
关键字。
for(var id=0;
变
for(let id=0;
详情请见此处 。
编辑 :正如HeribertoJuárez建议的那样,它只适用于支持EcmaScript6的浏览器。
在var
( tmp_id
)位于回调函数的较高范围内的循环中创建闭包是一个常见的错误 ,应该避免由于var
不是块作用域。 因此,并且因为在循环中创建的每个闭包共享相同的词法环境 ,所以当调用回调函数时,变量将始终是最后一个迭代值(即message.receiver.length - 1
作为tmp_id
)。 您的IDE检测到此行为并正确地抱怨。
为了避免这种警告,有几种解决方案:
用let
替换var
,确保每个创建的闭包在每次迭代中都定义了自己的作用域tmp_id
:
for (var id = 0; id < message.receiver.length; id++) { let tmp_id = id; zlib.gzip(JSON.stringify(message.json), function(err, buffer) { // Do something with tmp_id ... }); }
通过像gennadi.w那样利用IIFE,在每次迭代中创建一个词汇环境。
使用工厂函数( createCallback
)在每次迭代中创建一个回调函数:
const createCallback = tmp_id => function(err, buffer) { // Do something with tmp_id ... }; for (var id = 0; id < message.receiver.length; id++) { zlib.gzip(JSON.stringify(message.json), createCallback(id)); }
bind
回调函数上的变量,在它们的前面加上参数:
for (var id = 0; id < message.receiver.length; id++) { zlib.gzip(JSON.stringify(message.json), function(tmp_id, err, buffer) { // Do something with tmp_id (passed as id) ... }.bind(this, id)); }
如果可能的话,从ECMAScript 2015开始应该避免var
,因为这种容易出错的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.