隔了两周没有更新
今天开始整理ES6的知识
先来看看ES6增加的两个声明变量的关键字
let与const
我以前就写过一篇文章介绍了作用域的分类
传送门:理清JS中的词法、静态、动态、函数、块作用域
里面就谈到了块级作用域
在ES6之前
我们声明变量只能用var
并且作用域的机制是函数作用域(with关键字、catch子句是特例)
if(true){
var i = 1;
}
console.log(i); //输出:1
(function foo(){
var a = 1;
})();
console.log(a); //报错:a is not defined
(C/C++的作用域模式是块作用域)
ES6新增的let与const就可以将变量绑定到所在的任意作用域中(一般是 {….} 内部)
也就是说,let、const为声明的变量隐式劫持了所在的块作用域
与函数作用域类似
“块”内可以使用“块”外的变量
“块”外不能使用“块”内的变量
{
var a = 1;
let b = 2;
}
console.log(a); //1
console.log(b); //报错
上面我们复习了一下什么是块作用域
下面再来接着看看let产生的块级作用域有什么特点和优点
首先最重要的一点就是
使用let声明 不会有提升行为
下面就是var和let的区别
{
console.log(a); //undefined
var a = 1;
}
{
console.log(a);
let a = 1; //报错
}
既然let“劫持”了所在的块作用域
那么它声明的变量就会 统治所在块作用域
看这个例子
var a = 1;
{
console.log(a); //报错
let a = 2;
}
由于let的劫持,并没有打印1
而是报错a未定义
不仅如此,使用let 不能重复声明变量
{
var a = 1;
var a = 2;
console.log(a); //2
}
{
let a = 1;
let a = 2;
console.log(a); //报错:a已声明过
}
使用ES6的let或者说使用块作用域的好处是什么呢
首先变量进一步被限制在“块”中,可以防止变量污染
其次就是防止闭包产生的问题
for(var i = 0; i < 10; i++){
setTimeout(function(){
console.log(i);
}, 200);
}
由于闭包的原因
控制台打印了10个10
为了得到0~9
我们以前的做法通常是加一个立即执行函数
for(var i = 0; i < 10; i++){
(function(n){
setTimeout(function(){
console.log(n);
}, 200);
})(i);
}
这样通过增加中间函数作用域可以解决问题
但是let可以更好的解决
只需要把var换成let
for(let i = 0; i < 10; i++){
setTimeout(function(){
console.log(i);
}, 200);
}
这样每次迭代都会进行重新绑定的行为
ES6也引入了声明常量的关键字const
const拥有let的全部特点
包括劫持块作用域、无提升行为、不能重复声明等等
但是它用来声明常量
一旦声明就不能更改
const PI = 3.14;
PI = 555; //报错
所以使用const声明必须直接初始化
const PI;
PI = 555; //报错
关于const还有一点要注意
const foo = {
name: 'a',
arr: [1,2,3]
};
foo.name = 'b';
foo.arr.push(4);
console.log(JSON.stringify(foo));
引用值之所以可以改变
是因为我们在内存上拿到的是引用值的地址
和我们C/C++中的指针是一样的
我们修改引用值不该变它的地址
所以const并不能限制我们修改引用值
==主页传送门==