我有这样的代码:
for (var index = 1; index < args.length; index++) {
var shell = args[index];
listener.of('/' + shell.namespace || 'shotgun')
.on('connection', function (socket) {
socket.on('execute', function (cmdStr, context, options) {
console.log('Received: ' + cmdStr);
var result = shell.execute(cmdStr, context, options);
socket.emit('result', result);
});
});
}
我正在使用socket.io,我正在创建多个名称空间。 socket.io命名空间工作得很好,但在execute
回调中,对shell
的引用始终是for循环中创建的最后一个对象。我需要循环的每次迭代来保持对该迭代的shell
的引用。
答案 0 :(得分:3)
嗯,最终的答案是使用let
(ECMAScript 6或node --harmony
):
for (let index = 1; index < args.length; index++) {
let shell = args[index];
// ...
}
与此同时,您可以使用closure或其他function
范围来保留其他index
和shell
每次迭代:
function iterator(shell, index) {
listener.of('/' + shell.namespace || 'shotgun')
// ...
}
for (var index = 1; index < args.length; index++) {
iterator(args[index], index);
}
而且,如果args
是Array
,也可以使用.forEach()
来完成:
args.forEach(function (shell, index) {
listener.of('/' + shell.namespace || 'shotgun')
// ...
});
答案 1 :(得分:2)
以下是使用.bind
进行挑战的解决方案之一。
for (var index = 1; index < args.length; index++) {
var shell = args[index];
listener.of('/' + shell.namespace || 'shotgun')
.on('connection', function(socket) {
shell = this.shell;
socket.on('execute', function (cmdStr, context, options) {
console.log('Received: ' + cmdStr);
var result = shell.execute(cmdStr, context, options);
socket.emit('result', result);
});
}.bind({ shell: shell }));
}
答案 2 :(得分:2)
问题是你正在创建一个引用变量shell
的闭包,并在调用函数时评估变量,而不是在定义它时。您需要创建一个引用循环变量当前值的闭包。有几种方法,但一种方法是使用IIFE:
for (var index = 1; index < args.length; index++) {
var shell = args[index];
listener.of('/' + shell.namespace || 'shotgun')
.on('connection', (function (_shell) { return function (socket) {
socket.on('execute', function (cmdStr, context, options) {
console.log('Received: ' + cmdStr);
var result = _shell.execute(cmdStr, context, options);
socket.emit('result', result);
}; }(shell)));
});
}
注意:您可以使用相同的名称(shell
)作为IIFE的正式参数,这将隐藏外部作用域中的变量,但我重命名为_shell
以澄清发生了什么