ES6 class的继承

1.class继承简介

  • 1.1class可以同过extends关键字来实现继承。

      	{
      class Point {
    
      }
    
      class ColorPoint extends Point{
    
      }
      }
    
  • 1.2子类必须再constructor方法中调用super方法,否则新建实力会报错。这是因为子类没有自己的this对象,而是继承父类的this对象。
    {
    class Point {

      }
    
      class ColorPoint extends Point{
          constructor(){
              //没有使用super关键字
          }
      }
    
      let cp1 = new ColorPoint();
      //ReferenceError
      //Must call super constructor in derived class 
      //before accessing 'this' or returning from derived constructor
    

    }

  • 1.3 ES5 和 ES6的区别
    ES5继承的实质是先创造子类的实例对象this,然后将弗雷德方法添加到this上去。(parent,app(this))
    ES6的实质是先创造父类的实例对象this,然后再用子类的构造方法修改this。

  • 1.4再子类的构造函数中,只有调用super之后才可以使用this关键字。

         {
      class Point {
      constructor (x,y){
          this.x = x;
          this.y = y;
      }
    
      sum(x,y){
          return x + y;
      }
       }
    
       class ColorPoint extends Point {
      constructor(x,y,color){
          // this.color = color;  
          //ReferenceError
          super(x,y);
          this.color = color;
      }
    

    }

    let cp = new ColorPoint(2,10,‘red’);
    //cp ColorPoint {x: 2, y: 10, color: “red”}
    cp.sum(2,3);
    //5
    }

  • 1.5 子类的实例同时是子类和父类的实例。

       {
      cp instanceof ColorPoint
      //true
      cp instanceof Point
      //true
    

    }

2.Object.getPrototypeOf()

Object.getPrototypeOf()可以从子类上获取父类
{
Object.getPrototypeOf(ColorPoint) === Point
//true
}

3.super关键字

super这个关键字既可以当作函数使用也可以当作对象使用。

  • 3.1 super作为函数调用时代表父类的构造函数。
    ES6规定子类constructor必须执行一次super函数
    super代表了父类的构造函数,但是返回的是子类的实例,即super内部的this指向子类,因此super相当于

       {
      A.prototype.constructor.call(this);
      }
    
      {
      class A {
          constructor () {
              console.log(new.target.name);
          }
      }
    
      class B extends A {
          constructor(){
              super();
          }
      }
    
      let p1 = new A();  //A
    
      let p2 = new B();  //B
    

    }

    // 上面的代码中,new.target指向当前正在执行的函数。可以看到super执行时内部的this指向B

  • 3.2 super作为对象时在普通方法中指向父类的原型对象;在静态方法中指向父类。

       {
      class A {
          constructor () {
              
          }
    
          sayName(){
              return 'name'
          }
      }
    
      class B extends A {
          constructor(){
              super();
              console.log(super.sayName());
          }
    
      }
      new B();
      //name
      console.log(A.prototype.sayName());
      //name
    

    }

    //这时候就是将super当作一个对象来使用,指向A。prototype,所以super.p()相当于A.prototype.p()

4.类的prototype属性和__proto__属性

  • 4.0 ES5中每一个对象都有__proto__属性指向对应的构造函数的protype属性,
    ES6同时又prototype属性和__proto__属性,所以存在两条继承链。

  • 4.1 子类的__proto__属性表示构造函数的继承,总是指向父类。

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

    {
    class A {

      }
    
      class B extends A {
    
      }
    
      console.log(B.__proto__ === A); //true
      console.log(B.prototype.__proto__ === A.prototype)  //true
      console.log(B.constructor === Function);  //true
    

    }

  • 4.3 类的继承的模式实现
    {
    class A {}

      class B {}
    
      //B的实例继承A的实例
      Object.setPrototypeOf(B.prototype, A.prototype)
    
      //B的实例继承A的静态属性
      Object.setPrototypeOf(B,A);
    
      console.log(B.__proto__ === A); //true
      console.log(B.prototype.__proto__ === A.prototype)  //true
    
    
      //Object.setPrototypeOf的实现
      Object.setPrototypeOf = function (obj, proto){
          obj.__proto__ = proto;
          return obj;
      }
    

    }

  • 4.4 extends的继承目标只要有Prototype的属性的函数就能被继承。

  • 4.5 实例的__proto__属性
    子类实例的__proto__属性的__proto__属性指向父类的__proto__属性;
    子类原型的原型就是父类的原型。
    {
    class A {}

      class B extends A {
          constructor(){
              super()
          }
      }
    
      let a1 = new A();
      let b1 = new B();
      console.log(b1.__proto__.__proto__ === a1.__proto__)
      //true
    

    }

  • 5.Mixin模式的实现
    Mixin模式指的是将多个类的接口"混入"另外一个类。ES6如下实现
    {
    function mix(…mixins){
    class Mix {}

          for(let mixin of mixins){
              copyProperties(Mix,mixin);
              copyProperties(Mix.prototype, mixin.prototype);
          }
          
          return Mix;
      }
    
      //copyProperties
    
      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 objToClass extends mix(obj1,obj2){
    
      }
    

    }

    // 上面的mix函数可以将多个对象合并为一个类.使用的时候继承这个类就好了。

  • 参考文献<ES6标准入门>

发布了85 篇原创文章 · 获赞 16 · 访问量 6102

猜你喜欢

转载自blog.csdn.net/qq_43955202/article/details/104420763