1. 程式人生 > >關於ES6的let和const

關於ES6的let和const

### 變數 #### var存在的問題 1. 可以重複宣告 2. 無法限制修改 3. 沒有塊級作用域 (在全域性範圍內有效) 4. 存在變數提升 #### const/let 1. 不可以重複宣告 ```javascript let a = 1; let a = 2; var b = 3; var b = 4; a // Identifier 'a' has already been declared b // 4 ``` 2. const 不可以修改(定義常量)、let 可以修改(定義變數) ```javascript { let a = 0; var b = 1; } a // ReferenceError: a is not defined b // 1 ``` 3. 有塊級作用域 ```javascript 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 引擎內部會記住前一個迴圈的值 ``` 4. 不存在變數提升 ```javascript console.log(b); //undefined var b = "banana"; // 變數b用var 來宣告,存在變數提升,當指令碼執行時,b已經存在了,但是還沒有賦值,所以會出現undefined console.log(a); //ReferenceError: a is not defined let a = "apple"; ``` 5. const宣告一個只讀變數,宣告之後不允許改變。意味著,一旦宣告,必須初始化,否則會報錯。 ```javascript const a = 1; const b; // SyntaxError: Missing initializer in const declaration ``` ##### 問題來了,為什麼const可以在變數宣告初始化之後不允許改變呢? const 其實保證的不是變數的值不變,而是保證變數指向的記憶體地址所儲存的資料不允許變動。 ##### 問題又來了,不同資料型別(簡單型別,複合型別(或稱引用型別))儲存值的方式是不同的。 - 對於簡單型別(number,string,boolean),值就儲存在指向的記憶體地址,因此const宣告的簡單型別變數等同於常量。 - 對於複合型別(object,array,function),變數指向的記憶體地址其實儲存了一個指向實際資料的指標,所以const只能保證指標是固定的,至於指標指向的資料結構就無法保證其不改變,所以const聲明覆雜型別物件時要慎重。 #### 這其中涉及到了,簡單型別和複合型別的儲存方式 - 基本型別值在記憶體中佔固定大小的空間,因此被儲存在棧記憶體中 - 複合型別的值是物件,儲存在堆記憶體中 #### 當兩者分別進行變數複製的時候 1. 基本型別:會在變數物件上建立一個新值,然後把該值複製到為新的變數分配的位置。 ```javascript var num1 = 1; var num1 = num2; ``` | | | | ------- | ----- | | | | | num1 | 1 (number型別)| ###### 複製後的變數物件 | | | | ------- | ----- | | num2 | 1(number型別)| | num1 | 1 (number型別)| 2. 複合型別: 從一個變數向另一個變數複製引用型別的值,複製的其實是指標,因此兩個變數最終都指向同一個物件。 ```javascript var obj1 = new Object(); var obj2 = obj1; obj1.name = "Tom"; alert(obj2.name);// "Tom" ``` ![avatar](https://images.cnblogs.com/cnblogs_com/Heiofungming/1757523/o_200718035009%E5%8F%98%E9%87%8