Page 143 - Node.js开发指南
P. 143

136  第 6 章  Node.js 进阶话题


                 //forloopi.js

                 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]);
                   });
                 }
             运行修改后的代码,结果如下:

                 [ 'a.txt', 'b.txt', 'c.txt' ]
                 3
                 undefined
                 [ 'a.txt', 'b.txt', 'c.txt' ]
                 3
                 undefined
                 [ 'a.txt', 'b.txt', 'c.txt' ]
                 3
                 undefined
                 看到这里是不是有点启发了呢?三次输出的 i 的值都是 3,超出了 files 数组的下标
             范围,因此 files[i]  的值就是 undefined 了。这种情况通常会在 for  循环结束时发
             生,例如  for (var i = 0; i < files.length; i++),退出循环时 i 的值就是
             files.length 的值。既然 i 的值是 3,那么说明了事实上 fs.readFile 的回调函数中
             访问到的 i 值都是循环退出以后的,因此不能分辨。而 files[i] 作为 fs.readFile 的
             第一个参数在循环中就传递了,所以文件可以被定位到,而且可以显示出文件的内容。
                 现在问题就明朗了:原因是3次读取文件的回调函数事实上是同一个实例,其中引用到
             的  i  值是上面循环执行结束后的值,因此不能分辨。如何解决这个问题呢?我们可以利用
             JavaScript 函数式编程的特性,手动建立一个闭包:

                 //forloopclosure.js

                 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);
                 }
   138   139   140   141   142   143   144   145   146   147   148