0

我正在测试 node.js 中的回调机制,以查看触发回调的上下文。在运行以下代码时,我注意到一个奇怪的行为,我想知道你是否能解释一下:

var outID =2;

var closure = function (){
    var that = {};
    that.id = 1;
    outID = 3; //if line is commented out outID will always be 2.
    that.inside  = function(cb){
        console.log("level 0");
        console.log("thatID:" +that.id);
        console.log("outID:" +outID);
        setTimeout(function(){
            console.log("level 1");
            console.log("thatID:" +that.id);
            console.log("outID:" +outID);
            setTimeout(function(){
                setTimeout(cb,0,that.id);
            },0);
        }, 0);
    };
    return that;
};
var level3  = function(id){
    console.log("level 100S");
    console.log("id " + id);
    console.log(outID); // --- Interesting value is 3.
};
var cl = new closure();
cl.inside(level3);

输出是:

node: no process found
level 0
thatID:1
outID:3
level 1
thatID:1
outID:3
level 100S
id 1
3
[Finished in 0.1s]

为什么最后一个值是 3 而不是 2 ?

4

1 回答 1

2

outIDvar在顶级范围内声明(即使用关键字),并且从未在任何其他(函数)范围内重新声明。这意味着当它被分配到任何地方时,它正在写入同一个变量,而当它被引用时,它在任何地方都从同一个变量中读取。

为了防止outID=3内部函数中的行更改最后打印的值,您可以将其更改为var outID=3.

编辑:

发布的代码具有以下范围:

global 
    closure
         that.inside
             $anonymous1 (outer setTimeout argument)
                  $anonymous2 (inner setTimeout callback)
    level3

正如希望更清楚的那样,函数作用域继承自定义它的作用域,而不是调用它的作用域。当然,您可能会将范围与 的值混为一谈this,这是另一回事...

于 2012-09-07T21:12:36.037 回答