rya*_*yan 116 javascript closures listener pass-by-reference pass-by-value
这是我正在尝试运行的简化版本:
for (var i = 0; i < results.length; i++) {
marker = results[i];
google.maps.event.addListener(marker, 'click', function() {
change_selection(i);
});
}
Run Code Online (Sandbox Code Playgroud)
但我发现每个监听器都使用results.length的值(for循环终止时的值).我如何添加监听器,使得每次使用i时我添加它的值,而不是对i的引用?
And*_*y E 162
在现代浏览器中,您可以使用let或const关键字来创建块范围的变量:
for (let i = 0; i < results.length; i++) {
let marker = results[i];
google.maps.event.addListener(marker, 'click', () => change_selection(i));
}
Run Code Online (Sandbox Code Playgroud)
在旧版浏览器中,您需要创建一个单独的作用域,通过将变量作为函数参数传递,将变量保存在当前状态:
for (var i = 0; i < results.length; i++) {
(function (i) {
marker = results[i];
google.maps.event.addListener(marker, 'click', function() {
change_selection(i);
});
})(i);
}
Run Code Online (Sandbox Code Playgroud)
通过创建一个匿名函数并使用变量作为第一个参数调用它,您将按值传递给函数并创建一个闭包.
bob*_*nce 35
除了闭包,您还可以使用function.bind:
google.maps.event.addListener(marker, 'click', change_selection.bind(null, i));
Run Code Online (Sandbox Code Playgroud)
i调用时,将in 的值作为参数传递给函数.(null用于绑定this,在这种情况下您不需要.)
function.bind由Prototype框架引入,并已在ECMAScript第五版中标准化.在浏览器本身都支持它之前,您可以function.bind使用闭包添加自己的支持:
if (!('bind' in Function.prototype)) {
Function.prototype.bind= function(owner) {
var that= this;
var args= Array.prototype.slice.call(arguments, 1);
return function() {
return that.apply(owner,
args.length===0? arguments : arguments.length===0? args :
args.concat(Array.prototype.slice.call(arguments, 0))
);
};
};
}
Run Code Online (Sandbox Code Playgroud)
Dav*_*och 13
关闭:
for (var i = 0, l= results.length; i < l; i++) {
marker = results[i];
(function(index){
google.maps.event.addListener(marker, 'click', function() {
change_selection(index);
});
})(i);
}
Run Code Online (Sandbox Code Playgroud)
编辑,2013年: 这些现在通常被称为IIFE