Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/456.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript I';我对两种不同的输出感到困惑,因为setTimeout是异步的,fn定义应该更新为';2';在执行回调时_Javascript_Function_Asynchronous_Callback - Fatal编程技术网

Javascript I';我对两种不同的输出感到困惑,因为setTimeout是异步的,fn定义应该更新为';2';在执行回调时

Javascript I';我对两种不同的输出感到困惑,因为setTimeout是异步的,fn定义应该更新为';2';在执行回调时,javascript,function,asynchronous,callback,Javascript,Function,Asynchronous,Callback,如果我将第二个函数表达式更改为函数声明,则两个超时都将记录“1”,这从pov中完全可以理解,但在这里,由于我们使用函数表达式,因此根据我的说法,在两个超时中执行回调时,第二个定义应覆盖第一个 var fn = function () { console.log('1'); }; setTimeout(fn, 1000); //output: 1 setTimeout(()=>{ fn();

如果我将第二个函数表达式更改为函数声明,则两个超时都将记录“1”,这从pov中完全可以理解,但在这里,由于我们使用函数表达式,因此根据我的说法,在两个超时中执行回调时,第二个定义应覆盖第一个

    var fn = function () {
      console.log('1');
    };
    
    setTimeout(fn, 1000); //output: 1
    
    setTimeout(()=>{
     fn();               
    }, 1000);  //output: 2
    
    fn = function () {
      console.log('2');
    };

这令人困惑,因为它需要深入理解js如何处理javascript

您的代码有两个超时。当第一个函数运行时,JS事件循环(处理超时函数)中的函数fn设置为以1000ms运行

此时,函数fn记录
1
,因此在事件循环中,javascript引擎将计划在1000ms内运行函数
console.log('1')

这一部分似乎显而易见。如果是这样,第二次设置超时有什么不同

好的,
()=>{fn()}
特别意味着应该找到并执行函数
fn

因此,

    setTimeout(()=>{
     fn();               
    }, 1000);
表示:1000毫秒后,应找到函数
fn
,然后执行。因此,如果同时更改了
fn
,则将执行更新版本

这与第一次设置超时不同,在第一次设置超时中,
fn
的实际内容设置为在1000ms内执行,而不是在该点被命名为“fn”的任何函数


这就是为什么第二个timeout函数将运行更新版本的
fn

这令人困惑,因为它需要深入了解js如何处理javascript

您的代码有两个超时。当第一个函数运行时,JS事件循环(处理超时函数)中的函数fn设置为以1000ms运行

此时,函数fn记录
1
,因此在事件循环中,javascript引擎将计划在1000ms内运行函数
console.log('1')

这一部分似乎显而易见。如果是这样,第二次设置超时有什么不同

好的,
()=>{fn()}
特别意味着应该找到并执行函数
fn

因此,

    setTimeout(()=>{
     fn();               
    }, 1000);
表示:1000毫秒后,应找到函数
fn
,然后执行。因此,如果同时更改了
fn
,则将执行更新版本

这与第一次设置超时不同,在第一次设置超时中,
fn
的实际内容设置为在1000ms内执行,而不是在该点被命名为“fn”的任何函数


这就是为什么第二个超时功能将运行更新版本的
fn

,因为OP特别提到: 提升是指在执行脚本之前将变量或函数声明移动到文件顶部。对于变量,只有定义向上移动,其值仍然未定义。而函数声明则挂在顶部

这里有函数表达式,它类似于变量,它们的值不会被提升。 因此,循序渐进:

在第1行中,fn获取值。 在第2行中,setTimeout获取一个要运行的函数,即fn。(以后也会执行) 在第3行中,setTimeout获取一个要运行的函数,它不是fn,而是一个调用fn的函数。 然后执行第4行,其中fn的值将改变

注意:如果两个函数表达式都是声明,那么两次都将打印2

 function fn() {
      console.log('2');
    };

由于OP特别提到了吊装: 提升是指在执行脚本之前将变量或函数声明移动到文件顶部。对于变量,只有定义向上移动,其值仍然未定义。而函数声明则挂在顶部

这里有函数表达式,它类似于变量,它们的值不会被提升。 因此,循序渐进:

在第1行中,fn获取值。 在第2行中,setTimeout获取一个要运行的函数,即fn。(以后也会执行) 在第3行中,setTimeout获取一个要运行的函数,它不是fn,而是一个调用fn的函数。 然后执行第4行,其中fn的值将改变

注意:如果两个函数表达式都是声明,那么两次都将打印2

 function fn() {
      console.log('2');
    };

在这种情况下,提升是不相关的,因为重新分配是在第二次超时运行
fn()
之前发生的。如果两者都是一个函数声明,那就很重要了(我稍后会解释)

我认为您确实了解代码中发生了什么,但只是想了解一下相同的内容:

  • 您可以声明一个函数并将其分配给
    fn
    变量
  • 在从步骤1向
    fn
    函数传递直接引用的同时,触发
    setTimeout
  • 触发第二个
    setTimeout
    并向其传递对新函数的引用,请注意,此新函数正在“关闭”该
    fn
    变量,这意味着如果在执行函数之前更改此变量,它将拾取更改
  • 使用新函数重新分配
    fn
    变量(还记得上一步的注释吗?)
  • 同步代码是finished的,所以是时候将异步代码传递回调用堆栈了
  • 我们传递给第一个超时的函数现在正在运行(记住,我们传递了一个引用)并登录
    1
  • 我们传递给第二个超时的函数现在正在运行,它“拾取”您在步骤4中对
    fn
    变量所做的更改,并执行“new”
    fn
    函数,因此
    2
    被记录到控制台
  • 现在,您提到了提升,正如您所看到的,提升在您的具体案例中并不相关,因为只有变量声明被提升,而不是赋值。然而,确实如此