[关闭]
@hotlp 2017-12-16T14:07:45.000000Z 字数 4145 阅读 713

ES6(ES2015)

培训文档


函数

1.默认值
之前我们写函数时如果要制定默认值要这样:

  1. function foo(x,y){
  2. if (typeof y === 'undefined') {
  3. y = 'bar';
  4. }
  5. ...
  6. }

在es6中,我们可以这样:

  1. function foo(x,y='bar'){
  2. ...
  3. // 但是 因为y被默认声明了,所以function里不能再用let,const
  4. let y = 1; // error
  5. const y = 2; // error
  6. }

甚至可以与解构结合使用:

  1. function foo({x,y='bar'}){
  2. ...
  3. }
  4. // 这样写再使用的时候必须传参,只有当函数foo的参数是一个对象时,变量x和y才会通过解构赋值生成
  5. foo({});

所以我们可以解构复制默认值和参数默认值一起用:

  1. function foo({x,y='bar'} = {}){
  2. ...
  3. }

有默认值的参数最好放在最后,如果放在前面,那么使用默认值的时候就要传undefined:

  1. function foo(x='bar',y){
  2. }
  3. foo(undefined,'hahaha') // 要这样用

2.rest参数
rest n. 剩余部分
用来获取函数的多余参数,这样就不用使用arguments这个伪数组了,而是一个真·数组:

  1. function add(...nums){
  2. console.log( nums instanceof Array) // true
  3. // Array.prototype.slice.call(arguments)
  4. let sum = 0;
  5. for (var val of nums) {
  6. sum += val;
  7. }
  8. return sum;
  9. }

需要注意的是rest参数只能是最后一个参数,不能这样:

  1. function foo(x,...nums,y){
  2. }

3.箭头函数
箭头函数是一个匿名函数,并且简化了函数的定义,先看一个例子:

  1. function oldAdd(x,y){
  2. return x+y
  3. }
  4. var sum = oldAdd(1,2);
  5. var newAdd = (x,y) => x+y
  6. var sum = newAdd(1,2)

参数的传递和原来完全一样,rest参数什么的也能继续使用,=>替换了原来的{}return(当然这只是在返回值只有一条语句的时候,多条语句还是要加{}return),如果返回值是一个对象的话还要加上()

  1. var foo = () => ({name:'张三',age:'13'})

但是箭头函数并不等于匿名函数,在使用时也有很多注意事项:
1.箭头函数函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
2.不能用作构造函数
3.没有arguments对象,用rest参数代替
在写比较复杂的函数时还是建议使用原有的方式而不是箭头函数

Set和Map

Set和Map是ES6新增的两种数据结构,与ES5对应一下的话,Set类似于数组,Map类似于对象。

Set

Set更像是一个没有重复元素的数组:

  1. const set = new Set([1, 1, 2, 2, 3, 3, 4, 4]);
  2. console.log(set)// {1,2,3,4}

但是没有数组中的方法,而是一些新增的方法:

  1. add(value):添加某个值,返回Set结构本身。
  2. delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
  3. has(value):返回一个布尔值,表示该值是否为Set的成员。
  4. clear():清除所有成员,没有返回值。
  5. // 遍历
  6. keys():返回键名的遍历器
  7. values():返回键值的遍历器
  8. entries():返回键值对的遍历器
  9. forEach():使用回调函数遍历每个成员

在ES5中,数组去重是什么样的?

  1. // 百度了一个号称最简单数组去重法
  2. function unique1(array){
  3. var n = [];
  4. for(var i = 0; i < array.length; i++){
  5. if (n.indexOf(array[i]) == -1) n.push(array[i]);
  6. }
  7. return n;
  8. }

而在ES6中:

  1. let array = [1,1,1,2,2,3,3,4,5,6,6];
  2. [...new Set(array)] // [1, 2, 3, 4, 5, 6]

向Set中加入新值的时候,判读新旧值是否相同不会发生类型转换,类似于===,不同的是NaN等于NaN

Map

Object本质上是键值对的集合,键只能是字符串,而Map是一种值值对的集合:

  1. let m = new Map();
  2. let o = {p: 'Hello World'};
  3. m.set(o, 'content')
  4. m.get(o) // "content"

Map比Set多了一个属性,size,size属性返回 Map 结构的成员总数。
新增(赋值),和取值使用setget方法。
实例化时可以使用任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构当做参数,比如数组:

遍历器(Iterator)是这样一种机制:它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。比如数组,字符串,set,map等。。。

  1. const map = new Map([
  2. ['name', '张三'],
  3. ['age', '20']
  4. ]);
  5. map.size // 2
  6. map.has('name') // true
  7. map.get('name') // "张三"
  8. map.has('age') // true
  9. map.get('age') // "20"

class

class这种写法看起来更java更c++,但是之前大家早就接触过相关的用法了,不知道大家还记不记得ninjia~~(想不起来的去面壁顺便重新学一下JavaScript面向对象编程

之前的ninjia是这样构造出来的:

  1. function Ninjia(name, weapon) {
  2. this.name = name;
  3. this.weapon = weapon;
  4. this.sayHello = function() {
  5. console.log(this.name + '向你发射了一把' + this.weapon);
  6. }
  7. }

那么现在:

  1. class Ninjia{
  2. constructor(name, weapon) {
  3. this.name = name;
  4. this.weapon = weapon;
  5. this.sayHello = function() {
  6. console.log(this.name + '向你发射了一把' + this.weapon);
  7. }
  8. }
  9. sayGoodbye(){
  10. console.log(this.name + '拿着他的' + this.weapon+'走开了');
  11. }
  12. }

constructor是类的默认方法,不写也会添加一个空方法;
在实例的时候,必须使用new,否则会报错,ES5中则不会报错;
不存在变量提升,不可以先new,再定义;

继承的写法:

  1. class OldNinjia extends Ninjia {
  2. constructor(name, weapon, age) {
  3. super(name, weapon); // 调用父类的constructor(name, weapon)
  4. this.age = age;
  5. this.sayAge = function(){
  6. console.log('I am ' + this.age+' years old');
  7. }
  8. }
  9. }

Class 可以通过extends关键字实现继承,比起ES5的那几种继承方式看起来更直观,更好懂。继承机制也不同:

ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。ES6 的继承机制完全不同,实质是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this。在调用super之前使用this会报错。

Module

模块功能主要由两个命令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
以下是几种常用的方法:

export

1,最基础,每次输出一个变量

  1. // soldiers.js
  2. export class Ninjia{
  3. constructor(name, weapon) {
  4. this.name = name;
  5. this.weapon = weapon;
  6. this.sayHello = function() {
  7. console.log(this.name + '向你发射了一把' + this.weapon);
  8. }
  9. }
  10. }
  11. export function SwordMan{
  12. this.name = name;
  13. ......
  14. }

2,比较推荐,输出多个变量,很清晰

  1. class Ninjia{
  2. constructor(name, weapon) {
  3. this.name = name;
  4. this.weapon = weapon;
  5. this.sayHello = function() {
  6. console.log(this.name + '向你发射了一把' + this.weapon);
  7. }
  8. }
  9. }
  10. function SwordMan{
  11. this.name = name;
  12. ......
  13. }
  14. export{Ninjia,swordMan}
  15. // 或者起个别名
  16. export{
  17. Ninjia as N,
  18. SwordMan as S
  19. }

import

  1. import {Ninjia, SwordMan} from './soldiers'; // 相对路径或绝对路径或模块名(需配置)
  2. var n = new Ninjia('小花','AK-47')
  3. // 整体加载
  4. import * as soldier from './soldiers';
  5. var n = new soldier.Ninjia('小花','AK-47');
  6. // 但是不允许对soldier操作,比如:
  7. soldier.num = 2;

export default

  1. // 输出时可以这样:
  2. // helloWorld.js
  3. export default function () {
  4. console.log('Hello World');
  5. }
  6. // 用的时候这样:
  7. import sayHello from './helloWorld';
  8. sayHello(); // Hello World

export default输出一个叫做default的变量或方法,然后在import时你可以为随便起个名字。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注