代码运行后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.log
logging时, 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
循环。