小例1:數組
{
let tmp = 5;
console.log(tmp); // 5
}
console.log(tmp); // Uncaught ReferenceError: tmp is not defined
複製代碼
let 聲明的變量只在 let 命令所在的代碼塊內有效, 在代碼塊以外無效bash
小例:閉包
const I_MAX = 9999999;
console.log(I_MAX); // 9999999
const I_MIN; // Uncaught SyntaxError: Missing initializer in const declaration
console.log(I_MIN);
複製代碼
小例:函數
{
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 definedui
小例:spa
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指針
小例:code
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);
複製代碼
var tem = 3;
if (true) {
tem = 5; // Uncaught ReferenceError: tem is not defined
let tem;
}
複製代碼
ES6規定若是塊內存在let命令,那麼這個塊就會成爲一個封閉的做用域,並要求let變量先聲明才能使用,若是在聲明以前就開始使用,它並不會引用外部的變量。對象
var temA = 'A';
console.log(window.temA); // A
let temB = 'B';
console.log(window.temB); // undefined
複製代碼
var全局聲明後會做爲全局對象window的一個屬性,而let不會,因此提示undefined內存
小例:實現將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同樣,都是塊級做用域,存在暫時性死區,不存在變量聲明提早,不容許重複定義,不會成爲全局對象的一個屬性。