Javascript在声明新var时在循环中关闭

时间:2015-12-12 16:17:41

标签: javascript closures

我的问题可能与此问题类似: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的值。你能帮我理解一下吗?

谢谢。

1 个答案:

答案 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> 语法更具可读性。