代码运行后string发生变化

我知道这些对象是通过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(); }); }); 

在这个片段中循环运行多次。 使用console.loglogging时, projectName是正确的。 但是,当用于匿名函数(在projectTasks )时,该值始终与最后一个项目的值相同。

例如:如果连续三次,则会logging“1”,“2”,“3”(这是正确的)。 但是,在匿名函数中,它将以“3”值运行三次。

完整的代码可以在这里find: https : //github.com/gcamp/github-omnifocus-sync/blob/master/index.js

这是标准的closures问题。

你有一个名为projectName的variables。 你正在定义访问这个variables的循环中的函数。 但是这些函数并没有在定义点使用variables的值 – 它们将在调用点使用variables的值。 因为您正在循环项目并更改过程中的projectName ,所以在函数被调用的时候,该值是循环中的最后一个值。

解决这个问题的标准方法是使用一个IIFE来限制每个循环的variables:

 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); } 

“新用户”正确地指出你的push函数可能是asynchronous的,所以你在调用callback函数之前完成了for循环。

请记住,与其他C / Java相关的语言不同,JavaScript中的variables被函数作用域而不是花括号{} 。 所以要确保你的闭包variables在你的循环中没有改变,你需要把它的值传递给一个函数。 有很多方法可以解决这个问题,但是这里不需要对代码进行太多改动:

 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循环。