JavaScript 深度剖析之变量、函数提升:从表面到本质
JavaScript 深度剖析之变量、函数提升:从表面到本质
前言
系列首发于公众号『前端进阶圈』 ,若不想错过更多精彩内容,请“星标”一下,敬请关注公众号最新消息。
想要彻底理解
提升
这篇文章,除非你已经理解了作用域、词法作用域、动态作用域、编译器、引擎
之间的联系,否则建议你先从之前的文章读起。在前几篇文章中提到的作用域中的变量声明出现的位置有着某种微妙的联系,而这个联系就是本篇文章所讨论的内容。
先有鸡还是先有蛋
在我们的直觉上
JavaScript
代码在执行时是一行一行执行的,其实并不完全正确,有一种情况会导致这个假设是错误的。考虑以下代码:
可能会有人认为会输出
undefined
,因为var a
声明是在a = 2;
赋值之后的,他们会自然而然地认为变量被重新赋值了,因为会被赋予默认值undefined
。但正确的输出结果为2
;再考虑另外一段代码:
鉴于上一个代码片段所表现出的某种非自上而下的行为特点,你可能会认为这段代码会输出
2
。或者还有人可能认为,由于变量a
在使用前没有事先被声明过,会抛出ReferenceError
异常。然而,两种猜测都不会,正确的输出结果为undefined
。那到底还是先有鸡还是先有蛋?到底是声明(蛋)在前,还是赋值(鸡)在前?,让我们带着这个问题接着向下看。
编译器阶段
根据前面分享的几篇文章我们可得知,引擎会在解释
JavaScript
代码之前会首先对其进行编译。而编译阶段中的一部分工作就是先找到所有的声明,并用合适的作用域将他们关联起来。因此,包括变量和函数在内的所有声明都会在任何代码被执行前首先被处理。
当你看到
var a = 2;
时,你可能会认为这是一个声明。但JavaScript
会将他们看成两个声明。var a
和a = 2;
。第一个定义声明是在编译阶段进行的
,第二个赋值声明会被留在原地等待执行阶段
。第一段代码的解析过程:
第二段代码的解析过程:
因此,
这个过程就好像变量和函数声明从他们的代码中出现的位置被"移动"到了最上面,这个过程就叫做提升。
换句话说,
先有蛋(声明)后有鸡(赋值)
只有声明本身会被提升,而赋值或其他运行逻辑会留在原地。如果提升改变了代码的执行顺序,会造成非常严重的破坏。
考虑以下代码:
根据上面两个示例代码,先不要看答案。你可以试着将上面这段代码的解析后的结果写出来,巩固实践一下。<details><summary>查看答案</summary><pre>
另外,需要注意的是,
每个作用域都会进行提升操作
。这里的foo(...)
函数自身也会在内容对var a
进行提升(并不是提升到这个程序的最上方)。再考虑以下代码:
其实并不会,知道为什么吗?可以先自己想一下,再看下面的答案:<details><summary>查看答案</summary><pre>
因此,从上面的代码中得知,函数声明会被提升,但函数表达式并不会被提升。
再考虑以下代码:
自己可以先试着写出这段代码的解析后的结果,在查看答案:<details><summary>查看答案</summary><pre>
函数优先
函数声明和变量声明都会被提升,但出现有多个 "重复" 声明的代码中是函数首先会被提升,然后才是变量。
考虑以下代码:
自己可以先试着写出这段代码的解析后的结果,再查看答案:<details><summary>查看答案</summary><pre>
再考虑以下代码:
和之前一样,可先试试自己写出解析后的结果,再查看答案:<details><summary>查看答案</summary><pre>
从上面代码可以看出,在同一个作用域内重复定义是很糟糕的,经常会导致各种奇怪的问题。
小测试:
考虑以下代码:
自己先写出解析后的结果后,再来看看自己的答案是否正确:<details><summary>查看答案</summary><pre>
小结
先有鸡(声明),后有蛋(赋值)。
记住如
var a = 2;
这段代码看起来是一个声明,但 JavaScript 引擎并不这么认为,它会将这段代码当做var a
和a = 2;
两个单独的声明来处理,第一个是在编译阶段执行的任务,第二个是在执行阶段执行的任务。重复定义的函数声明后面的会覆盖前面的。
函数声明会被提升,但函数表达式并不会被提升。
只有声明本身会被提升,而包括函数表达式的赋值在内的赋值操作并不会被提升。
特殊字符描述:
问题标注
Q:(question)
答案标注
R:(result)
注意事项标准:
A:(attention matters)
详情描述标注:
D:(detail info)
总结标注:
S:(summary)
分析标注:
Ana:(analysis)
提示标注:
T:(tips)
往期推荐:
最后:
版权声明: 本文为 InfoQ 作者【控心つcrazy】的原创文章。
原文链接:【http://xie.infoq.cn/article/aea3d0b6ad628f39ca92e01b0】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论