如何将 JS 变量的值(而不是引用)传递给函数?

以下是我正在尝试运行的内容的简化版本:

for (var i = 0; i < results.length; i++) {
    marker = results[i];
    google.maps.event.addListener(marker, 'click', function() { 
        change_selection(i);
    }); 
}

但我发现每个侦听器都使用results.length的值(for循环终止时的值)。如何添加侦听器,以便每个侦听器在添加时都使用 i 的值,而不是对 i 的引用?


答案 1

在现代浏览器中,您可以使用 or 关键字创建块范围的变量:letconst

for (let i = 0; i < results.length; i++) {
  let marker = results[i];
  google.maps.event.addListener(marker, 'click', () => change_selection(i));
}

在较旧的浏览器中,您需要创建一个单独的作用域,通过将变量作为函数参数传递来将变量保存在其当前状态:

for (var i = 0; i < results.length; i++) {
  (function (i) {
    marker = results[i];
    google.maps.event.addListener(marker, 'click', function() { 
      change_selection(i);
    }); 
  })(i);
}

通过创建一个匿名函数并使用变量作为第一个参数来调用它,您可以按值传递给该函数并创建一个闭包。


答案 2

除了闭包之外,您还可以使用:function.bind

google.maps.event.addListener(marker, 'click', change_selection.bind(null, i));

调用时,将 in 的值作为参数传递给函数。( 用于绑定 ,在本例中不需要绑定。inullthis

function.bind由原型框架引入,并已在 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))
            );
        };
    };
}