ES6(一):let和const

版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/caomage/article/details/83586048

ES6(一):let和const

一、let

1. let基本用法

  相當於var,但是又與var不同,因爲let聲明的變量只能在let所在的代碼塊中有效。   從以下兩段代碼以及對應的輸出結果可以很明顯的看出var與let的區別。 code:

for (var i = 0; i < 5; i++) {
    console.log(i);
}
console.log(i);

result:

0
1
2
3
4
5

code:

for (let i = 0; i < 5; i++) {
    console.log(i);
}
console.log(i);

result:

0
1
2
3
4
ReferenceError: i is not defined

2. 塊級作用域

  衆所周知,在ES5中只有全局作用域和函數作用域,沒有我們所謂的塊級作用域。   這不禁讓我想起一個面試題: code:

for (var i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(new Date, i);
    }, 1000);
}

console.log(new Date, i);

  問:上面這段代碼輸出的結果是什麼?   仔細琢磨一下我們很容易得出正確的答案:

result:

2018-10-31T06:55:30.020Z 5
2018-10-31T06:55:31.021Z 5
2018-10-31T06:55:31.021Z 5
2018-10-31T06:55:31.022Z 5
2018-10-31T06:55:31.022Z 5
2018-10-31T06:55:31.022Z 5

  仔細看一下發現:由於setTimeout會被JavaScript延遲執行,因此是先輸出最底部的console.log,隔一秒之後再執行循環裏面的consol.log,此時i已經全部是5。   那我們怎麼樣才能使輸出結果變成想要的0,1,2,3,4呢?   明白了let的原理之後其實問題變得很簡單: code:

for (let i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(new Date, i);
    }, 1000);
}

console.log(new Date, i);

  這樣就行了嗎? result:

ReferenceError: i is not defined

  哈哈,剛剛還說過let只在所在的代碼塊裏面有效,這裏最外層的console.log很明顯找不到i,所以報出引用錯誤。想要得到正確答案其實還需要去掉最後一行console.log。   當然這個題目要擱以前的話,首先想到的解決方案應該是IIFE(Immediately Invoked Function Expression:聲明即執行的函數表達式)來解決閉包造成的問題。 code:

for (var i = 0; i < 5; i++) {
    (function(j) {  
        setTimeout(function() {
            console.log(new Date, j);
        }, 1000);
    })(i);
}

console.log(new Date, i);

result:

2018-10-31T07:17:45.825Z 5
2018-10-31T07:17:46.827Z 0
2018-10-31T07:17:46.827Z 1
2018-10-31T07:17:46.827Z 2
2018-10-31T07:17:46.827Z 3
2018-10-31T07:17:46.827Z 4

  由此我們是不是就可以得出一個結論,有了let,我們就可以拋棄IIFE了?   這個暫時還不好說,我們還是繼續看看let的其他特性。

3. 沒有變量提升

  var命令會產生變量提升的現象,這使得js這門語言變得並不嚴謹,這一點是特點也是雞肋。用var聲明的變量,如果我們在聲明之前使用,則它的值爲undefined。   而當我們用let定義變量時,就必須嚴格按照先定義再使用的原則了,反之則會拋出一個大大的引用錯誤(ReferenceError),顯然這更符合人們的使用習慣。 code:

console.log(a);
var a = 2;

console.log(b);
let b = 2;

result:

undefined
ReferenceError: b is not defined

4. 暫時性死區及不能重複聲明

  ES6 明確規定,如果區塊中存在let和const命令,這個區塊對這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,就會報錯。   總之,在代碼塊內,使用let命令聲明變量之前,該變量都是不可用的。這在語法上,稱爲“暫時性死區”(temporal dead zone,簡稱 TDZ)。   “暫時性死區”也意味着typeof不再是一個百分之百安全的操作。   let不允許在相同作用域內,重複聲明同一個變量。

二、const

1. const基本用法

  const命令是聲明一個常量,用法和let一樣。

  • 和let的相同之處是:
    • const與let作用域相同,都是隻在聲明的代碼塊中起作用
    • const也不會提升所聲明的常量
    • const也不能重複聲明
  • 不同之處是const聲明的常量在聲明時就必須賦值,因爲一旦聲明就不能改變改常量的值

2. 真的不能改變嗎?

  const實際上保證的,並不是變量的值不得改動,而是變量指向的那個內存地址所保存的數據不得改動。對於簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,因此等同於常量。但對於複合類型的數據(主要是對象和數組),變量指向的內存地址,保存的只是一個指向實際數據的指針,const只能保證這個指針是固定的(即總是指向另一個固定的地址),至於它指向的數據結構是不是可變的,就完全不能控制了。因此,將一個對象聲明爲常量必須非常小心。 code&result:

const a=1;
a=2;//TypeError
const obj={
    b:3,
    c:4
}
obj.b=5;
console.log(obj);//{b:5,c:4}

參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章