2、块级作用域与嵌套、let、暂时性死区

95 阅读2分钟

块级作用域:解决全局变量污染问题

1、let:的特点

1、同一个作用域下不能重复声明变量:通篇语法检查的阶段,报语法错误,SyntaxError

let a=10;

let a=11;

2、let 声明变量不会提升,使用let命令声明变量之前,该变量都是不可用的,在执行函数的阶段否则报ReferenceError。

function test() {
	console.log(j);//ReferenceError
	let j = 'a'
}
function test2(a=b,b=10){
}

2-1暂时性死区

let j=10;
function test() {
	console.log(j);//ReferenceError
	let j = 'a'
}
test()

3、let声明的变量只能在所在的块级作用域生效。

3-1、案例

function test(c) { //函数作用域
	let i = 1;
	{ //块级作用域 A
		let i = 2;
		console.log(b); { //块级作用域 B
			var j = 3
                        function i(){
			    console.log(j);
		        }
		}
		console.log(j);
	}
	console.log(j);
}

变量j会逐级冒泡声明var j=undefined,也就是会在j的每一个父级都声明变量j,函数声明只能提升在当前作用域

3-2:案例

function test(){
	var j=10
	for (let j = 0; j < 10; j++) {
		let j='a'
		console.log(j);
	}
}

由于for循环的参数部分(let j = 0; j < 10; j++),会作为循环体的父作用域,在该部分所声明的变量都在这个作用域内, 而循环体内部是一个单独的子作用域。以上代码等价于:

function test(){
	var j=10
	{
		let j = 0
		for (; j < 10;) {
			let j='a'
			console.log(j);
			 j++
		}
	}
}

3-3:案例

function test(){
	var j=20;
	for (let j = 0; j < 10; j++) {
		var j='a'
		console.log(j);
	}
}

这个会在通篇语法检查的阶段报SyntaxError,由于var声明的变量会逐级提升,导致变量重复声明,等价代码如下:

function test() {
	var j = 10;
	for (var j = undefined;
		let j = 0; j < 10;) {
		let j = 'a'
		console.log(j);
		j++
	}
**}**

function test(){
	var j=10
	{
		let j = 0
                var j=undefined
		for (; j < 10;) {
			let j='a'
			console.log(j);
			 j++
		}
	}
}

特点4:在全局声明的变量,不会挂载在顶层window上:

console.log(window.x);//undefined
console.log(window.y);//2

案例5:

// let x = 1
function test(y = x) {
	let x = 2;
	console.log(y);//1
}
test();
function test2(x=1) {
	let x = 2;
	console.log(x);//SyntaxError
}
test2();

用案例3-2可以说明形参和函数体的存在父子关系的作用域。 但是test2又否定了这种说法

const关键字

const关键字的特点和let的特点几乎一样, 存在的区别有2点:

1、const声明的变量,声明时必须赋值,let可以后赋值;

2、const声明的变量,不可重新赋值,let可以随意赋值;