前言
let
和const
是ES6
新增特性,都可生成块级作用域(是指声明在花括号内的变量只在该区域内有效)。let
用来声明变量,const
用来声明常量(不可修改变量值,数组和对象除外);两者处了在用途有区分外,其他特性一致,如无变量提升、TDZ等。
let(const)
的出现可以解决的问题:
- 解决
ES5
中var
变量出现的变量提升; - 降低闭包使用出错的概率;
- 解决使用计数的
for
循环变量可能会导致的数据泄露; ES5
只有全局作用域和函数作用域(对应var
声明的全局变量和局部变量时),没有块级作用域(ES6
中{}
中的代码块)。同理只能在顶层作用域window
中和函数中声明函数,不能在块级作用域中声明函数;
一、let
和const
的特点:
-
let
和const
关键词声明的变量不具备变量提升的特效、存在暂时性的死区、只能在声明的位置后使用,同一块级作用域中不能反复声明同一变量名(子块级可以重复声明父块级变量),而var
变量可以重复声明; -
let
和const
声明只在最靠近的一个块(花括号内)中有效; -
使用
const
声明常量时候大写,const
在声明时必须赋值; -
const
声明的变量值并不是不能变的,而是变量指向的内存地址是不能变的,对于数值、字符串等简单类型的数据,值就保存在变量指向的内存地址上,因此等同于常量;但对于符合类型的数据(如数组和对象),变量指向的内存地址是一个指引,数据结构是否可变就不能控制了,所以将对象声明为常量必须非常小心;const newArr=[23,43,22,66]; newArr[0]=888; console.log(newArr); //[888, 43, 22, 66]```
二、let(const)
与let的区别
- 作用域
-
通过
var
关键字声明的变量无块作用域,在块{ }
内声明的变量,存在变量提升,可以从块之外进行访问; -
通过
let
关键字声明的变量有块作用域,在块{ }
内声明的变量无法从块外访问。```javascript function varTest() { var x = 1; { var x = 2; // same variable! console.log(x); // 2 } console.log(x); // 2 } --------------------------------------- function letTest() { let x = 1; { let x = 2; // different variable console.log(x); // 2 } console.log(x); // 1 } ```
- 变量提升 && 暂时性死区
-
通过
var
声明的变量存在变量提升,并被初始化为undefined
; -
通过
let
声明的变量没有变量提升,而且要求必须 等let
声明语句执行完之后,变量才能使用,不然会报Uncaught ReferenceError
错误;在代码块内,使用let
命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。{ console.log(aicoder); // undefined 因为有变量提升 var aicoder = 'aicoder.com'; } --------------------------------------------------------------- { console.log(aicoder); // Uncaught ReferenceError ... let aicoder = 'aicoder.com'; // 这里就可以安全使用aicoder }
- 重复声明
-
var
声明的变量可以重复声明; -
let
声明的变量不允许在相同作用域内重复声明, 所以也不能在有参函数声明中重复声明函数参数,否则会报错{ var a = 0; console.log(a); // 0 var a = 'sss'; console.log(a); // sss } { let a = 0; let a = 'sss'; // Uncaught SyntaxError: Identifier 'a' has already been declared }
注:
1) 在相同的作用域,或在相同的块中:
- 仅允许通过
var
重新声明var
变量; - 通过
let
重新声明一个var
变量是不允许的; - 通过
let
重新声明一个let
变量是不允许的; - 通过
var
重新声明一个let
变量是不允许的。
2) 在不同的作用域或块中:通过 let
或var
重新声明变量是允许的。
3) 不能在函数内声明参数。
- 生成window对象
- 通过 var 关键词定义的全局变量属于 window 对象;
- 通过 let 关键词定义的全局变量不属于 window 对象。
var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined
注:在ES5中顶层对象(在浏览器指的是window对象),顶层对象属性和全局变量是等价的。属性也可以动态创建变量,顶层对象的属性可以被随处读写不利于模块化编程;
而在ES6中,var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。