说说 ES6 的 let 指令

let 指令用法相似于 var,也是用来声明变量 ,可是它所声明的变量,只能在 let 指令所在的代码块内有效 。bash

{
    let a = 1;
    var b = 1;
}


console.log(b);
console.log(a);
复制代码

运行结果:函数

1
console.log(a);
            ^

ReferenceError: a is not defined
复制代码

此例中, b 会打印出结果。但 a 由于是使用 let 命令声明的变量,因此只在它所在的代码块内有效。ui

1 应用场景

let 指令适用于 for 循环变量声明。在 ES6 以前,咱们使用 var 指令来声明变量,可能存在一些问题,请看下面的示例:spa

var a = [];
for (var i = 0; i < 3; i++) {
    a[i] = function () {
        console.log(i);
    };
}
a[0]()
a[2]()
复制代码

运行结果:设计

3 3code

变量 i 是 var 声明的,因此它在全局范围内都有效 。 因此在每一次循环中,新的 i 值都会覆盖旧值,致使最后 a 中的全部函数,输出的都是最后一轮的 i 的值 。cdn

使用 let 指令,就可以避免上述问题:blog

var a = [];
for (let i = 0; i < 3; i++) {
    a[i] = function () {
        console.log(i);
    };
}
a[0]()
a[2]()
复制代码

运行结果:内存

0 2作用域

注意: for 循环内部,设置循环变量是一个做用域,而循环体内部是另外一个做用域:

for (let i = 0; i < 3; i++) {
    let i = 10;
    console.log(i)
}
复制代码

运行结果:

10 10 10

2 变量不提高

var 会发生 “ 变量提高 ” 现象,即 var 声明的变量,能够在声明以前使用。 但 let 声明的变量,必定要在声明以后使用,这种设计,让 JS 变得更加规范。变量在声明后,才能使用。

//var 变量提高
console.log('j='+j);
var j = 1;

//let 变量不会提高
console.log('k='+k);
let k = 1;
复制代码

运行结果:

j=undefined ReferenceError: k is not defined

3 暂时性死区

只要块级做用域内,存在 let 指令,那么它所声明的变量不会再受外部影响,因此称为暂时性死区(temporal dead zone)。

var str = 1;
if (true) {
    str = 'a';
    let str;
}
复制代码

运行结果:

ReferenceError: str is not defined

ES6 中,若是代码块内存在 let 或 const 指令声明的变量,那么这些变量从一开始就会造成封闭做用域 。 凡在声明以前使用这些变量,就会抛出 ReferenceError。

3.1 对 typeof 的影响

暂时性死区甚至会影响到 typeof 操做符:

if(true){
    console.log('y 类型:'+typeof y);
    console.log('x 类型:'+typeof x);
    let x;
}
复制代码

运行结果:

y 类型:undefined ReferenceError: x is not defined

这个示例,变量 x 使用 let 指令声明,因此在声明以前,都属于 x 的暂时性死区 ,所以抛出了 ReferenceError 。

3.2 隐蔽的死区

请看这个示例:

function test(x = y, y = 1) {
    return x + y;
}
test();
复制代码

运行结果:

ReferenceError: y is not defined

函数的入参 x,它的默认值等于另外一个入参 y ,而此时 y 还未声明,因此会抛出 ReferenceError。

只要声明了全部的入参,就可让这个函数正确运行:

function test2(y = 1,x = y ) {
    return x + y;
}
console.log(test2());
复制代码

运行结果:

2


暂时性死区的设定,能够有效地减小运行时错误。它的本质是:在当前做用域下,只有声明了变量,才可使用它。

4 拒绝重复声明

let 指令,在相同做用域内,同一个变量只能被声明一次。

if(true){
    let a = 1;
    var a = 2;
}
复制代码

运行结果:

SyntaxError: Identifier 'a' has already been declared

if(true){
    let a = 1;
    let a = 2;
}
复制代码

运行结果与上例相同。

这样的限制,也约束了函数的入参声明:

function test(a) {
    let a = 2;
    console.log(a);
}

test(1);
复制代码

运行结果:

SyntaxError: Identifier 'a' has already been declared

但咱们能够在函数内部,加入块级做用域,来绕开这一限制:

function test(a) {
    {
        let a = 2;
        console.log(a);
    }
}

test(1);
复制代码

运行结果:

2

相关文章
相关标签/搜索