块级作用域:解决全局变量污染问题
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可以随意赋值;