let 與 var的區別
-
let有塊級作用域
es5中有全局作用域、函數作用域,es6中新增了塊級作用域,即用let聲明的變量只能在聲明的{}內訪問到
// let有塊級作用域
for(var i = 0; i < 3; i++) {
setTimeout(function () {
console.log(i) //打印 3個 3
}, 1000)
}
for(let i = 0; i < 3; i++) {
setTimeout(function () {
console.log(i) //打印 0 1 2
}, 1000)
}
var tmp = new Date();
function f() {
// 變量提升會執行,var沒有塊級作用域,變量賦值未執行
console.log(tmp);
if (false) {
var tmp = 'hello world';
}}
f(); // undefined
- 實踐:
利用這個特性,在爲DOM元素數組循環添加click事件時,可以用let獲取需要的i
// 添加onclick事件
const dom = [{}, {}, {}]
for(let i = 0; i < 3; i++) {
dom[i].onclick = function () {
console.log(i)
}
}
dom[0].onclick() // 0
dom[1].onclick() // 1
dom[2].onclick() // 2
- for中( )的特殊塊級作用域:
for循環中的()是一個特殊的塊級作用域,for循環中()中的let與{}內的不衝突
for(let i = 0; i < 3; i++) {
let i = 'foo';
console.log(i); // 打印3次 foo, ()內外層作用域,{}爲內層作用域,互不影響
}
// for可看成如下的代碼過程,可看出內外層i互不影響
// {
// let i = 0;
// if(i < 3) {
// let i = 'foo';
// console.log(i);
// }
// i++;
// ......
// }
-
let 沒有變量提升
在使用let定義變量前訪問變量出錯 而不是 undefined
// let 沒有變量提升
console.log(b); // undefined
var b = 200;
console.log(a);
let a = 100; // Cannot access 'a' before initialization
- 在全局作用域中let聲明不會像var一樣會在全局window對象中創建一個屬性
const
- 在let的基礎上“只讀”,聲明後無法修改(不允許修改內存地址,例如object可以修改其內容,但不能將其指向一個新的地址)
tips: 如果要確保引用類型值的屬性值不可變,請使用Object.freeze()凍結
// 將對象徹底凍結的函數
var constantize = (obj) => {
Object.freeze(obj);
Object.keys(obj).forEach( (key, i) => {
if ( typeof obj[key] === 'object' ) {
constantize( obj[key] );
}
});
};
- 由於其聲明後無法修改,因此聲明的時候必須賦值 const a; a = 10;這樣會報錯
最佳實踐
不用var,儘量用const,配合用let