javascript - 为什么以及何时会立即忽略变量声明,并在后续查询中覆盖函数声明?
问题描述
在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中的变量和函数是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);
推荐阅读
- android - 使用 Instagram 基本显示 API 时出现“无效平台应用”错误
- c++ - Arduino - PROGMEM a avr/pgmspace.h 的问题
- hyperledger-fabric - 为组织创建锚点对等点的问题
- racket - 无法在球拍 7.7 中安装 RSOUND(DrRacket 安装:在目录包中找不到包:portaudio-x86_64-windows))
- java - 使用 Spring Boot 或 Spring MVC 开发社交网络应用程序
- wordpress - Roots 在 Ubuntu 和 VituralBox 上全新安装的 Trellis 在 /srv/www/website.com/current 下缺少 composer.json
- amazon-web-services - elbv2 的 AWS cli 查询通配符
- python - Tkinter askopenfilename 路径
- c++ - 迭代位的最快方法
- dask - 如何从压缩的 .npy 文件创建 Dask 数组?