详解ES6(一) - 区别var、let和const实现块级作用域

ES6之前的JavaScript变量由var声明,而var声明的变量是始终保存在内存中的,为了实现块级作用域,我们会使用闭包模拟,但实际上非常的不方便。ES6添加了let和const标识符,弥补了这些不足。

var和闭包

我们先来了解一下var和闭包,下面用花括号生成一个块级作用域,在其内创建变量count:

{
	var count = 5;
}
console.log(count);//5

我们可以看到在块级作用域外部仍然可以访问count变量。实际上这段代码等效为:

var count;
{
	count = 5;
}
console.log(count);//5

这就是说,变量count的声明被提升至函数顶部,而初始化操作仍旧留在原初执行。

如果想要模拟块级作用域,实际上我们要做的是在使用变量的时候为其赋值块级作用域的值。利用函数的特性(可以参考这里理解),再来看一下闭包:

(function(){
	var count = 5;
	console.log(count);//5
})();
console.log(count);//报错,count未定义

之所以如此,是因为函数过程是动态执行的,因此在函数内的变量是动态创建的。

let和const

ES6之后就不需要这么麻烦了,可以看下面这个例子:

{
	let count = 5;
	console.log(count);//5
}
console.log(count);//报错

总结一下,let和const声明的变量都是块级作用域,在块级作用域之外访问就会报错

此外,他们还有另一个特性,那就是不允许重定义,像下面这样就会报错:

var value = 30;
let value = 2;//报错,不能重复定义

const与let的区别在于:const必须初始化且只能初始化一次,若改变变量值就会报错。此外,const变量如果是对象,对象的属性可以修改。

另外我们需要注意一个特性,看下面的例子:

if(condition){
    console.log(typeof value);//引用错误
    let value = "blue";
}

但是这样写就不会报错:

console.log(typeof value);//"undeined"
if(condition){
    let value = "blue";
}

循环中的块作用域绑定

看下面的例子:

for(var i=0;i<10;i++){
	console.log(i);//0...9
}
console.log(i);//10
for(let i=0;i<10;i++){
	console.log(i);//0...9
}
console.log(i);//报错
for(const i=0;i<10;i++){
	console.log(i);//输出0后报错,因为const不能改变
}
console.log(i);//报错

但是const可以用在for-in或for-of中,不会报错,如下。

var obj = {a:true,b:true,c:true}
for(const key in obj){
	console.log(key);//a/b/c
}

全局块作用域绑定

当var被用于全局作用域时,它会创建一个新的全局变量作为全局对象(浏览器环境中的window对象)的属性。这样就有可能会出现下面的错误。

//在浏览器中
var RegExp = "Hello!";
console.log(window.RegExp );//"Hello!"

但使用let就不会出现这种错误。

//在浏览器中
let RegExp = "Hello!";
console.log(RegExp );//"Hello!"
console.log(window.RegExp === RegExp);//false

最后建议:默认使用const,只有确实需要修改变量时使用let。


猜你喜欢

转载自blog.csdn.net/qq_45467083/article/details/106499261