《nodejs开发指南》for与forEach之间的差别
发布于 11 年前 作者 ceclinux 35388 次浏览 最后一次编辑是 8 年前

作者提到循环的陷阱

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 回复

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

forEach算是FP的半成品

这个其实跟 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),所以就正常了

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); }

感谢,对闭包的理解又深了一步 也就是说forEach不存在上下文环境这个问题?

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

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);
})

}

顶一个,很好的知识点。

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

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

回到顶部