ES6&Beyond是JS You don't know系列之一,如果说学JS有什么武林秘笈,那我推荐三本书,一本是JS高级程序设计第3版,另一本被国人翻译成JS忍者秘笈,还有就是这个系列书。
第一本打牢你扎实的语言基础,第二本给你灵魂上的升级,这个系列则是二者合体,内容全而透彻。如果说你还需要什么,那只剩下ES6语言规范了。今天开始撸ES6&Beyond. 笔记做完可能会做这个系列的翻译。
第一章 ES Now & Future
- 如果想用最新的特性,需要使用webpack这样的编译器,webpack会把ES6语法翻译成ES5。配合使用es6-shim/Polyfills,可以兼容旧的浏览器
- 一个例子:快速定义属性
var foo=[1,2,3]
var obj = {
foo
}
大家如果第一次看到这个代码,会很奇怪为什么{}里面有个foo,但它实际上是快速定义了一个foo属性,值也是foo而已,等同于下面代码:
var foo = [1,2,3];
var obj = {
foo: foo
};
- 未来的 JS语言演化会加快,比如一年出一个,如ES7。可以理解成特性集,大家可以早些了解和充分利用这些新特性。
第二章 语法
- 块级作用域,let,这个大家用的很多。let和var有个区别涉及前向引用,var是可以前向引用的,而let会报错,比如
{
console.log( a ); // undefined
console.log( b ); // ReferenceError!
var a;
let b;
}
变量a用console打印出来undefined,但b就会报ReferenceError
- let 用在for循环中还有个很重要的特性,如下:
var funcs = [];
for (let i = 0; i < 5; i++) {
funcs.push( function(){
console.log( i );
} );
}
funcs[3](); // 3
它会在每次迭代的时候为循环体新定义一个变量i,如果把let换成var,那么会输出5,而不是3,因为整体闭包中仅有一个i。其实上面的代码等同于下面
var funcs = [];
for (var i = 0; i < 5; i++) {
let j = i;
funcs.push( function(){
console.log( j );
} );
}
funcs[3](); // 3
- const用来定义常量,在使用const时必须赋值。const虽然定义的是常量,但严格意义上说,是禁止再次给这个变量赋值,而如果是对象,它本身的内容是可以改变的。比如一个const数组,可以插入和删除元素的。书中还提到const数组不会被垃圾回收
- 一个很好用的网站 http://www.es6fiddle.net, 可以在线编译ES6,方便学习ES6
- Spread/Rest 展开运算符/不定参数,也就是...运算符,这个运算符具体指展开运算符还是不定参数,要看使用场景。一个例子
function foo(x,y,z) {
console.log( x, y, z );
}
foo( ...[1,2,3] ); // 1 2 3
这个例子是在数组前面使用...运算符,表明展开数组中数据分别传给x,y,z三个变量,极大的简化了在函数中引用具体元素,否则得这样写
function foo(arr) {
console.log( arr[0], arr[1], arr[2] );
}
foo( [1,2,3] ); // 1 2 3
展开运算符还可以用在数组中间,比如:
var a = [2,3,4];
var b = [ 1, ...a, 5 ];
console.log( b ); // 1,2,3,4,5
这相当于[1].concat( a, [5]),即数组的连接操作。
对于展开运算符,书中没有提到对象的展开,其实是一样的,比如:
var a = {name:'zs', age:10};
var b = {...a, gender:'male'};
console.log(b.name, b.age, b.gender); // zs 10 male
另一个用法是不定参数,如下例:
function foo(x, y, ...z) {
console.log( x, y, z );
}
foo( 1, 2, 3, 4, 5 ); // 1 2 [3,4,5]
在上面这个例子中,x=1, y=2, 其余参数都做为数组传给了z,这就是不定参数,不是展开运算符。
- 默认参数,这个比较简单,不过功能很实用。
function foo(x = 11, y = 31) {
console.log( x + y );
}
foo(); // 42
foo( 5, 6 ); // 11
foo( 0, 42 ); // 42
foo( 5 ); // 36
foo( 5, undefined ); // 36 <-- `undefined` is missing
foo( 5, null ); // 5 <-- null 转换成 `0`
foo( undefined, 6 ); // 17 <-- `undefined` is missing
foo( null, 6 ); // 6 <-- null 转换成 `0`
这个例子演示了默认参数的写法,就是在参数后面跟赋值表达式,这儿可以是一个值,也可以是表达式,比如一个函数调用。如果在调用foo时y不传值或传undefined,那么y的值是31;对于x也一样,只是x必须传值而已。需要注意的是null不同于undefined,如果传null不会被认为没有传值,所以默认的值不会被应用,上面的foo(5, null)和foo(null, 6)就是这个场景。
未完 待续