😁 作者简介:一名大四的学生,致力学习前端开发技术
⭐️个人主页:夜宵饽饽的主页
❔ 系列专栏:JavaScript小贴士
👐学习格言:成功不是终点,失败也并非末日,最重要的是继续前进的勇气
🔥前言:
这是我在整理JavaScript中觉得比较重要的基础知识,有关变量提升的,希望可以帮助到大家,欢迎大家的补充和纠正
文章目录
- 11 关于JavaScript变量提升,它导致了什么问题
- 一、前言:
- 二、变量提升的原因
- 三、函数声明的细节
- 四、为什么要变量提升
- 五、变量提升的缺点。
- 六、 最后:
11 关于JavaScript变量提升,它导致了什么问题
一、前言:
😀在介绍变量提升之前,大家可以先看一段有意思的代码:
//第一种情况
a=2
var a;
console.log(a)//第二种情况
console.log(b)
var b=3
❓这两种情况的代码,大家可以猜一下最后会输出什么呢?
👉答案是:
- 第一种情况会输出2
- 第二种情况会输出undefined
这种输出是不是出乎意料,那么到底发生了什么呢?我们接下来一起来看看今天的”主角“概念,变量提升。
⭐什么是变量提升:变量和函数声明从它们在代码中出现的位置被提升”移动“到最上面
二、变量提升的原因
JavaScript代码在执行之前引擎会首先对其进行编译,编译阶段的一部分工作就是找到所有声明,并使用合适的作用域将它们关联起来,正是因为这个机制,包含变量和函数在内的所有声明都会在任何代码被执行前首先被处理
当我们看到一个变量赋值的语句时:
var a=2
可能会认为这是一个声明,但是JavaScript实际上会将其看成两个声明:var a;和a = 2。
第一定义声明是在编译阶段进行的,第二个渎职声明会被留着原地等待执行阶段,所以代码声明和赋值是在不同阶段的。
那么现在我们来看我们上面的代码,实际会以如下形式进行处理
//第一种情况
var a
a=2
console.log(a)//第二种情况
var b
console.log(b)
b=2
所以可以得知**代码是先声明后赋值,**只有声明本身会被提升,而赋值或其他运行逻辑会留在原地
三、函数声明的细节
看完变量之后,我们来了解一下函数声明,会有一些注意点
请看如下代码:
foo()function foo(){console.log(a) //undefinedvar a=2
}
上面代码中,函数是先调用后声明的,按自上到下的逻辑理解,这样显然是不合理的,但是这样依然可以正常执行,因为函数声明也会提升。而且在函数作用域内部的变量也会被提升,提升到函数作用域的最上方
⭐每个函数作用域都会进行提升操作,提升到函数作用域的最上方
所以上面的代码可以理解为以下这种形式
function foo(){var a;console.log(a)a=2
}foo()
❗注意,函数声明会提升,但是函数表达式不会被提升,切记!切记!
⭐函数声明和变量声明都会被提升,那么是哪一个先被提升,或者说当存在函数声明和变量声明,是谁在最上方
🌱函数会首先被提升,然后才是变量
四、为什么要变量提升
变量提升主要有两个原因:
- 提高性能
- 容错率更好
- 提高性能:在js代码执行之前,会进行语法检查和编译,而且这一操作只进行一次,如果没有这一步每次代码的执行都必须重新解析一遍代码,而且在解析的过程中,还会为函数生成预编译代码,那么当代码没有改变时,会直接使用预编译中的变量和函数,所以当代码执行时就不需要进行编译了,性能当然会提高。
- 容错率更好:虽然我们应该避免先赋值再声明,我们应该有先声明再赋值的好习惯,但是再JavaScript代码执行的过程中,这种先赋值再声明的错误写法也是可以正确执行的。
五、变量提升的缺点。
变量提升虽然有一些优点,但是他也会造成一定的问题,可以来看以下代码:
//第三情况
var tmp=new Date()function fn(){console.log(tmp)if(false){var tmp='老秀才'}
}fn()
在这个函数,原本要打印出外层的tmp变量,但是因为变量提升问题,导致内层的变量被提升到函数内部作用域的最顶层,相当覆盖了外层的tmp,所以输出结果undefined
六、 最后:
🌼下面推荐的一篇文章可以补充和扩展文章中涉及的知识点 😃
- 【js作用域】JavaScript中作用域的是什么?:从编译时其承担什么角色和查询作用域中的变量的角度解析作用域