CNode

《nodejs开发指南》for与forEach之间的差别

Cceclinux发布于12 年前最后回复11 年前11 回复36453 浏览0 收藏

作者提到循环的陷阱

for( var i = 0;i<files.length;i++){
    fs.readFile(files[i],'utf-8',function (err,contents) {
        console.log(files[i] + ':' + contents);
    })
}

结果是

undefined:AAA
undefined:BBB
undefined:CCC

这个不难理解,作者建议改成这样,但是没有解释

files.forEach(function (filename) {
    fs.readFile(filename,'utf-8',function (err,contents) {
        console.log(filename+':'+contents);
    })
})

我不懂,为什么把for改成forEach就解决问题了,for与forEach本质区别在哪里

查看回复

回复 (11)

C
chjjin#1·12 年前

这是经典的js闭包问题,题主可自行查阅

Y
yorkie#2·12 年前

forEach算是FP的半成品

A
abcdabcd987#3·12 年前

这个其实跟 for 和 forEach 没什么关系,是写 javascript 闭包的一个经常犯的错误,可参考: Creating closures in loops: A common mistake

闭包会把当前的环境保存下来,原来的代码里面那个 for 创建了若干个闭包,但是每个闭包共享上下文环境 i。因为 for (很大可能)会先跑完,所以运行回调函数的时候 i 已经变成了 files.length,这时候 files[i] 因为超过数组边界,所以就 undefined 了。

写 for 其实也没问题,用 function factory 就可以。

function gencb(filename) {
    return function (err, contents) {
        if (err) //...
        console.log(filename + ':' + contents);
    };
};

for( var i = 0;i<files.length;i++){
    fs.readFile(files[i],'utf-8', gencb(files[i]))
}

这个代码因为每次闭包都不一样(包括filename),所以就正常了

W
winki#4·12 年前

for循环的时候i每次都是files.length所以找不到。 也可以这样改: for( var i = 0;i<files.length;i++){ (function(i){ fs.readFile(files[i],'utf-8',function (err,contents) { console.log(files[i] + ':' + contents); }); })(i); }

C
ceclinux#5·12 年前
L
lzyzsd#6·12 年前

使用js必然会遇见的闭包问题

S
suxianbaozi#7·11 年前

for( var i = 0;i<files.length;i++){

fs.readFile(files[i],'utf-8',function (err,contents) {  
		//这一部分是异步执行的,其实差不多等到for循环完成才会执行,所以这时候的i==files.length ,懂了吗?
		console.log(files[i] + ':' + contents);
})

}

L
liudaxingtx#8·11 年前

顶一个,很好的知识点。

B
bluenaux#9·11 年前

i 每次循环 复制一份就好啦

A
alsotang#10·11 年前

闭包啊

D
DevinXian#11·11 年前

包装一层函数(闭包)会保持当前参数,so~

参与回复
登录后即可参与回复。登录