Javascript中 let, var的变量提升问题

es6引入了let, 解决了不少原本需要用闭包解决的问题;var与let定义的变量时,其生命周期执行的过程不尽相同。

1 变量生命周期的三部曲

当程序在使用一个变量时, 它的生命周期按以下三个阶段依次进行:

  • 声明阶段(Declaration phase) : 此阶段, 在作用域中注册一个变量; //通俗的说, 就是告诉程序当前作用域有这个变量;
  • 初始化阶段(Initialization phase): 此阶段, 会为变量分配内存空间, 并会自动分配数值为 undefined;
  • 赋值阶段(Assignment phase): 此阶段, 会为完成初始化的变量分配一个指定的数值;

    : 这里说的生命周期三个阶段是一个抽象的概念, 与我们通常所说的变量声明和变量初始化可能会有些出入, 对应到代码上是这样的
// 声明阶段, 当前全局作用域中存在a变量
let a; //初始化阶段, a === undefined 
a = 0; //赋值阶段
{   
    // 开启一个块级作用域
    // 声明阶段, 当前块级作用域中存在a变量
	let a = 0; //初始化阶段 和 赋值阶段
}

2 var变量的生命周期

var变量提升: 当一个函数作用域(包括全局作用域)内, 存在用var定义的变量时, 该变量会在此作用域内所有语句执行之前完成其 声明阶段;
除此以外, 对于用var定义的变量而言, 其 声明阶段初始化阶段 保持高度耦合如图所示, 即完成声明阶段紧接着就会执行初始化阶段, 自动获得值undefined.

function test(){
    // 变量a在test作用域内所有语句之前完成声明阶段和初始化阶段, 近似看成执行
    // var a;
	console.log(a); //undefined
	var a = 0;
}
test();

var定义的变量, 其 声明阶段和初始化阶段 会被提升至所在作用域最前端执行


3 let变量的生命周期


在开始深入了解之前, 还需知道:

let声明的变量特性

  • 作用域是块级
  • 同一作用域内, 无法重复声明

关于let是否会被提升, 似乎的确存在些争议. 其实, 各位说的都有道理, 只不过是每个人对 “提升” 的定义不一样罢了. 首先, 我们来看这段代码:

console.log(a);  //ReferenceError
let a = 1;

可见, 用let定义的变量并不能在let语句之前获得数值, 即使像var的undefined也没有. 这样看来, 的确是没有"提升".

然而, 还有这样一段有趣的代码:

var a = 0;
{
	console.log(a);  //依然是 ReferenceError !
	let a;
	a = 1;
	console.log(a);  //1
}

控制台前后打印的分别是ReferenceError 和 1. 数值1不难解释, 这里就不赘述.
那么前一个抛出的"引用错误"又是什么原因呢? 如果let定义的变量没有进行"提升", 那么当其在当前块级作用域中未捕获相应数值后, 应该会循着作用域链找到全局变量a, 打印数值0才对啊?

let变量提升: 实际上, let同var类似. 当一个块级作用域内, 存在用let定义的变量时, 该变量会在此作用域内所有语句执行之前完成其 声明阶段 ;
需要注意的是!!!
用let定义的变量 声明阶段初始化阶段 是解耦的. 声明阶段位于变量所在作用域的最顶部执行, 直到let语句所在处才能执行初始化阶段. 我们将声明阶段与初始化阶段的这段区域称为 临时死区(TDZ - Temporal dead zone) , 参照 “let变量声明周期” 示意图.
因此, 也就能解释为什么会抛出ReferenceError. 块级作用域内的变量a只是在作用域顶部执行了 声明阶段, 内部处理引擎只是告诉了程序当前作用域中存在a, 并未分配其内存和数值. 而只有当a完成初始化阶段, 也就是程序运行到let所在语句才能进行正常的引用.

let定义的变量, 其 声明阶段 会被提升至所在作用域的最前端进行


4 函数声明的生命周期

函数声明的提升 : 函数会在其被定义的作用域最顶部完成声明,初始化和赋值三个阶段.
示例如下:

a();
function a(){
    console.log("我被提升了");
	a();
	function a(){console.log("我又被提升了")}
}

<!-- 
我被提升了
我又被提升了
-->

本文参考: javascript变量的生命周期

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值