var fs = require('fs');
var files = ['./files/a', './files/b', './files/c'];
for (var i = 0; i < files.length; i++) {
fs.readFile(files[i], 'utf-8', function(err, contents) {
console.log(files[i] + ': ' + contents);
});
}
// undefined: aaaaaaaa
// undefined: bbbbbbbb
// undefined: cccccccc
for (let i = 0; i < files.length; i++) {
fs.readFile(files[i], 'utf-8', function(err, contents) {
console.log(files[i] + ': ' + contents);
});
}
// ./files/a: aaaaaaaa
// ./files/b: bbbbbbbb
// ./files/c: cccccccc
files.forEach(function(element, i) {
fs.readFile(element, 'utf-8', function(err, contents) {
console.log(files[i] + ': ' + contents);
});
});
// ./files/a: aaaaaaaa
// ./files/b: bbbbbbbb
// ./files/c: cccccccc
我建议文件的大小不同
来自酷炫的 CNodeMD
我想知道为啥会这样?是跟es6块级作用域有关吗? From Noder
第一个循环里因为var的原因i的值变为了3,所以输出的文件名是file[3]===undefined 为什么依然能获得相应文件的内容?因为给readFile传的参是按照for循环里正常的012,在readFile回调的时候i才变为3 和下面这个是一个意思
for (var i = 0; i < 3; i++) {
setTimeout((u)=>{
console.log(`${u}:${i}`);
},0,i);
}
// 0:3
// 1:3
// 2:3
再详细一点 i=0 readfile 0 开始 i=1 readfile 1 开始 i=2 readfile 2 开始 i=3 for循环结束 readfile依次完成,注意此时的i已经变为3(如果三个文件大小不同的话下面三个顺序也可能会打乱): readfile 0 读取获得 aaaaaaaa 回调 console.log file[3]:aaaaaaaa readfile 1 读取获得 bbbbbbbb 回调 console.log file[3]:bbbbbbbb readfile 2 读取获得 cccccccc 回调 console.log file[3]:cccccccc
@lei2231 var的问题在于它会变量提升,对变量的声明会提升到作用域顶部
for (var i = 0; i < files.length; i++) {
fs.readFile(files[i], 'utf-8', function(err, contents) {
console.log(files[i] + ': ' + contents);
});
}
实际上是
var i; // 把这个var改成let也不会有区别
for (i = 0; i < files.length; i++) {
fs.readFile(files[i], 'utf-8', function(err, contents) {
console.log(files[i] + ': ' + contents);
});
}
所以在回调函数那里拿到的i其实是在for外面定义的那个i(已经经过for循环变成了3)
而let不会变量提升,i只存在于for内部,它的表现和我们看到的一样,回调函数拿到的是调用readfile时的i的值 简单的说,并不是let有什么特别的功能,而是var有麻烦的特性而已
其实问题的关键就在于,第一个for
循环的var i
使 i 泄漏成了全局变量。所以在回调结束之后,i
变成了3