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