关于js的各种变量提升机制

js中,传统声明变量是var、function;es6中是let、const、import。今天说一下前四种的异同。

let 和 const
  1. let const 都是声明一个变量,但是const声明的变量不允许指针重新指向,且const声明的时候必须赋值,否则会报错。

变量赋值本质上就是一个指针指向的过程。const变量的值如果是引用数据类型的话,那么是可以改变里面的值的(这并不会改变指针的指向)。

  1. let const 不存在变量提升,所以必须先声明后使用。

注意看报错信息
3. let const 声明的变量并不会给全局对象GO(window)增加属性。所以带声明的变量和不带声明的变量是不一样的机制,平时写的时候不要省略。

如果变量不带任何声明,则默认是给全局对象GO(window)增加属性,该变量就不会提前声明。

在这里插入图片描述
5. 同一上下文中,let不允许重复声明

let 的检测是否重复声明发生在词法解析阶段(js代码自上而下执行,浏览器会提前处理很多事情,例如词法解析—>变量提升—>代码执行 等)。一旦在词法解析这一阶段报错,js代码一行都不会执行的。

在这里插入图片描述

var 和 function
  1. var function 声明的变量都存在变量提升机制,而且function 声明的变量会提前声明+定义。
  2. 基于 var function 声明的全局变量会给全局对象GO(window)增加一个对应的私有属性,它们之间有一个映射机制(一个修改,另一个也会跟着修改)
    在这里插入图片描述
上下文中变量提升的细节点

代码执行分为:全局代码,函数中的代码,私有块的代码……不同环境下的代码执行都有着自己的上下文。

  • 细节点1:不论条件是否成立,都要进行变量提升
if(!("a" in window)){ //"a" in window 检测a是否为window的一个属性  !true =>false
    var a = 1;//变量提升
}
console.log(a);//undefined
  • 细节点2:除函数/对象的大括号外,如果大括号中出现let/const/function,则会产生块级私有上下文

块级上下文中,只有基于let/const/function声明的变量,才是块级上下文私有的

if(1 == 1){
 	var n = 12;//此时并没有形成块级私有上下文
}
consolo.log(n);//12
if(1 == 1){
	 let  n = 12;//let !!! 此时形成块级私有上下文
}
consolo.log(n);//Uncaught ReferenceError: n is not defined
if(1 == 1){
	var m = 13;//只有let/const/function声明的变量才是块级上下文私有的,所有m是全局的
 	let n = 12;//let !!! 此时形成块级私有上下文
}
console.log(m);//13
console.log(n);//Uncaught ReferenceError: n is not defined
  • 细节点3:块级上下文中,函数的变量提升

在全局中,函数此时是只声明(针对新版本浏览器);在块级私有上下文中,函数是提升声明+定义。

但是在块级私有上下文中,会把里面对function xxx(){} 这一部分代码(包括这一部分)之前的操作“映射”给全局一份,此后的代码操作就是私有的了,与全局无关。

console.log(fn);//函数在全局中只是提前声明=====> undefined
if(1 == 1){
	console.log(fn);//块级私有上下文中,函数提前声明+定义===>fn
	function fn(){//此时形成块级私有上下文。代码执行到这的时候,会私有上下文中,对fn的操作(包括这一部分代码的操作)“映射”给全局一份,此后的代码操作就是私有的了,与全局的fn没有关系
		console.log('ok');
	}
	fn = 12;
	console.log(fn);//12
}
console.log(fn);//私有上下文的对于fn的定义映射给全局一份了=====>fn
  • 细节点4:函数中,如果形参有默认值 且 函数体内有基于var/let/const声明的变量,也会形成块级私有上下文

注意里面说的两个条件哈,缺一不可!

这里形成块级私有上下文后,只有在里面(函数的大括号)中新声明的变量才是块级上下文私有的。且块级上下文的上级上下文是函数私有上下文

var x = 1;
function func(x,y = function annoymous(){x=2}){
	x = 3;//x是func的私有变量,这里改变的是func私有变量x的值
	y();
	console.log(x);//2
}
func(5)
console.log(x);//1
//这里函数有形参默认值,但是函数体内没有基于var/let/const声明的变量,所以并不满足形成块级私有上下文的条件
var x = 1;
function func(x,y = function annoymous(){x=2}){
	var x = 3;//两个条件满足了,形成块级私有上下文
	y();//y不是新声明的变量,所以y是函数上下文的变量,执行y,改变的x是函数上下文的私有变量x,和块级上下文的私有变量x没有关系
	console.log(x);//3
}
func(5)
console.log(x);//1
var x = 1;
function func(x,y = function annoymous(){x=2}){
	var x = 3;//形成块级私有上下文
	var y = function annoymous(){x=4};//y是新声明的,执行y,块级私有上下文的x变为4
	y();
	console.log(x);//4
}
func(5)
console.log(x);//1
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值