var fs = require('fs');
var files = ['a.txt', 'b.txt', 'c.txt'];
for (var i = 0; i < files.length; i++) {
fs.readFile(files[i], 'utf-8', function(err, contents) {
console.log(files);
console.log(i);
console.log(files[i]);
});
}
var fs = require('fs');
var files = ['a.txt', 'b.txt', 'c.txt'];
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);
}```
书上说第一个是模块的的 `readFile` 中的回调函数一直是一个实例,第二个则是用了闭包,就创建三个实例,感觉不是很明白,麻烦解答下
用面向对象来解释: for (var i = 0; i < files.length; i++) { fs.readFile(…, function(err, contents) { console.log(i); }); } 相当于,在执行环境中,this.i = 0; for 运行了3次循环, this.i = 0; this.i = 1; this.i=2; 当最后异步回调的时候会去取用this.i === 2;
for (var i = 0; i < files.length; i++) { (function(i) { fs.readFile(…, function(err, contents) { console.log(files[i] + ': ' + contents); }); })(i); } 相当于,在执行环境中,this.i = 0; for 运行了3次循环, this.i = 0; this.i = 1; this.i=2; 但是, 在每次循环, 使用function () {} () 创建一个匿名的“对象”, 并使匿名对象的属性i 赋值为外部的i. 每个匿名“对象”的异步回调函数在匿名“对象”内的执行环境中,访问匿名“对象”的i.
关键是内存占用. for 中的i只是一个内存位置. 当function () {} () 会在内部启动一个内存占用. (每个循环会生成一个内存占用)
关于内存占用的回收: 当所处的函数环境不再对变量有引用的时候, 内存会被回收.
第一种情况你console的都是循环后的结果,因为是异步的,里面的i是无法同步访问的,所以你每次打印的i的值都是最后一次i的值。 第二种情况就是为了解决第一种情况用了function闭包,把i的值保存下来了没有被gc回收,所以可以打印每次i不同的值
提一个另外的话题,建议写法:
var fs = require('fs');
var files = ['a.txt', 'b.txt', 'c.txt'];
files.forEach(read);
function read(filename) {
fs.readFile(filename, 'utf8', function (err, content) {
if (err) return console.errror(err.stack);
console.log(content);
});
}
很多 callback hell 是可以通过提取函数来解决的。另外,array 的 forEach, map, reduce, filter 这些方法也还是挺好用的。