[TOC] #### 1. 作用域 --- let 和 const 具有塊級作用域;var 聲明的變量具有全局作用域,但是不能跨函數訪問 ```javascript if (true) { var a = 1 let b = 2 const c = 3 } console.log(a) // 1 console.log(b) // Uncaught ReferenceError: b is not defined console.log(c) // Uncaught ReferenceError: c is not defined for (var index = 0; index < 2; index++) { } console.log(index) // 2 for (let index = 0; index < 2; index++) { } console.log(index) // Uncaught ReferenceError: index is not defined ``` var 在函數內聲明的變量具有局部作用域,只能在函數內部訪問,不能在全局訪問 ```javascript function test() { var a = 1 } test() console.log(a) // Uncaught ReferenceError: a is not defined ``` #### 2. 變量提升 --- 變量提升: 變量能在聲明前使用 let 和 const 不存在變量提升,var 存在變量提升 在 let 和 const 聲明變量之前,該變量都是不可用的,這在語法上稱為 **暫時性死區(qū)**,var 聲明的變量不存在 **暫時性死區(qū)** ```javascript console.log(a) // undefined var a = 1 console.log(a) // Uncaught ReferenceError: Cannot access 'a' before initialization let a = 1 console.log(a) // Uncaught ReferenceError: Cannot access 'a' before initialization const a = 1 ``` #### 3. 全局屬性 --- 瀏覽器的全局對象是 window,var 聲明的變量為全局變量,并且會將該變量添加為全局對象的屬性,但 let 和 const 不會 ```javascript var a = 1 let b = 2 const c = 3 console.log(window.a) // 1 console.log(window.b) // undefined console.log(window.c) // undefined ``` #### 4. 重復聲明 --- var 聲明變量時,可以重復聲明,但 let 和 const 在同一作用域不允許重復聲明變量 ```javascript var a = 1 var a = 2 let b = 1 let b = 2 // Uncaught SyntaxError: Identifier 'b' has already been declared const c = 1 const c = 2 // Uncaught SyntaxError: Identifier 'c' has already been declared ``` let 和 const 在不同的作用域可以使用相同的變量名聲明變量 ```javascript { let b = 1 const c = 3 } let b = 2 const c = 4 ``` #### 5. 初始值設置 --- var 和 let 聲明的變量可以不設置初始值,而 const 聲明的常量必須有初始值 ```javascript var a let b const c = 1 ``` #### 6. 指針的指向 --- let 和 const 都是 ES6 新增的語法,var 是 ES6 之前的語法 let 聲明的變量可以更改指針的指向,即可以重新賦值,而 const 聲明的常量則不行 ```javascript // 正確示例 let a = 1 a = 2 let b = { name: 'liang' } b = { name: 'wang' } const c = { name: 'liang' } c.age = 20 // 錯誤示例 const c = { name: 'liang' } c = { name: 'wang' } // 錯誤原因是因為改變了指針的指向 ``` #### 7. 塊級作用域解決的問題 --- 塊級作用域解決了 ES5 中的兩個問題: **一、內層變量可能覆蓋外層變量** ```javascript var tmp = 'hello' function test() { console.log(tmp) // undefined var tmp = 'mysql' } test() ``` **二、用來計數的循環(huán)變量泄露為全局變量** ```javascript for (var index = 0; index < 3; index++) { } console.log(index) // 3 for (let index = 0; index < 3; index++) { } console.log(index) // Uncaught ReferenceError: index is not defined ``` #### 8. var、let、const 的選擇 --- 對于 var 使用,需要明白一個事實,它所表現(xiàn)出來的特殊性: 作業(yè)域提升、window 全局屬性、沒有塊級作用域等都是一些歷史遺留問題,其實是 JavaScript 在設計之初的一種語言缺陷。市場上也在利用這種缺陷出一系列的面試題,來考察對 JavaScript 語言本身及底層的理解。在實際開發(fā)中,我們可以使用最新的規(guī)范來編寫,也就是不再使用 var 聲明變量了 優(yōu)先推薦使用 let 和 const,對于指針的指向不會改變的可以使用 const,指針指向可能會改變的變量使用 let 對于 let 和 const,會優(yōu)先推薦 const,這樣可以 **保證數據的安全性不會被隨意的篡改**,當明確知道一個變量后續(xù)會被修改指針的指向,這時候再使用 let,在其他很多語言里面也都是一種約定俗成的規(guī)范,我們盡量也遵守這種規(guī)范