web前端高级JavaScript - 深度剖析JS变量提升的机制

变量提升

变量提升:在当前上下文中(全局/私有/块级),js代码自上而下执行之前,浏览器会提前处理一些事情(可以理解为词法解析的一个环节,词法解析一定要发生在代码执行之前):会把当前上下文中所有带var/function关键字的进行提前声明或定义。

  • 声明declare:如 var a;
  • 定义defined:如 a = 10;
  • 带var的只会提前声明,不定义
  • 带function的会提前声明并定义
  • 代码执行前全局上下文中带var的变量提升
console.log(a);
var a = 12;
a = 13;
console.log(a);

上面代码中执行步骤为:

  • 变量提升 - 声明变量a var a; 默认值为undefined
  • 执行console.log(a);输出undefined
  • 创建一个值12,然后再让变量a与12关联; a = 12;
  • 创建一个值13,然后再让变量a与13关联; a = 13;
  • 最后执行console.log(a);输出13
  • 代码执行前全局上下文中带function的变量提升

在调用函数func之前,该函数已经被声明并定义

func();
function func(){
	console.log('变量提升');
}
  • 全局上下文 判断体(if)中 的变量提升

不管条件是否成立,都要进行变量提升
需要注意的是:条件中带function的在新版本浏览器中只会声明不会定义,而在老版本浏览器中是即声明又定义

  • 老版本,如IE10以下:
    • var a 全局上下文中声明一个a也相当于给window加一个a属性
    • fn = 函数(声明+定义)
  • 新版本
    • var a 全局上下文中声明一个a也相当于给window加一个a属性
    • fn;只声明不定义
console.log(a);//undefined
if(!('a' in window)){
	var a = 1;
	function func(){}
}
console.log(a);//undefined
//'a' in window 检测a是否为window的属性,因为是全局声明所以a是window的属性,再取反后则条件不成立,则if里的代码不执行,所以两次都输出undefined
  • 关于变量提升的练习题
fn();
function fn(){console.log(1)}
fn();
function fn(){console.log(2)}
fn();
var fn = function {console.log(3)}
fn();
function fn(){console.log(4)}
fn();
function fn(){console.log(5)}
fn();

上面代码中最终输出结果为 5 5 5 3 3 3

  • 步骤分析:
    • 首先进行带var和function的变量提升
      fn => 1;
      fn => 2;
      var fn;此处不再处理,因为上面处理function提升时已经有变量fn了,所以这里不再处理
      fn => 4;
      fn => 5;
      变量提升以后fn对应的值是输出5
    • 然后代码开始执行
      第一次调用fn(); 输出的是5
      第二次调用fn(); 输出的是5
      第三次调用fn(); 输出的是5
      执行到var fn…时对fn进行重新赋值,因为刚才在变量提升阶段并没有对这句代码进行处理,所以fn变为输出3
      最后几次调用都是输出3
var foo = 1;
function bar(){
	if(!foo){
		var foo = 10;
	}
	console.log(foo);
}
bar();

步骤分析:

  • 首先进行全局变量提升
    • var foo
    • function bar(){ …}
  • 全局变量提升后,开始代码执行,调用bar函数
  • bar函数执行会形成一个私有的执行上下文
  • 在函数私有上下文中,初始化步骤
    • 初始化作用域链
    • 初始化this
    • 初始化arguments
    • 形参赋值
    • 变量提升: var foo; 不管判断题条件是否成立都先变量提升
  • 然后函数中的代码执行,发现foo是函数的私有变量,并且只声明没赋值,所以取反后条件成立
  • 给变量foo赋值为10
  • 所以最后输出结果10
    在这里插入图片描述
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值