JavaScript 变量提升和函数提升

前言

When we learn a new technology,we need to know what it is,why we learn it and how to use it best

今天在写代码的时候,突然发现了一个非常有意思的现象

其实就是两行代码

console.log(a);
var a = 1;

当将这两段代码运行在浏览器中时,会发现浏览器会报打印undefined,但是当我注释掉第二行后,浏览器就报错,提示a未定义
正常情况

注释第二行代码

按照我们正常的逻辑来思考,无论有没有”var a = 1“这段代码,浏览器都应该报错“a is not defined”。然而事实却不是这样的。那么为什么会这样,这其中就涉及到了JavaScript中的一个概念:变量提升

什么是变量提升

引擎在读取js代码的过程中,其实是分为两步:

1. 整个js代码的解析读取
2. 第二个步骤是执行

在js代码执行之前,浏览器的解析器在遇到var变量名和function整个函数时,变量名和函数会被提升到当前作用域的最前面。其中变量被提升到作用域的最前面的就叫做变量提升,而函数被提升到作用域的最前面的就叫做函数提升。函数提升和变量提升还是有一些区别的,在这里先好好说一下变量提升。

首先,我们要清楚两个概念,变量的声明和初始化。

变量的声明:就是定义变量,但不赋值,例如var a,就是对变量a的定义

变量的赋值:就是给变量赋值,例如 a =1。就是给变量a赋值1

而var a =1 就包括了两步:变量的定义和赋值。

ok,说完了,接下来就是思考刚刚之前的代码。为什么浏览器会打印undefined而不是打印1或者报错。

首先,浏览器在解析js代码时,会把var 变量的作用域提升到作用域的最前面,这就是变量提升。但是要记住,变量提升只会提升变量名的声明,而不会提升变量的赋值初始化。OK,这样我们就可以分析出为什么会出现这种情况

  1. 浏览器在开始解析那两段js代码时,遇见了var a = 1的代码,引擎会把变量a的作用域提升到最前面,但是不会提升变量的初始化赋值。
  2. 然后在运行这段js代码时,遇见了"console.log(a)"的代码,发现变量a已经有定义,但是还没有被赋值,因此输出undefined的值
  3. 这样就清楚了为什么会出现上述情况。
什么是函数提升

刚刚前面除了讲到了变量提升,还讲到了函数提升,什么是函数提升?

函数提升其实跟变量提升差不多,当引擎在解析js代码时,发现有函数变量的定义,就会先把这函数变量的作用域提升到整个作用域的最前面,但是函数提升是大于变量提升的

console.log(a); 

var a=1;

function a(){
    console.log(a);
}

运行结果

在这里插入图片描述

我们发现最终打印的是函数a的定义。函数提升的优先级大于变量提升的优先级,即函数提升在变量提升之上

其实只要理解下面两句话就可以掌握变量提升函数提升

  1. 变量提升只会提升变量名的声明,而不会提升变量的赋值初始化
  2. 函数提升的优先级大于变量提升的优先级,即函数提升在变量提升之上

来自这篇博客的总结:为啥要进行变量提升和函数提升

最后

其实,浏览器对于js代码的操作流程(主要是跟浏览器的js引擎有关)是造成出现变量提升和函数提升的最主要原因

浏览器对于js代码的处理,其实可以分为两步

  1. 解析(纵览js代码,做一些预处理,例如变量提升,函数提升,为了方便第二步的执行操作)
  2. 执行(从js代码第一行开始执行,一步一步执行)

或许不同浏览器的js引擎对于js代码的处理流程有可能有一些区别,但最多就是一些细节差别。或许我们有可能发现在chrome浏览器会出现变量提升,但是在其他浏览器就不会出现变量提升(我没测试过,我无法保证)

最后,附赠一张常见的各个主流浏览器的js引擎和渲染引擎
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值