js中的变量声明提升

两个小问题

问题一:输出什么?

console.log(fun)
var fun = 2
function fun (a) {
    return a
}

问题二:输出什么? 如果把var变更为let呢?

console.log(foo);
var foo = { n: 1 };

(function (foo) {
    console.log(foo);
    foo.n = 3;
    var foo = { n: 2 };
    console.log(foo);
})(foo);

console.log(foo);
if(自信回答){
	跳过本篇
}else{
	继续阅读
}

以上问题,涉及一个问题:变量 声明提升 (Hosting)


什么是变量声明提升?

为避免不必要的误解,本文中对变量的周期描述为:声明初始化赋值
JS代码的执行过程分为两个阶段:
1.预解析阶段:进入某作用域时,js解析器会受限找到当前作用域中所有的变量和函数进行声明(提前在内存中为变量开辟好空间)
2.执行阶段: 执行当前作用域中的代码(遇到变量赋值则赋值)

变量声明提升是如何进行的?(var关键字声明)
<script>
	console.log(a, fun) //undefined undefined
	var a = 1
	var fun () {}
	console.log(a, fun) //1 Function
</script>

1、js解析器会找到当前作用域中的变量和函数 , a和fun
2、将其声明过程提升到当前作用域的顶部
3、初始化变量为undefined

以上代码段相当于

<script>
	var a
	var fun
	console.log(a, fun) //undefined undefined
	a = 1
	fun () {}
	console.log(a, fun) //1 Function
</script>

变量声明提升的一些误区
1、函数与变量名冲突(同名)

策略:**函数优先变量进行声明提升

console.log(fun)	// Function
var fun = 2
function fun (a) {
    return a
}
2、变量与形参冲突(同名)

规范:对形参和变量均保存在该作用域的变量对象当中。
10.5 Declaration Binding Instantiation
Every execution context has an associated VariableEnvironment. Variables and functions declared in ECMAScript code evaluated in an execution context are added as bindings in that VariableEnvironment‘s Environment Record. For function code, parameters are also added as bindings to that Environment Record.

策略:**声明变量与形参重名,则该变量即形参 **
可以分为两种情况,变量只声明未赋值,变量声明后赋值。

console.log(foo);
var foo = { n: 1 };

(function (foo) {
    console.log(foo);
    foo.n = 3;
    var foo = { n: 2 }; //
    console.log(foo);
})(foo);

console.log(foo);
//undefined 
// { n: 1 }
// { n: 2 }
// { n: 3 }
其中
var foo = { n: 2 };
等价于
var foo
foo = {n:2}	//此时foo重新指向新的对象

var进行变量声明提升的过程存在与我们认知不符的情况

console.log(a)	//undefined
a = 1
console.log(a)	// 1

1、在声明变量前,就可以使用该变量,不合理吧
2、赋值前使用该变量竟然输出undefined, 我们并未对此变量进行赋值
于是就有了ES6的 let、const声明


ES6 的let const

let const变量声明提升过程:
1、预解析阶段:JS解析器找到该作用域中所用变量,进行变量声明(即在内存中开辟存储位置,但并不初始化)
2、执行阶段:对变量进行赋值等等。。。。
特点
1、let、const声明变量同样存在变量声明提升问题,但其有一个特性:暂时性死区,变量声明之前,不可调用该变量,否则会报错
2、let、const声明变量绑定声明时的作用域,这个特性其实为JS新增了块级作用域
3、作用域中不能重复声明,否则会报错,解决了变量名称冲突问题
4、const用以声明一个只读的变量,一旦声明,则该变量在内存(栈)中位置不可变。(不清楚这句话含义可查读JS中变量存储、值传递、深、浅拷贝等知识点)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值