Javascript 如何将 JS 变量的值(不是引用)传递给函数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2568966/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I pass the value (not the reference) of a JS variable to a function?
提问by ryan
Here is a simplified version of something I'm trying to run:
这是我尝试运行的简化版本:
for (var i = 0; i < results.length; i++) {
marker = results[i];
google.maps.event.addListener(marker, 'click', function() {
change_selection(i);
});
}
but I'm finding that every listener uses the value of results.length (the value when the for loop terminates). How can I add listeners such that each uses the value of i at the time I add it, rather than the reference to i?
但我发现每个侦听器都使用 results.length 的值(for 循环终止时的值)。如何添加侦听器,以便每个侦听器在添加时都使用 i 的值,而不是对 i 的引用?
回答by Andy E
In modern browsers, you can use the letor constkeywords to create a block-scoped variable:
在现代浏览器中,您可以使用letorconst关键字来创建块范围变量:
for (let i = 0; i < results.length; i++) {
let marker = results[i];
google.maps.event.addListener(marker, 'click', () => change_selection(i));
}
In older browsers, you need to create a separate scope that saves the variable in its current state by passing it as a function parameter:
在较旧的浏览器中,您需要创建一个单独的作用域,通过将变量作为函数参数传递来将其保存在当前状态:
for (var i = 0; i < results.length; i++) {
(function (i) {
marker = results[i];
google.maps.event.addListener(marker, 'click', function() {
change_selection(i);
});
})(i);
}
By creating an anonymous function and calling it with the variable as the first argument, you're passing-by-value to the function and creating a closure.
通过创建匿名函数并使用变量作为第一个参数调用它,您将按值传递给函数并创建一个闭包。
回答by bobince
As well as the closures, you can use function.bind:
除了闭包,您还可以使用function.bind:
google.maps.event.addListener(marker, 'click', change_selection.bind(null, i));
passes the value of iin as an argument to the function when called. (nullis for binding this, which you don't need in this case.)
i调用时将 in的值作为参数传递给函数。(null用于 binding this,在这种情况下您不需要。)
function.bindwas introduced by the Prototype framework and has been standardised in ECMAScript Fifth Edition. Until browsers all support it natively, you can add your own function.bindsupport using closures:
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))
);
};
};
}
回答by David Murdoch
回答by ajm
You're winding up with a closure. Here's an article on closuresand how to work with them. Check out Example 5 on the page; that's the scenario you're dealing with.
你即将结束。这是一篇关于闭包以及如何使用它们的文章。查看页面上的示例 5;这就是你正在处理的场景。
EDIT: Four years later, that link is dead. The root of the issue above is that the forloop forms closures (specifically on marker = results[i]). As markeris passed into addEventListener, you see the side effect of the closure: the shared "environment" is updated with each iteration of the loop, before it's finally "saved" via the closure after the final iteration. MDN explains this very well.
编辑:四年后,该链接已失效。上述问题的根源在于for循环形成了闭包(特别是在 上marker = results[i])。当marker传入 时addEventListener,您会看到闭包的副作用:共享的“环境”随着循环的每次迭代而更新,然后在最终迭代之后通过闭包最终“保存”。MDN 很好地解释了这一点。
回答by user3647947
for (var i = 0; i < results.length; i++) {
marker = results[i];
google.maps.event.addListener(marker, 'click', (function(i) {
return function(){
change_selection(i);
}
})(i));
}
回答by Ken
I think we can define a temporary variable to store the value of i.
我认为我们可以定义一个临时变量来存储 i 的值。
for (var i = 0; i < results.length; i++) {
var marker = results[i];
var j = i;
google.maps.event.addListener(marker, 'click', function() {
change_selection(j);
});
}
I haven't tested it though.
不过我还没有测试过。

