聲明語法
var upperA = 'A'; let upperB = 'B'; const upperC = 'C';
只聲明不初始化的結果,【 const定義的常量不能夠修改,並且必須初始化。】
// var 聲明變量 var upperA; console.log('打印大寫的A:%s', upperA); // 結果:打印大寫的A:undefined // let 聲明變量 var upperB; console.log('打印大寫的B:%s', upperB); // 結果:打印大寫的B:undefined // const 聲明常量 const upperC; console.log('打印大寫的C:%s', upperC); // 錯誤:SyntaxError: Missing initializer in const declaration
聲明後值是否可修改,【 const定義的常量不能夠修改,並且必須初始化。】
// var 聲明變量初始化並修改值 var upperA = 'A'; console.log('打印upperA:%s', upperA); // 結果:打印upperA:A upperA = 'LetterA'; console.log('打印upperA:%s', upperA); // 結果:打印upperA:LetterA // let 聲明變量初始化並修改值 var upperB = 'B'; console.log('打印大寫的B:%s', upperB); // 結果:打印upperB:B upperB = 'LetterB'; console.log('打印大寫的B:%s', upperB); // 結果:打印upperB:LetterB // const 聲明常量初始化並修改值 const upperC = 'C'; console.log('打印upperC:%s', upperC); // 結果:打印upperC:C upperC = 'LetterC'; console.log('打印upperC:%s', upperC); // 錯誤:TypeError: Assignment to constant variable.
瀏覽器在運行代碼以前會進行預解析,首先解析函數聲明,定義變量,解析完以後再對函數、變量進行運行、賦值等
不論var聲明的變量處於當前做用域的第幾行,都會提高到做用域的頭部。
var 聲明的變量會被提高到做用域的頂部並初始化爲undefined,而let聲明的變量不會被提高到做用域的頂部。
console.log('打印upperA:%s', upperA); // 結果:打印upperA:undefined console.log('打印upperB:%s', upperB); // 錯誤:ReferenceError: upperB is not defined var upperA = 'A'; let upperB = 'B';
** var容許在相同做用域內,重複聲明同一個變量,後面聲明的變量會覆蓋前面聲明的變量。
** let不容許在相同做用域內,重複聲明同一個變量。
var upperA = 'A'; let upperB = 'B'; // 重複聲明 var upperA = 'LetterA'; let upperB = 'LetterB'; console.log('打印upperA:%s', upperA); console.log('打印upperB:%s', upperB) // 錯誤:SyntaxError: Identifier 'upperB' has already been declared
在ES6以前,咱們都是用var來聲明變量,並且JS只有函數做用域和全局做用域,沒有塊級做用域,因此{}限定不了var聲明變量的訪問範圍。
// ---------- 例如: ---------- { var upperA = 'A'; } console.log('打印upperA:%s', upperA); # 結果: 打印upperA:A // ---------- ES6新增的let,能夠聲明塊級做用域的變量。---------- { let upperB = 'B'; } console.log('打印upperB:%s', upperB); // 錯誤: ReferenceError: upperB is not defined
let很是適合用於 for循環內部的塊級做用域。
** JS中的for循環體比較特殊,每次執行都是一個全新的獨立的塊做用域,用let聲明的變量傳入到 for循環體的做用域後,不會發生改變,不受外界的影響。
// ---------- 看一個常見的面試題目: ---------- for (var i = 0; i <10; i++) { setTimeout(function() { // 同步註冊回調函數到 異步的 宏任務隊列。 console.log(i); // 執行此代碼時,同步代碼for循環已經執行完成 }, 0); } // 輸出結果:10 共10個 // 這裏面的知識點: JS的事件循環機制,setTimeout的機制等 // ---------- 若是把 var改爲 let聲明:---------- // i雖然在全局做用域聲明,可是在for循環體局部做用域中使用的時候,變量會被固定,不受外界干擾。 for (let i = 0; i < 10; i++) { setTimeout(function() { console.log(i); // i 是循環體內局部做用域,不受外界影響。 }, 0); } // 輸出結果:0 1 2 3 4 5 6 7 8 9