node.js中的闭包是否不同?

dsi*_*ard 1 closures callback node.js

我用javascript工作了很多但是昨天我开始使用node.js. 这是一个在文件夹文件上运行jslint的小脚本.对于此示例,我将命令更改为调用ls而不是jslint.

var sys = require("sys");
var fs = require("fs");
var cp = require('child_process');

var path = fs.realpathSync("./src/");

fs.readdir(fs.realpathSync("./src/"), function(err, files) {
  for (var i = 0; i < files.length; i++) {
    var filename = files[i];
    var complete = path + filename;

    // Run jslint on each file
    var jslint = cp.exec("ls " + complete, function(error, stdout, stderr) {
      console.log(filename + " : " + stdout);
    });    
  }
});
Run Code Online (Sandbox Code Playgroud)

输出是这样的:

jskata.nofreeze.js:/home/dan/php/jskata/src/jskata.undo.js

jskata.nofreeze.js:/home/dan/php/jskata/src/jskata.nofreeze.js

jskata.nofreeze.js:/home/dan/php/jskata/src/jskata.timezone.js

为什么当文件名明显与?的结果相匹配时,console.log(filename + " : " + stdout);总是会打印该行?node.js中的闭包和作用域是否与javascript不同?jskata.nofreeze.jsls

Ivo*_*zel 13

不,它们没有任何不同,这只是JavaScript中闭包最常见的陷阱.

看,你处于一个循环中,你在循环的filename每次迭代中分配局部变量,因此你实际上覆盖了它的值.由于它始终是相同的局部变量,并且每个引用filename都有闭包,因此回调内部的值会在循环的每次迭代中获得更新.

'jskata.nofreeze.js'恰好是目录中的最后一个文件,因此它也是分配给的最后一个值filename.

要解决它,您需要传递filename 每个值的值:

// Run jslint on each file
(function(c, f) {
    cp.exec("cat " + c, function(error, stdout, stderr) {
      console.log(f + " : " + stdout);
    });
})(complete, filename);
Run Code Online (Sandbox Code Playgroud)

这使整个过程变得有效,即使它有点难看.如果你不想用更多的匿名函数来混淆你的内部循环,你当然可以把它移到一个命名函数中.