JavaScript中的变量提升

变量提升

这里先给出变量提升的定义。

1. 变量提升的定义

所谓的变量提升,是指在JavaScript代码执行的过程中,JavaScript引擎变量的声明(使用var)和函数的声明部分提升到代码开头的“行为”。

变量被提升后,会给变量设置默认值,这个默认值就是我们熟悉的undefined。变量提升是JavaScript中比较基本的知识点,只有深入理解变量提升打好JavaScrip技术基础,才能更快地排查代码执行中出现的异常。

2. 理解变量提升

2.1 JavaScript代码的执行顺序

先思考一个问题,JavaScript是按照顺序执行的吗?比如下面这样一段代码:

showMsg(); // 1
console.log(name); // 2
var name = '小明';
function showMsg () {
  console.log('吃得苦中苦');
}
复制代码

如果以上代码完全是按照顺序执行的,那么1和2的位置应该会报错,因为访问不到函数showMsg和变量name,但是实际运行这段代码发现,1位置的代码运行可以打印出吃得苦中苦的字符串,2位置的代码运行打印的结果是undefined。所以,代码并不是完全按照顺序执行的,其中肯定是发生了什么,改变了某些代码执行的顺序的。

2.2 JavaScript代码的执行流程

要搞懂这个问题,就要先了解JavaScript代码的执行流程,一段JavaScript代码在执行之前会被JavaScript引擎编译,编译完成之后,才会进入执行阶段,整个流程如下图所示。

vueresponse

JS代码经过编译后的产出是执行上下文和可执行代码。这里的执行上下文是可执行代码运行的环境,如果对执行上下去不太理解,可以参考这篇文章JavaScript的执行上下文,执行上下文包含变量环境和词法环境两部分。当JS引擎执行可执行代码时,就会去执行上下文中寻找代码运行所需要的变量。

画图演示2.1中代码的编译和执行过程如下图所示。

从上图可以看到,经过编译之后,name变量的声明和showMsg函数的声明,被放到了执行上下文中的变量环境中,并且name变量被赋值了初始值undefined,当JS引擎执行代码时,在变量环境中就会访问到变量name和函数showMsg。

2.3 相同的变量或函数如何处理

当代码中出现相同的变量或函数怎么办,如以下代码

showMsg();
console.log(name);
var name = '小明'; // 第1次,声明name变量
var name = '小王'; // 第2次,声明name变量,虽然不会报错但是这并不是好的实践
console.log(name);
function showMsg () { // 第1次,声明showMsg函数
  console.log('吃得苦中苦');
}
function showMsg () { // 第2次,声明showMsg函数,会将第一次声明的覆盖掉
  console.log('方为人上人');
}
复制代码

JavaScript允许使用var重复定义一个变量,并不会报错,但这不是好的实践,不推荐这种写法。如果定义了两个相同的函数,那么最终存放在变量环境中的是最后定义的那个函数,后面定义的函数会覆盖掉之前定义的。

3. 总结

  1. JS的执行机制是,先编译再执行,编译为执行阶段生成执行上下文和可执行代码;
  2. 在编译阶段,变量和函数会被存放到变量环境中;变量默认值是undefined,在执行阶段,JS引擎会从变量环境中去查找自定义的变量和函数;
  3. 当定义两个名称相同的函数时,后面的会覆盖掉前面的。

这里注意,被提升的变量是使用var定义的,使用let定义的变量不会被提升

核心记住这么一句话

先编译,再执行,变量函数被提升

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享