当前位置: 代码迷 >> JavaScript >> 在初始化和调用之间重新定义函数
  详细解决方案

在初始化和调用之间重新定义函数

热度:54   发布时间:2023-06-05 14:20:04.0

为什么此警报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);

将超时设置为零并不一定意味着回调将立即运行。 控制权立即前进到下一行,您在此处返回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()时,它指向重新定义的版本,因此它将显示“ Redefined”。

您可能想知道为什么我们不能仅仅这样做:

var inner = function() { console.log('Initial'); }
var outer = function() {
    setTimeout(function() { 
       inner = function() { console.log('Redefined'); }
    }, 0);
    return inner;
}
outer();
setTimeout(inner, 1000);

但是出于同样的原因,您也会在这里得到“初始”字样。 setTimeout被称为inner仍然指向原始版本。

这是因为在执行所有其他JS之后设置了inner的值。 该函数将发送到其他堆栈,并从main堆栈中删除。 即使您将计时器设置为0毫秒 setTimeout函数将在执行所有其他JS时执行。 这是程序的执行方式:

  1. 初始化innerouter
  2. 执行outer ,并初始化f与返回值。

但是, outer()如何执行? 这是如何做:

  1. 命中setTimeout Web API,该API具有应在0毫秒后执行的功能,但它将被发送到事件循环并在以后执行。 其余代码将被执行。
  2. 点击return声明。 它将访问inner的值。 现在,请记住您的setTimeout函数尚未执行。 因此,该函数将移至原型链并找到inner inner是在Global上下文中定义的。 该值将被返回。

  3. 最后, outer()将函数返回给f ,该函数由另一个setTimeout执行。 setTimeout的函数也将发送到事件循环

现在, 事件循环有2个函数可以调用! 其中一个将重置“内部”的值,另一个将警告“初始”,但inner的值将立即更改。 警报将在定义的1秒后显示。

  相关解决方案