說說 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

相關文章
相關標籤/搜索