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