我知道在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
答案 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
循环。