运行代码后字符串更改

时间:2014-09-04 03:22:32

标签: javascript node.js

我知道在javascript中通过引用复制对象,但这很奇怪。

var project = projects[projectIndex];

var projectName = project[0]["repository"]["name"];
console.log("type" + " of name " + projectName + " in " + ownerFolderName);

projectTasks.push(function(callback){
    omnifocus.create_folder_if_possible_in_group(projectName, ownerFolderName, function () {
      callback();
    });
});

在此代码段中循环运行多次。使用projectName登录时console.log是正确的。但是,在匿名函数(projectTasks)中使用时,值始终与最后一项相同的值。

例如:如果它循环三次,它将记录“1”,“2”,“3”(这是正确的)。但是,在匿名函数中,它将以“3”值运行三次。

此处提供完整代码:https://github.com/gcamp/github-omnifocus-sync/blob/master/index.js

2 个答案:

答案 0 :(得分:3)

这是标准的关闭问题。

您有一个名为projectName的变量。您在访问此变量的循环中定义函数。但是这些函数在定义时没有使用变量的值 - 它们将在调用点使用变量的值。因为您在循环中遍历项目并在过程中更改projectName,所以在调用函数时,该值是循环中的最后一个值。

解决此问题的标准方法是使用IIFE在每个循环的基础上限制变量:

for (var projectIndex in projects) {
    var project = projects[projectIndex];

    var projectName = project[0]["repository"]["name"];
    console.log("type" + " of name " + projectName + " in " + ownerFolderName);

    (function(projectName) {
        projectTasks.push(function (callback) {
            omnifocus.create_folder_if_possible_in_group(projectName, ownerFolderName, function () {
                callback();
            });
        });
    })(projectName);
}

答案 1 :(得分:1)

“新用户”正确指出您的push函数可能是异步的,因此您在调用回调函数之前已完成for循环。

请记住,与其他与C / Java相关的语言不同,javascript中的变量的范围是功能,而不是花括号{}。因此,为了确保在循环过程中不会更改闭合变量,您需要将其值传递给函数。有很多方法可以解决这个问题,但是这里的代码不需要太多改动:

function makeCallback(projectName)
{
    return function(callback){
        omnifocus.create_folder_if_possible_in_group(
            projectName, ownerFolderName, 
            function () {
                callback();
            });
    };
}

...

var project = projects[projectIndex];

var projectName = project[0]["repository"]["name"];
console.log("type" + " of name " + projectName + " in " + ownerFolderName);

projectTasks.push(makeCallback(projectName));

另一种选择可能是使用Array.prototype.forEach()而不是for循环。