ECMAScript 6 学习笔记 (let & const)

ECMAScript 6是js的新标准,对js之前的很多语言缺陷做了一定规范。并且也提供了非常多好用的新特性。最重要的是,既然是新标准,那么各个浏览器的实现和node的实现,都是会往这个标准的方向发展。

let&const语法

let和const的语法其实特别简单,非常类似var。同时又修改了var的缺陷。

1
2
3
4
5
let num = 2;

const tree = {
name: 'tree'
}

上面代码中可以看出,let声明用法跟var非常类似。但被声明的变量,只在所在代码块内有效。
const所声明的变量,表示变量不可更改。

块级作用域

1. es6的块级作用域完美支持闭包。
看下例子

1
2
3
4
5
6
7
8
9
10
11
12
var array = [];
for (var index = 0; index < 10; index++) {
array[index] = (function(index) {
return function() {
return index;
}
})(index);
}

console.log(array[1]);

// result: 1

为了让function参数index不随着for循环变更,只能构造一个闭包。
相信新手非常难以理解,特别是有java,c等静态语言背景的人。这个确实是增加代码理解成本,也非常反人类。
于是到了es6 完全可以这样写

1
2
3
4
5
6
7
8
9
10
let array = [];
for (let index = 0; index < 10; index++) {
array[index] = function() {
return index;
};
}

console.log(array[1]());

// result: 1

这样代码复杂度明显下降,并且更加易读。

2. 没有变量提升(声明提升)

1
2
num; //ReferenceError 
let num;

在num声明之前调用,直接报错。

下面看个函数声明提升的bug

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var num = 1;

function foo() {
num = 2;
}

foo();
console.log(num);

function foo() {
num = 3;
}

// result: 3

非常诡异的bug。foo的第二次声明在整个执行之前就已经执行了,所以覆盖了foo的第一次声明。
虽然es6本身没有解决这个问题,但是我们可以用表达式的方式解决这个问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var num = 1;

var foo = function() {
num = 2;
}

foo();
console.log(num);

foo = function() {
num = 3;
}

// result: 2

3. 在同一块级作用域下不允许重复声明

1
2
3
4
5
6
let str = 'sss';
function foo() {
let str = 'bbb';
let num = 1;
let num = 2; // Error
}

上面的代码str两次声明都正确,因为不在同一块级作用域中,但是num的第二次声明会直接报错。

注意点

es6也有几个问题需要注意。

1. const声明的同时必须赋值

1
2
3
const num;  // Error

const tree = 1;

在const声明的时候,如果没有赋值,会直接报错。

2. const声明的对象的属性可以变更

const声明的变量所指向的是数据地址,而不是数据本身。
也就是意味着数据可以变更,但是变量指向的地址无法修改。
看下面代码就很清楚这之间的区别了

1
2
3
4
5
6
7
8
9
10
11
const num = {
a: 1
}

num.a = 2;

console.log(num.a); // result: 2

num = { // Error
a: 2
}

修改num的属性是可以的,但是给num赋新对象是不可以的。

3. 全局变量声明

let和const的声明在任何时候,都不会挂在到全局变量上(window/global)。

1
2
let a = 1;
console.log(window.a) // undefined

如果真的需要挂在到全局,可以显式给window的属性赋值。

小结

let和const优势明显,在开发环境能用es6的情况还是摈弃var,尽量采用let和const吧。