let
- let 宣告的變數只在 let 命令所在的程式碼塊內有效。
小例1:
{
let tmp = 5;
console.log(tmp); // 5
}
console.log(tmp); // Uncaught ReferenceError: tmp is not defined
複製程式碼
let 宣告的變數只在 let 命令所在的程式碼塊內有效, 在程式碼塊之外無效
const
- const 宣告一個常量(所謂常量就是物理指標不可以更改的變數),宣告之後不允許改變。意味著,一但宣告必須初始化,否則會報錯。
小例:
const I_MAX = 9999999;
console.log(I_MAX); // 9999999
const I_MIN; // Uncaught SyntaxError: Missing initializer in const declaration
console.log(I_MIN);
複製程式碼
- const 除了不能改變物理指標的特性,其他特性和 let 一樣。
let const var 的區別
- let 是在程式碼塊內有效,var 是在全域性範圍內有效。
小例:
{
var temA = 'A';
let temB = 'B'
}
console.log(temA); // A
console.log(temB); // Uncaught ReferenceError: temB is not defined
複製程式碼
temA和temB都宣告在程式碼塊裡面,temA是由var宣告,在外部可以直接訪問,temB是由let宣告,在外部不可直接訪問,提示錯誤:temB is not defined
- let 宣告的變數不存在變數提升。
小例:
temA = 'A';
temB = 'B'; // Uncaught ReferenceError: temB is not defined
console.log(temA); // A
console.log(temB);
var temA;
let temB;
複製程式碼
var 宣告的變數存在變數提升,所以temA在賦值語句下面宣告,沒有問題;let 宣告的變數不存在變數提升,所以temB在賦值語句下面宣告,提示錯誤:temB is not defined
- let 只能宣告一次變數 var 可以宣告多次變數。
小例:
var temA = 'A';
let temB = 'B';
console.log(temA); // A
console.log(temB); // B
var temA = 'C';
let temB = 'D'; // Uncaught SyntaxError: Identifier 'temB' has already been declared
console.log(temA); // C
console.log(temB);
複製程式碼
- let存在暫時性死區
var tem = 3;
if (true) {
tem = 5; // Uncaught ReferenceError: tem is not defined
let tem;
}
複製程式碼
ES6規定如果塊記憶體在let命令,那麼這個塊就會成為一個封閉的作用域,並要求let變數先宣告才能使用,如果在宣告之前就開始使用,它並不會引用外部的變數。
- let 不會成為全域性物件的一個屬性
var temA = 'A';
console.log(window.temA); // A
let temB = 'B';
console.log(window.temB); // undefined
複製程式碼
var全域性宣告後會作為全域性物件window的一個屬性,而let不會,所以提示undefined
- const和var的區別,除了const是宣告一個不可更改的常量外,和var的區別和let一致,也就是說上面幾點let和var的區別,同樣也是const和var的區別。
進階用法
- 在for迴圈中使用let定義變數,只在for迴圈內可以使用。
小例:實現將for迴圈中的i變數,存入arr陣列中,for迴圈結束後,依次輸出。
// ES5的實現
var arr = [];
for(var i = 0; i < 3; i++){
arr.push(function (){
console.log(i);
})
}
arr[0]() // 3
arr[1]() // 3
arr[2]() // 3
複製程式碼
為什麼每次輸入都是3,因為for迴圈每次做的事只是向陣列中存入一個函式,但是函式並沒有立刻執行。i是通過var來宣告的。當for迴圈完,此時i的值是3。當你去執行函式的時候,自然輸出3
ES5的閉包實現
var arr = [];
for(var i = 0; i < 3; i++){
arr.push((function (arg){
return function (){
console.log(arg);
}
})(i))
}
arr[0]() // 0
arr[1]() // 1
arr[2]() // 2
複製程式碼
利用ES5的閉包也可以實現,但是程式碼比較複雜,如果用ES6就比較簡單了,看下面程式碼
// ES6的實現
let arr = [];
for(let i = 0; i < 5; i++){
arr.push(function (){
console.log(i);
})
}
arr[0]() // 0
arr[1]() // 1
arr[2]() // 2
複製程式碼
為什麼這樣就能彈出 0,1,2? 其實需要注意個問題,就是這個let i=0;宣告的位置,是在for的()內,那麼你可以理解成,在for的內部就定義了一個i而且是使用let定義的。所以每次迴圈就相當於在當前迴圈的i值的前提下向陣列push的。
總結:var let const 都是宣告變數的關鍵字,var的作用域是函式作用域,在一個函式內利用var宣告一個變數,則這個變數只在這個函式內有效。如果在函式外部宣告一個變數,則這個變數全域性有效,var存在變數提升。const一般用來宣告常量,且宣告的常量是不允許改變的,只讀屬性,因此就要在宣告的同時賦值。const與let一樣,都是塊級作用域,存在暫時性死區,不存在變數宣告提前,不允許重複定義,不會成為全域性物件的一個屬性。