[英]why I'm getting array values as “undefined”
I'm a rookie in node.js so I apologize if my question is immature .Basically I'm trying to iterate thorough an array of values for performing certain operation but I don't know why I'm getting the values as undefined
. 我是node.js的菜鸟,所以我很抱歉我的问题还不成熟。基本上,我正在尝试遍历用于执行某些操作的一组值,但是我不知道为什么我得到的值是undefined
。
Code: 码:
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**
});
}
Replace 更换
var i = 0; i < array.length; ++i
by 通过
let i = 0; i < array.length; i++
and you're done. 到此为止。
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
问题原因:缺乏了解scope
Check this example to understand the problem: 检查此示例以了解问题:
var
creates function scope
var
创建function scope
var funcs = [] for (var i = 0; i < 10; i++) { funcs.push(function() { console.log(i) }) } funcs.forEach(function(func) { func() })
While you might expect this forEach
loop to result in number 0
to 9
being printed, instead you get ten times 10
. 尽管您可能希望此forEach
循环导致打印0
到9
,但您会得到10乘以10
。 The cause of this is the variable i
being declared using var
keyword, which creates a function scope
that leads to each function
in funcs
holding a reference to the same i
variable. 原因是使用var
关键字声明了变量i
,该变量创建了一个function scope
,该function scope
导致funcs
每个function
持有对相同 i
变量的引用 。 At the time the forEach
loop is executed, the previous for
-loop has ended and i
holds 10 (9++ from the last iteration). 在执行forEach
循环时,前一个for
循环已结束,并且i
持有10(最后一次迭代的9 ++)。
Compare how ES6's let
, which creates block scope
instead of function scope
, behaves in this regard: 比较一下ES6的let
,它创建block scope
而不是function scope
在这方面的表现:
let
(ES6 or officially ES2015 ) creates block 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() })
Because let
creates block scope
, each iteration of the for
loop has its "own" variable i
. 因为let
创建了block scope
,所以for
循环的每个迭代都有其“自己的”变量i
。
IIFE
wrapper 使用IIFE
包装器的ES5解决方案 If you need an ES5 solution, an IIFE ( i mmediately i nvoked f unction e xpression) wrapper would be the way to go: 如果你需要一个ES5液,IIFE( 我 mmediately 我 nvoked˚F结Ë上的表达)的包装将是要走的路:
var funcs = [] for (var i = 0; i < 10; i++) { funcs.push((function(value) { return function() { console.log(value) } }(i))) } funcs.forEach(function(func) { func() })
Here, i
is passed as a parameter to each function which stores its own copy value
. 在这里, i
作为参数传递给每个存储自己的副本value
。
for..in
loops: 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() })
Again, all functions in funcs
hold the reference
to the same key
because var key
creates a function scope that lives outside of the for..in
loop. 同样,在所有功能funcs
保持reference
相同的key
,因为var key
创建功能范围是生活在外面for..in
循环。 And again, let
produces the result you'd probably rather expect: 再一次, 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() })
Also compare the excellent (!) book 同时比较优秀的(!)书
Nicholas C. Zakas: "Understanding ES6" , no starch press, p. 尼古拉斯·扎卡斯(Nicholas C. Zakas):“ Understanding ES6” (不理解ES6) ,第8页。 8-9. 8-9。
from which the examples were taken. 以此为例。
Change var i = 0
to let i = 0
. 将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]);
});
} }
NB When the callback function ( function (error, numOfDocs) {...}
) is executing the for loop is finished. 注意:当回调函数( function (error, numOfDocs) {...}
)正在执行时,for循环完成。 if we declare var i
then i
is equal to array.length
when executing callback so, array[array.length] returns undefined. 如果我们声明var i
那么在执行回调时i
等于array.length
,因此array [array.length]返回未定义。 One of the solutions is to use ES6 let
which will create callback's block scope i
for each iteration. 解决方案之一是使用ES6 let
,它将为每次迭代创建回调的块作用域i
。
The problem is that in your callback function, the reference of i remains only one which is already changed by the time callback is called. 问题是在您的回调函数中, i的引用仅保留一个在调用回调时已更改的引用。
you can change your code to 您可以将代码更改为
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**
});
})();
}
it should work fine with this tweak 通过这种调整应该可以正常工作
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.