我正在测试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?
答案 0 :(得分:2)
outID
在顶级范围内声明(即使用var
关键字),并且从不在任何其他(函数)范围内重新声明。这意味着,当它被分配到任何地方时,它会写入同一个变量,并且当它被引用时,它会从同一个变量中读取。
要保持内部函数中的outID=3
行不会更改最后打印的值,您需要将其更改为var outID=3
。
编辑:
发布的代码具有以下范围:
global
closure
that.inside
$anonymous1 (outer setTimeout argument)
$anonymous2 (inner setTimeout callback)
level3
由于希望更清楚,函数作用域继承自定义的作用域,而不是 的作用域。当然,您可能会将范围与this
的值混为一谈,这是另一个故事......