1. 程式人生 > >ES6 let&const

ES6 let&const

  今天來總結一下ES6裡面let與const的用法

  先總體看一下ES6中的let都有哪些特性:

let 特性

  1. let宣告的變數在js中不可以重複宣告,防止變數的汙染和覆蓋
  2. let宣告的變數不涉及變數的提升,可以有效防止閉包問題
  3. let宣告的變數在塊級作用域中有效
  4. let宣告的變數存在暫時性死區
    宣告的變數在為執行到宣告語句時,變數將會暫存在暫時性死區中,當執行完宣告 語句時,將會從暫時性死區中將變數取出

 

1. 同名變數不可以重複宣告2. let宣告的變數不存在變數提升的問題

1   var a = 100;
2   et b = 20; // 報錯

2. let宣告的變數不存在變數提升的問題

1 /**
2 * es6新出的變數定義方式宣告的變數不再與全域性物件相關聯
3 * 即class , let , const , import 宣告的變數不會把變數掛到全域性物件上
4 **/
5 let num = 10;
6 console.log(window.num); //undefined
7 var num2 = 10;
8 console.log(window.num2); //10

 

 

  我們都知道,js在全域性中宣告變數,其實質是哪個就是將該變數掛載到window物件的屬性上,因此,在訪問全域性變數時,與訪問window物件的屬性是一致的。js的設計者逐漸意識到設計存在問題,因此,逐漸開始全域性物件與全域性變數進行分離。在使用let或者const,甚至之後的class宣告變數,都不再將全域性變數掛載全域性物件(window或者global上)
3. 在ES6中還引入了塊級作用域的概念。

 使用let和const宣告的變數只在申明語句所在的塊級作用域有效。離開了塊級作用域,變數的宣告失效,因此也不存在變數的提升。

1 {
2   var a = 100;
3   let b = 200;
4 }
5 
6 console.log(a); // 100
7 console.log(b); // b is not defined

  使用let和const+塊級作用域的宣告方式可以在某種程度上代替立即執行函式的方式

 1 let vari = 123;
 2 // 立即執行函式解決變數命名衝突問題
 3 (function(){
 4   let vari = 456;
5   console.log(vari); // 4561 6 }()) 7 8 // 塊級作用域解決變數重名問題 9 { 10   let vari = 789 11   console.log(vari); // 789 12 } 13 console.log(vari); // 123

  很顯然,利用ES6的塊級作用域解決命名衝突更加簡潔明瞭。

4.暫時性死區。

1 let a = 10;
2 {
3   // 使用let宣告變數時,變數會存放在暫時性死區中,在執行宣告語句之前不可以使用該變數
4   // 即使全域性中有a變數也不行
5   console.log(a); // a is not defined
6   let a = 5;
7 }

  以上的程式碼在其他程式語言中是不會報錯的,但是在js中就會報錯。雖然在全域性聲明瞭變數a,但在塊級作用域中,存在let的宣告語句,變數將會被存放在暫時性死區中。存放在暫時性死區中的變數,只有在執行了變數的宣告語句之後才會從暫時性死區中取出使用。
5.函式宣告方式

 1 {
 2   /**
 3   * 1. 在塊級作用域內允許宣告函式
 4   * 2. 函式宣告類似於var宣告,將變數宣告提升到函式作用域或者全域性作用域前面,但函式體不提升
 5   * 3. 函式宣告提升到所在塊級作用域的頭部
 6   **/
 7   function f() { console.log('i am in outside!'); }
 8   (function () {
 9     // f(); //f is not a function ,說明函式的宣告提升到了函式作用域的頭部,在此處已有f變數的宣告,其值為undefined
10     // console.log(f);
11     if (true) {
12       // f = 10;
13       console.log(f); //此處f的值為函式體,說明函式整體提升到了塊級作用域的頭部
14       // f = 10;
15       function f() { console.log('i am in inside!'); }
16     }
17   }());
18 }

  在塊級作用域中允許申明函式,不過該宣告方式與ES5的形式不同,在ES6的塊級作用域中宣告函式,會將函式的宣告部分提升到塊級作用域的頭部,而函式提不提升。
  關於const的用法,其宣告特性與let一致,只不過const宣告的一般型別變數值是不可以修改的,對於引用資料型別來說是可以修改的。const宣告的實質是const宣告的物件的棧記憶體空間不能再改變,而引用變數所指向的堆記憶體空間是可以改變的。

 1 {
 2   let obj = {
 3     name: 'zhang',
 4     age: 18,
 5     birthday: {
 6     year: 2018,
 7     month: 13,
 8     day: 32
 9     }
10   };
11   let myFreeze = (obj) => {
12     for (let prop in obj) {
13       // Object.freeze()方法能夠是物件屬性的值不可改,相當於加上了const宣告
14       Object.freeze(obj);
15       // 若物件的屬性依舊是引用型別,則遞迴處理
16       if (typeof (obj[prop]) === 'object') {
17       // console.log('referencing prop');
18       myFreeze(obj[prop]);
19     } 
20   }
21   return obj;
22 }
23 var constObj = myFreeze(obj);
24 console.log(obj);
25 obj.birthday.year = 1998; //此處修改屬性無效


  用上面的遞迴方式即可將一個物件轉換為物件常量,即物件中所有的屬性,不可更改。
  let與const的出現使得js的變數生命更加規範,因此,建議使用const和let的方式宣告變數。