ES6之class的继承

class语法为咱们提供了构造函数的语法糖,响应的,也给咱们提供了ES5经过原型链实现继承提供了extends关键字实现继承。继承这个概念对面后台应该也是很是常见。bash

经过extends继承,语法:数据结构

class User{}函数

class Son extends User{}ui

继承以后Son可使用User类的全部属性和方法:this

class User{

    constructor(a){

        this.a = a;

        this.b = 10;

    }

    eat(){

        console.log('user eat');

    }

}

class Son extends User{

    constructor(b, c){

      super(b);

      this.c = c;

    }

    sum(){

        console.log(this.a, this.b, this.c);

    }

}

var son = new Son(1, 2);

son.eat();//user eat

son.sum();//1 10 2
复制代码

子类必须在constructor方法中调用super方法,不然新建实例时会报错。这是由于子类本身的this对象,必须先经过父类的构造函数完成塑造,获得与父类一样的实例属性和方法,而后再对其进行加工,加上子类本身的实例属性和方法。若是不调用super方法,子类就得不到this对象。spa

若是子类没有定义constructor方法,这个方法会被默认添加,须要注意的地方是,在子类的构造函数中,只有调用super以后,才可使用this关键字,不然会报错。这是由于子类实例的构建,基于父类实例,只有super方法才能调用父类实例。静态方法也会继承。prototype

经过Object.getPrototypeOf获取父类:code

class User{}

class Son extends User{}

console.log(Object.getPrototypeOf(Son));//class User{}
复制代码

Super关键字有两个用法,一个是函数,一个是对象。当作函数的时候只能在子类的构造函数中使用,子类必须调用,也就是constructor里面,其余地方会报错:cdn

class User{}

class Son extends User{

    eat(){

        super();

    }

}

//Uncaught SyntaxError: 'super' keyword unexpected here

复制代码

做为对象的时候,普通方法super指向父类的原型对象,在静态方法中指向父类;对象

class User{

  constructor(){

      this.a = 1;

      this.b = 1;

  }

  eat(){

      console.log(this.b);//10

      return 2

  }

}

class Son extends User{

   constructor(){

       super();

       this.b = 10;

       this.c = 20;

       console.log(super.c);//undefined

       console.log(this.c);//20

   }

   talk(){

       console.log(super.a);//undefined

       console.log(super.eat());//2

   }

}

var son = new Son();

son.talk();
复制代码

普通方法中,super指向父类原型对象(constructor里面是实例的属性),因此调用eat方法能够,a就获取不到。若是属性定义在父类的原型对象上,能够获取。子类调用super的时候,this指向当前子类的实例。对super赋值至关于为this赋值。

静态方法中,super指向父类,也就是User类:

class User{

    constructor(){

        this.a = 10;

    }

    static eat(val) {

        console.log('static', val);

    }

    eat(val) {

        console.log('instance', val);

    }

    static talk(){

        console.log(this.a);

    }

}



class Son extends User{

    constructor(){

        super();

        this.a = 20;

    }

    static eat(val) {

        super.eat(val);

    }

    eat(val) {

        super.eat(val);

    }

    static talk(){

        super.talk();

    }

}

Son.a = 30;

Son.talk();//30

Son.eat(1); // static 1

var son = new Son();

son.eat(2); // instance 2
复制代码

子类Static eat方法super指向父类,因此调用父类static eat方法,子类普通方法eat指向父类原型对象,因此调用父类普通方法eat。子类静态方法super内部this指向当前子类,而不是实例或者原型对象,因此子类Son调用talk方法,输出的是30。

使用super必须指定是函数仍是对象,不然报错。

类也是有prototype和__proto__属性的,相应的构成原型链:

子类的__proto__属性是构造函数的继承,指向父类

子类的prototype属性的__proto__属性,表示方法的继承,指向父类的prototype。

class User{}

class Son extends User{}

console.log(Son.__proto__ === User); // true

console.log(Son.prototype.__proto__ === User.prototype); // true
复制代码

由于类的继承是经过setPrototypeOf。

子类实例的__proto__属性的__proto__属性,指向父类实例的__proto__属性。也就是说,子类的原型的原型,是父类的原型:

class User{}

class Son extends User{}

console.log(Son.__proto__ === User.__proto__); // false

console.log(Son.__proto__.__proto__ === User.__proto__); // true
复制代码

原生的构造函数Boolean()、Number()、String()、Array()、Date()、Function()、RegExp()、Error()、Object()在ES5以前是没法继承的,ES6能够自定义原生数据结构:

class MyArray extends Array {

    constructor(...args) {

        super(...args);

    }

}

var arr = new MyArray();
复制代码

Misin模式就是把多个对象合成一个新的对象,新对象有各个组成的接口:

var a = {}

var b = {}

var c = {...a, ...b}
复制代码

阮大神提供了class的Mixin:

function mix(...mixins) {

    class Mix {

        constructor() {

            for (let mixin of mixins) {

                copyProperties(this, new mixin()); // 拷贝实例属性

            }

        }

    }

    for (let mixin of mixins) {

        copyProperties(Mix, mixin); // 拷贝静态属性

        copyProperties(Mix.prototype, mixin.prototype); // 拷贝原型属性

    }

    return Mix;

}

function copyProperties(target, source) {

    for (let key of Reflect.ownKeys(source)) {

        if ( key !== 'constructor'

            && key !== 'prototype'

            && key !== 'name'

        ) {

            let desc = Object.getOwnPropertyDescriptor(source, key);

            Object.defineProperty(target, key, desc);

        }

    }

}
复制代码

使用:

class DistributedEdit extends mix(Loggable, Serializable) {// ...}
复制代码

建议可使用了看看打印的数据。

相关文章
相关标签/搜索