我是node.js的新手,所以如果我的问题不成熟,我会道歉。基本上我正在尝试迭代一系列值来执行某些操作,但我不知道为什么我会得到这些值为undefined
。
代码:
for (var i = 0; i < array.length; ++i) {
console.log(array[i]); //At this point I'm getting values without any problem
var sQ = {
_tag: array[i],
_pid: data.change_caption_post_mail,
time: data.change_caption_post_time,
};
db.collection('tags')
.find(sQ)
.count({}, function(error, numOfDocs) {
if (error) throw err;
console.log(array[i]);
//But here I'm getting values as **undefined**
});
}
答案 0 :(得分:6)
替换
var i = 0; i < array.length; ++i
通过
let i = 0; i < array.length; i++
你已经完成了。
for (let i = 0; i < array.length; i++) {
console.log(array[i]); //At this point I'm getting values without any problem
var sQ = {
_tag: array[i],
_pid: data.change_caption_post_mail,
time: data.change_caption_post_time,
};
db.collection('tags')
.find(sQ)
.count({}, function(error, numOfDocs) {
if (error) throw err;
console.log(array[i]);
// i will be array.length here in all your callbacks
});
}
scope
选中此示例以了解问题:
var
创建function scope
var funcs = []
for (var i = 0; i < 10; i++) {
funcs.push(function() {
console.log(i)
})
}
funcs.forEach(function(func) {
func()
})
&#13;
虽然您可能希望此forEach
循环导致正在打印0
到9
,但您会获得10次10
。造成这种情况的原因是使用i
关键字声明变量var
,这会创建function scope
,导致function
中的每个funcs
持有引用到相同的 i
变量。在执行forEach
循环时,先前的for
- 循环已结束且i
保持10(从上次迭代开始的9 ++)。
比较创建let
而不是block scope
的ES6&#39; function scope
在这方面的行为:
let
(ES6或正式 ES2015 )创建block scope
:
var funcs = []
for (let i = 0; i < 10; i++) {
funcs.push(function() {
console.log(i)
})
}
funcs.forEach(function(func) {
func()
})
&#13;
由于let
创建block scope
,for
循环的每次迭代都有其自己的&#34;变量i
。
IIFE
包装器如果你需要一个ES5解决方案,一个IIFE( i 立即 i nvoked f unction e xpression)包装将是要走的路:
var funcs = []
for (var i = 0; i < 10; i++) {
funcs.push((function(value) {
return function() {
console.log(value)
}
}(i)))
}
funcs.forEach(function(func) {
func()
})
&#13;
此处,i
作为参数传递给存储其自己的副本value
的每个函数。
for..in
循环也是如此:
var funcs = [],
obj = {
first: "first",
last: "last",
always: "always"
}
for (var key in obj) {
funcs.push(function() {
console.log(key)
})
}
funcs.forEach(function(func) { // outputs: "always", "always", "always"
func()
})
&#13;
同样,funcs
中的所有函数都将reference
保持为相同的key
,因为var key
创建了一个位于for..in
循环之外的函数作用域。同样,let
会产生您可能更期待的结果:
var funcs = [],
obj = {
first: "first",
last: "last",
always: "always"
}
for (let key in obj) {
funcs.push(function() {
console.log(key)
})
}
funcs.forEach(function(func) {
func()
})
&#13;
还要比较优秀的(!)书
Nicholas C. Zakas: "Understanding ES6",没有淀粉压榨,p。 8-9。
从中获取了这些例子。
答案 1 :(得分:2)
将var i = 0
更改为let i = 0
。
for (let i = 0; i < array.length; ++i) {
console.log(array[i]); //At this point I'm getting values without any problem
var sQ = {
_tag: array[i],
_pid: data.change_caption_post_mail,
time: data.change_caption_post_time,
};
db.collection('tags')
.find(sQ)
.count({}, function (error, numOfDocs) {
if (error) throw err;
console.log(array[i]);
});
}
N.B。当回调函数(function (error, numOfDocs) {...}
)正在执行时,for循环结束。如果我们在执行回调时声明var i
然后i
等于array.length
,那么array [array.length]将返回undefined。其中一个解决方案是使用ES6 let
,它将为每次迭代创建回调的块范围i
。
答案 2 :(得分:0)
问题是,在你的回调函数中, i 的引用仍然只是在调用回调时已经改变的引用。
您可以将代码更改为
for (var i = 0; i < array.length; ++i) {
(function(){
var index = i;
console.log(array[index]); //At this point I'm getting values without any problem
var sQ = {
_tag: array[index],
_pid: data.change_caption_post_mail,
time: data.change_caption_post_time,
};
db.collection('tags')
.find(sQ)
.count({}, function(error, numOfDocs) {
if (error) throw err;
console.log(array[index]);
//But here I'm getting values as **undefined**
});
})();
}
这个调整应该可以正常工作