JavaScript中关闭的奇怪行为

时间:2014-04-17 14:52:14

标签: javascript

以下程序以意外方式执行。这究竟是为什么?基于闭包返回对i的引用而不是i的值的事实,我有一些模糊的理解。由于最后i的值为3,因此它将全部应用这些值。

function idCreator (peopleList) {
    var i;
    var uniqueID = 100;
    for (i = 0; i < peopleList.length; i++) {
      peopleList[i]["id"] = function ()  {
        return uniqueID + i;
      }
    }
    return peopleList;
}

var myFriends = [{name:"ABC", id:0}, {name:"PQR", id:0}, {name:"XYZ", id:0}];

var createIdForMyFriends = idCreator (myFriends);

var abcID = myFriends [0];
console.log(abcID.id()); // 103

4 个答案:

答案 0 :(得分:3)

问题是你在循环中创建的每个闭包都引用了相同的变量i;函数执行时i的值不一定是创建闭包时的值。 (在你的情况下,当循环终止时它将是i的值,即3)。你可以使用一个返回闭包的单独函数来解决这个问题:

function idCreator (peopleList) {
    var i;
    var uniqueID = 100;
    for (i = 0; i < peopleList.length; i++) {
      peopleList[i]["id"] = closureCreator(i);
    }
    return peopleList;
}

function closureCreator(i) {
    return function ()  {
        return uniqueID + i;
    };
}

这是使用IIFE的方式:

peopleList[i]["id"] = (function(loop_i) {
    return function()  {
        return uniqueID + loop_i;
    };
)(i));

答案 1 :(得分:2)

for (i = 0; i < peopleList.length; i++) {
  peopleList[i]["id"] = function ()  {
    return uniqueID + i;
  }
}

在此代码中,您正在创建的每个函数中的i引用相同的i。在运行任何这些函数之前将更改的i。当它们最终运行时,它们都将使用i的相同(最终)值。

你需要&#34;捕获&#34;每次迭代时i的值并使用它。

function idCreator (peopleList) {
    var i;
    var uniqueID = 100;

    var createFunc = function(i){
        return function(){
            return uniqueID + i;
        };
    };

    for (i = 0; i < peopleList.length; i++) {
      peopleList[i].id = createFunc(i);
    }

    return peopleList;
}

答案 2 :(得分:0)

你不需要关闭。

function idCreator (peopleList) {
    var i;
    var uniqueID = 100;
    for (i = 0; i < peopleList.length; i++) {
      peopleList[i]["id"] = uniqueID + i;
    }
    return peopleList;
}

var myFriends = [{name:"ABC", id:0}, {name:"PQR", id:0}, {name:"XYZ", id:0}];

var createIdForMyFriends = idCreator (myFriends);

var abcID = myFriends [0];
console.log(abcID.id);

如果仍然想在代码

之后使用闭包
function idCreator (peopleList) {
    var i;
    var uniqueID = 100;
    for (i = 0; i < peopleList.length; i++) {
     (function(i){
       peopleList[i]["id"] = function(){
          return uniqueID + i;
      }
     })(i);
    }
    return peopleList;
}

var myFriends = [{name:"ABC", id:0}, {name:"PQR", id:0}, {name:"XYZ", id:0}];

var createIdForMyFriends = idCreator (myFriends);

var abcID = myFriends [0];
console.log(abcID.id());

你的闭包函数总是返回i的最后一个值,因为它在for循环结束后执行;

答案 3 :(得分:-1)

变量i在您调用.id()方法时解析,而不是在定义方法时解析。所以在循环运行之后,i的值总是3,无论你调用.id()的对象是什么。