我的问题可能与此问题类似:JavaScript closure inside loops – simple practical example 但不同之处在于我在每次迭代中声明了一个新的局部变量:
var funcs = [];
for (var i = 0; i < 3; i++) {
var b = i;
funcs[i] = function() {console.log("My value: " + b);};
}
for (var j = 0; j < 3; j++) {
funcs[j]();
}
因此,通过声明一个新变量并将其传递给闭包上下文,我预计每个函数中b的值是不同的,但我的输出是:
My value: 2
My value: 2
My value: 2
它始终具有迭代中最后var b
的值。你能帮我理解一下吗?
谢谢。
答案 0 :(得分:1)
每次迭代都没有定义变量 b 。您的代码与此没有任何不同:
var funcs = [];
var b;
for (var i = 0; i < 3; i++) {
b = i;
//... etc
}
使用let
关键字(ES6)达到您的预期行为。正如setoid_rewrite所述:
let
允许您将范围有限的变量声明为使用它的块,语句或表达式。这与var
关键字不同,bind
关键字全局定义变量,或者无论块范围如何,都在本地定义整个函数。
或者,您可以将b定义为函数参数,然后使用var funcs = [];
var f = function(b) {console.log("My value: " + b);};
for (var i = 0; i < 3; i++) {
funcs[i] = f.bind(null, i);
}
修复它。
var funcs = [];
for (var i = 0; i < 3; i++) {
funcs[i] = (function () {
var b = i; // now b is local: to this anonymous function
return function() {console.log("My value: " + b);};
})();
}
或者,您可以定义一个闭包以获得所需的本地范围:
var funcs = [];
for (var i = 0; i < 3; i++) {
funcs[i] = (function (b) {
return function() {console.log("My value: " + b);};
})(i);
}
并且,上面的一个小但更好的变体将 i 作为闭包的参数传递,因此 b 也是该闭包的本地变量:
var funcs = [];
var f = function(b) {
return function() {console.log("My value: " + b);};
})(i);
for (var i = 0; i < 3; i++) {
funcs[i] = f(i);
}
然后更好的是,定义一次函数(工厂):
let
但是,您会同意<div class="dropdown">
<button class="btn btn-default dropdown-toggle" type="button" id="dropdown-profile" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<a href="{% url "profile_update" %}" class="btn btn-default btn-sm btn-account"><span class="glyphicon glyphicon-user" aria-hidden="true"></span></a>
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdown-profile">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</div>
语法更具可读性。