1 变量声明及变量提升机制(Hosting)
var
无论在函数左右阈还是全局作用域中声明,都会被当成在当前作用域顶部声明的变量;块级声明:ES6中引入块级作用域
1.1 let
声明
let
声明的用法与var
一致,let
声明的变量可以把变量限制在作用域的代码中。
同时,let
关键字声明不允许重复声明同一变量标识符。
var count = 1;let count = 1; //抛出语法错误复制代码
但是,如果当前作用域内嵌在另一个作用域中,便可以在内嵌作用域中用let
声明同名变量了。
var count = 1;if (condition) { let count = 1; // 不会抛出语法错误,let在内部作用域内会遮蔽全局作用域中的count}复制代码
1.2 const
声明
const
声明的是常量,起止一旦设定后不可修改。因此,const
常量声明是必须进行初始化。常量也不会被提升至作用域顶部。常量也不可以重复声明变量,无论该变量是var
或者let
声明的。
const
与let
const
与let
都是块级标识符,常量也只在当前代码块内有效,一旦执行到块外作用域其就会被立即销毁。唯一的不同是,无论严格模式还是非严格模式,变量不可以被再次赋值。
const
声明的对象,不允许修改绑定,但可以修改值。
const person = { name: 'a'}person.name = 'b' //可以修改person = { // 抛出语法错误 name: 'b'}复制代码
1.3 临时死区(Temporal Dead Zone)
通过两端代码理解
if (condition) { console.log(typeof value) // ReferenceError: condition is not defined let value = 'hello'}复制代码
console.log(typeof value) // "undefined"if (condition) { let value = 'hello'}复制代码
由于const
与let
声明的变量不会被提升到作用域顶部,如果在改作用域内在变量声明前访问该变量,则触发语法错误。因为,此时变量value
还处于社区所谓的临时死区(TDZ)中。Javascript引擎在扫描代码发现变量声明时,要么将他们提升至作用域顶部(var
),要么将声明当道TDZ中。访问TDZ中的变量会触发运行时错误,之有执行过变量声明语句后, 变量才会从TDZ中移出,才能被正常访问。
2. 块级作用与循环
let
可以较好的替换for
循环中闭包的方式
在for-in
或 for-of
循环使用中使用const的行为与let
一致,唯一的区别是不能改变循环的key值,
3. 作用域与全局域绑定
var在全局作用域时,声明的变量可能会覆盖一个已经存在的全局变量。及时这个全局变量定义在window
上,也不能幸免。但如果再全局作用域中使用let
或const
,会在全局作用域下创建一个新的绑定,该绑定不会添加为全局对象的属性,不会覆盖只会遮蔽。
//浏览器中var RegExp = 'test';console.log(window.RegExp); // ‘test’var ncz = 'Hi'console.log(window.ncz); // 'Hi'复制代码
let RegExp = 'test';console.log(window.RegExp); // ‘test’const ncz = 'Hi'console.log(window.ncz); // 'Hi'复制代码
如果在浏览器中跨frame
或者 window
访问代码,仍然可以使用 var
4 用let
还是const
当前使用块级绑定的最佳实践是:默认使用const
,只在确实需要改变变量值时使用let
.