用實例說明 var、let、const 的區別和特性
寫了這麼就居然發現沒寫一篇關於 let 和 const 的…從今天開始全方位的進軍 es6,哈哈啊哈哈哈
首先回顧一下 es5 var 的特性和作用域。var 命令可以聲明一個變量,聲明的變量和函數會有變量提升。例如:
console.log(a); // undefined
var a = 10;
console.log(foo); // undefined
var foo = function() {
return 12;
};
詳情可跳至 var 作用域||變量
在 es5 中 JavaScript 沒有塊級作用域特性,使用 var 聲明的變量會產生污染。例如:
var i = "ooo";
for (var i = 0; i < 10; i++) {
console.log(i); //0,1,2,3,4,5,6,7,8,9
}
console.log(i); // 10
變量 i 由於是 var 聲明的,在全局範圍內都有效,每一次循環 i 的值都會改變,由於不是塊級作用域,循環內的 i 會在循環結束後(for 循環外)也會有效。
let 和 var 的區別:
1.不存在變量提升
使用 let 聲明變量,使用它必須要在聲明之後,否則報錯。例如:
console.log(b); // b is not defined
let b = 10;
2.在同一作用域內不能重複聲明
使用 var 聲明變量可以重複聲明同樣名稱的變量,後聲明的會覆蓋之前聲明的,例如:
var a = 10;
var a = 9;
if (true) {
var a = 5;
}
console.log(a); // 5
使用 let 則不允許重複聲明:
let a = 10;
let a = 9; //Identifier 'a' has already been declared
3.暫時性死區
使用 var 聲明變量時的情況:
var a = 10;
if (true) {
a = 6;
var a;
}
console.log(a); // 6
使用 let:
let a = 10;
if (true) {
a = 6; // a is not defined
let a;
}
console.log(a);
這是因爲使用 let 相當於給 JavaScript 增加了塊級作用域,它所聲明的變量會綁定這個區域不受外界影響。
上面的例子中,let 寫在 if 語句內,此時 if 語句{}形成一個塊級作用域,這個作用域不受外界影響{a = 6;let a;}
,a=6 賦值語句執行的時候 a 還沒有被聲明,所以報錯。也就是說在使用 let 聲明變量之前(已經寫了 let 聲明)不可以使用該變量,就稱爲暫時性死區。
4.塊級作用域
使用 var 聲明變量,不會對作用域有所改變。使用 let 聲明變量會自動給當前聲明的作用域綁定塊級作用域。
例如:
if (true) {
let a = 10;
}
這個 if 裏的{}就形成了塊級作用域,而普通{}或者{var a = 10},則不會對該作用域有影響。換句話說,使用 var 則在該{}外能夠訪問該變量,使用 let 則在{}外不能訪問該變量。例如:
if (true) {
let a = 10;
}
console.log(a); // a is not defined
if (true) {
var b = 10;
}
console.log(b); //10
5.const
關於 let 以上特性,const 也同樣具備。不過 const 表示聲明一個只讀常量,也就是說是一個不可以被更改的數據。例如:
const a = 10;
a = 6; //Assignment to constant variable.
a 變量不可以更改,這一點與 let 不同,因爲 let 聲明的變量是可以被更改的。其次,const 一旦聲明就要立刻初始化給它賦值,只聲明不賦值會報錯。而 let 可以先聲明後賦值。
const a //Missing initializer in const declaration
這裏需要注意的是const保證的,並不是變量的值不得改動,而是變量指向的那個內存地址不得改動。對於簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,因此等同於常量。對於符合類型數據(如對象、數組)變量指向的內存地址保存的只是一個指針,const只保證這個指針是固定的,不能控制指針指向的數據結構是否改變。
const foo = {};
// 爲 foo 添加一個屬性,可以成功
foo.prop = 123;
foo.prop; // 123
// 將 foo 指向另一個對象,就會報錯
foo = {}; // TypeError: "foo" is read-only
const a = [];
a.push("Hello"); // 可執行
a.length = 0; // 可執行
a = ["Dave"]; // 報錯