首页 > 解决方案 > 为什么以及何时会立即忽略变量声明,并在后续查询中覆盖函数声明?

问题描述

Pluralsight上关注Kyle Simpson 的Advanced JavaScript时,我遇到了这段代码,它应该证明函数声明在变量声明之前得到(预)编译:

foo();
var foo = 2;
function foo() { console.log("bar"); }
function foo() { console.log("foo"); }

(请注意,上面的代码要么输入为带有空格而不是换行符的单行,要么使用 SHIFT+ENTER 防止在输入整个代码之前立即执行。)在 Node 中输入上面整个代码的立即结果或(Chrome)控制台(并按 Enter 键)是:

  foo                                                                                                   
< undefined  

套用凯尔的解释,第一个function foo声明被第二个覆盖,因此foo输出到控制台,并且由于foo已经声明为函数,该var foo声明被(预)编译器忽略。

foo直接的结果支持了被忽视的理论,然而,随后的调查foo()显示了一个不同的故事:

> foo                                                                                                   
2                                                                                                       
> foo()                                                                                                 
Uncaught TypeError: foo is not a function                                                               
> 

有人可以解释为什么以及何时被忽略的声明var foo = 2;生效,当立即执行产生时:

  foo
< undefined  

我的理解是 JavaScript 引擎(预)编译解析步骤应该注意两个函数的声明,然后是变量的声明,按顺序,然后,在执行步骤,foo();执行尝试应该失败,因为它随后会失败,其中:Uncaught TypeError: foo is not a function- 但显然情况并非如此,因为foo将输出作为直接结果的一部分。

标签: javascript

解决方案


javascript中的变量和函数是Hoisting

如此处所写:

提升是一种 JavaScript 机制,其中变量和函数声明在代码执行之前被移动到其作用域的顶部。不可避免地,这意味着无论函数和变量在哪里声明,它们都会被移到其作用域的顶部,而不管它们的作用域是全局的还是局部的

这意味着在你写这个之后:

foo();
var foo = 2;

function foo() {
  console.log("bar");
}

function foo() {
  console.log("foo");
}

它实际上看起来像这样(这是为什么事情会以这种方式发生的非常合乎逻辑的:

var foo;

function foo() {
  console.log("bar");
}

function foo() {
  console.log("foo");
}

foo(); // this happens first
foo = 2; // this happens after

console.log(foo);


推荐阅读