前言
经过前几章的学习,相信大家已经很熟悉作用域的概念了,前几章我们介绍了关于函数作用域的相关概念,这一章我们将进一步来学习javascript编译执行过程中的特殊机制,变量提升机制
正文
变量提升
包括变量和函数在内的所有声明都会在任何代码被执行前首先被处理。当你看到 var a = 2; 时,可能会认为这是一个声明。但 JavaScript 实际上会将其看成两个声明:var a; 和 a = 2;。第一个定义声明是在编译阶段进行的。第二个赋值声明会被留在原地等待执行阶段。比如下面的例子:
实际执行的是:
变量提升的作用域
每个作用域都会进行提升操作。但是很明显的是,并不是提升到整个程序的最上方,而是所在作用域的最上方,例如:
实际执行的是:
但是函数声明会被提升,但是函数表达式却不会被提升。
这里只对foo进行了提升,bar不会提升,所以没办法对undefined进行函数调用,所以报出TypeError!
函数优先
函数声明和变量声明都会被提升。但是一个值得注意的细节(这个细节可以出现在有多个“重复”声明的代码中)是函数会首先被提升,然后才是变量。例如下面的例子:
这个例子会输出1而不是2,虽然foo变量申明在foo函数声明之后,但是以函数声明优先
小结
我们习惯将 var a = 2; 看作一个声明,而实际上 JavaScript 引擎并不这么认为。它将 var a和 a = 2 当作两个单独的声明,第一个是编译阶段的任务,而第二个则是执行阶段的任务。这意味着无论作用域中的声明出现在什么地方,都将在代码本身被执行前首先进行处理。可以将这个过程形象地想象成所有的声明(变量和函数)都会被“移动”到各自作用域的最顶端,这个过程被称为提升。