本篇是仿网易云音乐PC-总结的第三部分,Part3-ES6。本文总结的并非ES6全部内容,而是是在项目中运用到的ES6新特性,包括let、模板字符串、对象简洁表示法、解构赋值、数组查找、rest参数、扩展运算符、箭头函数、for…of循环、模块。本文对上述每个新特性,会介绍它的用法、特性、应用。
仿网易云音乐PC全部项目请戳->>>>> https://github.com/love3forever/gogo3
关于ES6
ES6已于2015年6月正式发布,是ECMAScript历史上最大的一次版本省级,代表JavaScript语言的下一代标准。我对ES6的理解是,它提供了许多全新的特性,把现代编程语言中比较流行的思想带入ECMAScript中来;它也包括一些语法糖,让语法更精简,更具有表现力。使用ES6,可以让代码更加简洁易懂、安全优雅。
let命令-声明变量
语法
let命令用法类似于var,用于变量声明,如:
|
|
特性-与var的区别
- 创建了块级作用域,let声明的变量仅在声明所在的{}代码块内有效
|
|
- 不存在变量提升
我们知道,var声明的变量,声明会提升到作用域顶端。比如下面代码执行后会在控制台输出undefined(变量声明但未赋值)而不是抛出ReferenceError错误(变量未声明)。
|
|
原因就是变量提升会使得上面的代码在实际运行时变为:
|
|
如果使用let进行变量声明,不存在变量提升,则会抛出ReferenceError错误。
- 存在暂时性死区
块级作用域内的使用let声明的变量,会绑定这个区域,不能再声明之前使用变量。
|
|
- 不允许重复声明
在同一个块级作用域内,let声明的变量只允许声明一次。
|
|
- 全局let变量不是全局对象的属性
var声明的全局变量会成为全局对象的属性,let声明的全局对象不会成为全局对象的属性。
|
|
应用
传统for循环的计数器使用let声明可以避免计数器泄露出循环。
事实上let可以完全代替var,let与var语义相同且没有副作用。
模板字符串
ES6以前,字符串由双引号或单引号包围,由于不能多行书写,当字符串较长时,会采用使用+运算符将多个字符串拼接成一个字符串。字符串字面量与变量拼接时也需要采取上述办法。这种写法繁琐且不方便,因此ES6引入了模板字符串解决这个问题。
语法
反引号``中包含字符串,在反引号中用${}包含变量或JavaScript表达式。
|
|
特性
- ${}中的内容可以是任意JavaScript表达式,所以静态字符串、变量、函数调用、算数运算等都可以写在其中
- 如果${}中表达式返回的不是字符串,则自动执行toString()方法
不会自动转义特殊字符,
中所有空格、新行、缩进等,都会被识别和保留。
对象简洁表示法
ES6运行直接斜土变量和函数作为对象的属性和方法。
语法
ES6允许对象只写属性名不写属性值,此时属性值等于属性名代表的变量。
|
|
解构赋值
ES5允许按照一定的模式,直接从数组、对象、字符串、数值、布尔值、函数参数等中提取值并赋值给变量。
语法
解构赋值的本质是模式匹配,等号左边的变量会寻找等号右边具有相同模式的值。如果是数组,则按位置和模式匹配;如果是对象,则按属性名和模式匹配。
|
|
特性
- 具有Iteration接口的数据结构都可以采用数组形式解构赋值
- 如果解构不成功,变量值为undefined
- 允许为变量指定默认值,默认值在等号右边的对应值===undefined的时候生效
应用
- 取得函数返回值
- 定义函数参数
- 快速提取JSON数据
本项目中提取从后端返回的JSON数据全部用的解构赋值方法,详见
https://github.com/love3forever/gogo3/blob/master/src/components/play-list.vue
line 190-197
数组查找
ES6数组实例的Array.find()和Array.findIndex方法用于找到数组中第一个符合要求的数组成员/位置,其参数为一个回调函数,所有数组成员依次执行回调函数直至找到第一个满足条件的成员。
语法
array.findIndex(function(value, index, arr), thisValue)
特性
- find和findIndex查找失败返回undefined和-1
- 对于空数组不会执行
- 不改变原数组
- 可以识别indexOf方法无法识别的NaN,具有更强的语义
rest参数
ES6引入rest参数,用于获取函数的多余参数。
语法
…变量名,变量为一个数组。也就是说,如果函数有多余参数,rest参数会将这些参数存放在这个数组中。如下:
|
|
rest参数可以替代arguments对象,并且由于rest参数中的变量是一个数组,因此这个变量可以使用所有数组的特有方法。
特性
- rest参数只能是最后一个参数,在它之后不可以存在其他参数
- 函数的length属性不包括rest参数
应用
- 与解构赋值结合生成数组12345//ES5var a = list[0],rest = list.slice(1);//ES6var [a,...rest] = list;
扩展运算符
扩展运算符…是rest参数的逆运算,它将一个数组转为用,分隔的参数序列。
语法
…变量名,变量名为一个数组。在数组前加入扩展运算符,可以将数组展开为参数序列。
|
|
特性
- 扩展运算符可以与正常的函数参数结合使用,无顺序要求
- 具有Iterator接口的对象,都可以使用扩展运算符//typeof obj[Symbol.iterator] === ‘function’
应用
- 在将数组转为参数序列时,可以取代apply、call方法
- 合并数组
|
|
- 将类数组的对象转化为数组
|
|
本项目中的例子详见
https://github.com/love3forever/gogo3/blob/master/src/components/generalComment.vue
line 119-135
箭头函数
ES6允许使用=>定义函数。
语法
( 参数 ) => { 函数体 }
- 只有一个参数时,参数可不加圆括号()
- 只有一条语句时,函数体可不加大括号{},并且可以省略return关键字
|
|
特性
- 不存在arguments对象,如有需要可以使用rest参数代替
- 一般函数的this指针指向使用是调用它的那个对象;箭头函数绑定了this指针,它总是指向函数定义时所在的对象。
- 不可以使用new命令作为构造函数
- 不可以使用yield命令
应用
- 立即执行函数可以写为箭头函数,这样表达更清楚简洁
- 需要使用函数表达式的场景、简单、单行、不会复用的函数,尽量使用箭头函数。由于箭头函数this指正总是指向函数定义时所在的对象,它修正了定义在函数中的函数的this指针指向问题。
在本项目中,所有响应服务器返回数据的函数都写为箭头函数
https://github.com/love3forever/gogo3/blob/master/src/components/play-list.vue
line 177-186
以及定义在函数中的函数修正this指针:
https://github.com/love3forever/gogo3/blob/master/src/components/mainleft.vue
line 111-137
for…of循环
ES6引入的for…of循环,可以遍历所有具有Iterator接口的对象,获取的是对象的键值。
语法
|
|
特性
- for…of循环获取的是键值而非键名或索引,如需获取索引,需要借助数组的entries或keys方法。
|
|
- 遍历数组时,只返回具有数字索引的属性,并且返回索引类型为number(for…in循环返回的是string)
- 对于类数组但不具有Iterator接口的对象,可以使用Array.from先将其转为数组
- 对于普通的不具有Iterator接口的对象,可以使用object.keys方法将对象的键名生成一个数组,然后遍历此数组;也可以直接将数组是Symbol.iterator属性直接赋给对象。
- 可以正确识别32位UTF-16字符
与其他循环比较
- 与foreach
foreach循环的实现效果与for…of一致,但break,return都无法生效,也就是说无法中途跳出。因此for…of可以完全代替foreach。 - 与for…in
for…in循环可以遍历没有Iterator接口的对象,而for…of不可以
for…in循环遍历的是键名,键名以字符串形式存在,而for…of遍历的是键值
for…in循环遍历的范围包括手动添加的其他键以及原型链上的键,而for…of不会
for…in循环在一些情况下不按照顺序遍历,而for…of不会
综上,for…in更适合于遍历对象而不适合遍历数组,for…of更适合于遍历数组以及具有Iterator接口的其他对象
本项目中for…of应用见
https://github.com/love3forever/gogo3/blob/master/src/components/play-list.vue line 187-218
模块
ES6在语言规格上实现了模块功能,通过显式输出指定代码,在需要是通过静态命令引入,就可以实现方法加载。这种实现方法可以在编译时就完成加载,比现有的规范更高效。模块部分详细内容参见
http://es6.ruanyifeng.com/#docs/module,这里不再详述了。