为什么此警告Initial
而不是Redefined
:
var inner = function() { alert('Initial'); }
var outer = function() {
setTimeout(function() {
inner = function() { alert('Redefined'); }
}, 0);
return inner;
}
var f = outer();
setTimeout(f, 1000);
答案 0 :(得分:2)
将超时设置为零并不 意味着将立即运行回调。控制立即进入下一行,返回inner
。此时尚未重新定义且f
指向旧inner
,这就是您看到" Initial"的原因。
将您的代码更改为以下内容:
var inner = function() { console.log('Initial'); }
var outer = function() {
setTimeout(function() {
inner = function() { console.log('Redefined'); }
}, 0);
return inner;
}
outer();
setTimeout(function() {
inner();
}, 1000);
现在您将看到"重新定义",因为我们会调用outer
,它将在未来的某个时刻重新定义inner
。当我们在超时处理程序中调用inner()
时,它指向重新定义的版本,因此它将打印"重新定义"。
你可能想知道我们为什么不能这样做:
var inner = function() { console.log('Initial'); }
var outer = function() {
setTimeout(function() {
inner = function() { console.log('Redefined'); }
}, 0);
return inner;
}
outer();
setTimeout(inner, 1000);
但是你会得到" Initial"这也是出于同样的原因;调用setTimeout
时inner
仍然指向原始版本。
答案 1 :(得分:0)
这是因为inner
的值是在执行所有其他JS之后设置的。该函数被发送到其他堆栈并从main
堆栈中删除。即使您将计时器设置为 0 ms ;当所有其他JS执行时,将执行setTimeout函数。以下是您的程序执行方式:
inner
和outer
。outer
并使用返回值初始化f
。但outer()
如何执行?方法如下:
setTimeout
Web API,其具有应在0 ms后执行的功能,但它将被发送到事件循环,并将在稍后执行。其余的代码将被执行。点击return
声明。它将访问inner
的值。现在,请记住您的setTimeout函数尚未执行。因此,该函数将移动到原型链并找到inner
。由inner
在Global
上下文中定义。该值将被退回。
最后,outer()
将函数返回到f
,由另一个setTimeout
执行。 setTimeout
中的功能也会发送到事件循环。
现在,事件循环有两个要调用的函数!其中一个将重置内部值,另一个将提醒“初始”,但inner
的值将立即更改。警报将在定义的1秒后显示。