[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 声明变量之前,该变量都是不可用的,这在语法上称为 **暂时性死区**,var 声明的变量不存在 **暂时性死区** ```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() ``` **二、用来计数的循环变量泄露为全局变量** ```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 使用,需要明白一个事实,它所表现出来的特殊性: 作业域提升、window 全局属性、没有块级作用域等都是一些历史遗留问题,其实是 JavaScript 在设计之初的一种语言缺陷。市场上也在利用这种缺陷出一系列的面试题,来考察对 JavaScript 语言本身及底层的理解。在实际开发中,我们可以使用最新的规范来编写,也就是不再使用 var 声明变量了 优先推荐使用 let 和 const,对于指针的指向不会改变的可以使用 const,指针指向可能会改变的变量使用 let 对于 let 和 const,会优先推荐 const,这样可以 **保证数据的安全性不会被随意的篡改**,当明确知道一个变量后续会被修改指针的指向,这时候再使用 let,在其他很多语言里面也都是一种约定俗成的规范,我们尽量也遵守这种规范