1. 程式人生 > 實用技巧 >關於ES6的let和const

關於ES6的let和const

變數

var存在的問題

  1. 可以重複宣告
  2. 無法限制修改
  3. 沒有塊級作用域 (在全域性範圍內有效)
  4. 存在變數提升

const/let

  1. 不可以重複宣告
        let a = 1;
let a = 2;
var b = 3;
var b = 4;
a // Identifier 'a' has already been declared
b // 4
  1. const 不可以修改(定義常量)、let 可以修改(定義變數)
        {
let a = 0;
var b = 1;
}
a // ReferenceError: a is not defined
b // 1
  1. 有塊級作用域
        for (var i = 0; i < 10; i++) {
setTimeout(function(){
console.log(i);
}
}
// 輸出十個 10
//由於var宣告的變數i是在全域性範圍內有效,所以全域性中只有一個i,setTimeout定時器裡面的i指的是全域性變數i,而迴圈裡的是個setTimeout是在迴圈結束後才執行的,所以此時的i都是10。 // 可以利用函式function來解決該問題
for (var i = 0; i < 10; i++) {
(function (i){
setTimeout(function(){
console.log(i);
}
})(i)
}
// 輸出 0123456789 for (let j = 0; j < 10; j++) {
setTimeout(function(){
console.log(j);
})
}
// 輸出 0123456789
// 每次迴圈都是一個新的變數
// 問題來了,若每次迴圈的變數 j 都是重新宣告的,如何知道前一個迴圈的值?這是因為 JavaScript 引擎內部會記住前一個迴圈的值
  1. 不存在變數提升
    console.log(b);  //undefined
var b = "banana";
// 變數b用var 來宣告,存在變數提升,當指令碼執行時,b已經存在了,但是還沒有賦值,所以會出現undefined console.log(a); //ReferenceError: a is not defined
let a = "apple";
  1. const宣告一個只讀變數,宣告之後不允許改變。意味著,一旦宣告,必須初始化,否則會報錯。
        const a = 1;

        const b;  // SyntaxError: Missing initializer in const declaration
問題來了,為什麼const可以在變數宣告初始化之後不允許改變呢?
const 其實保證的不是變數的值不變,而是保證變數指向的記憶體地址所儲存的資料不允許變動。
問題又來了,不同資料型別(簡單型別,複合型別(或稱引用型別))儲存值的方式是不同的。
  • 對於簡單型別(number,string,boolean),值就儲存在指向的記憶體地址,因此const宣告的簡單型別變數等同於常量。

  • 對於複合型別(object,array,function),變數指向的記憶體地址其實儲存了一個指向實際資料的指標,所以const只能保證指標是固定的,至於指標指向的資料結構就無法保證其不改變,所以const宣告覆雜型別物件時要慎重。

這其中涉及到了,簡單型別和複合型別的儲存方式

  • 基本型別值在記憶體中佔固定大小的空間,因此被儲存在棧記憶體中
  • 複合型別的值是物件,儲存在堆記憶體中

當兩者分別進行變數複製的時候

  1. 基本型別:會在變數物件上建立一個新值,然後把該值複製到為新的變數分配的位置。
      var num1 = 1;
var num1 = num2;
num1 1 (number型別)
複製後的變數物件
num2 1(number型別)
num1 1 (number型別)
  1. 複合型別:
      var obj1 = new Object();
var obj2 = obj1;
obj1.name = "Tom";
alert(obj2.name);// "Tom"