zoukankan      html  css  js  c++  java
  • es6从零学习(四):Class的继承

    es6从零学习(四):Class的继承

     一:继承的方式

    1、Class 可以通过extends关键字实现继承

    class Point {
    }
    class ColorPoint extends Point {
      constructor(x, y, color) {
        super(x, y); // 调用父类的constructor(x, y)
        this.color = color;
      }
    
      toString() {
        return this.color + ' ' + super.toString(); // 调用父类的toString()
      }
    }
    

    constructor方法和toString方法之中,都出现了super关键字,它在这里表示父类的构造函数,用来新建父类的this对象

    子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。

    如果不调用super方法,子类就得不到this对象。这是因为:ES6 的继承机制完全不同,实质是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this

    2、在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错。

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

    这是因为子类实例的构建,是基于对父类实例加工,只有super方法才能返回父类实例。

    3、子类实例对象同时是父类和子类两个类的实例

    let cp = new ColorPoint(25, 8, 'green');
    
    cp instanceof ColorPoint // true
    cp instanceof Point // true
    

    上面代码中,实例对象cp同时是ColorPointPoint两个类的实例,这与 ES5 的行为完全一致。

    4、父类的静态方法,也会被子类继承。

    二:Object.getPrototypeOf()

    Object.getPrototypeOf方法可以用来从子类上获取父类

    Object.getPrototypeOf(ColorPoint) === Point
    // true
    

    因此,可以使用这个方法判断,一个类是否继承了另一个类。

    三:super 关键字

    super这个关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。

    1、super作为函数调用时,代表父类的构造函数

    class A {}
    
    class B extends A {
      constructor() {
        super();
      }
    }
    

    上面代码中,子类B的构造函数之中的super(),代表调用父类的构造函数。这是必须的,否则 JavaScript 引擎会报错。

    2、作为函数时,super()只能用在子类的构造函数之中,用在其他地方就会报错。

    class A {}
    
    class B extends A {
      m() {
        super(); // 报错
      }
    }
    

    3、super作为对象时,在普通方法中,指向父类的原型对象,在静态方法中,指向父类。

    class A {
      p() {
        return 2;
      }
    }
    
    class B extends A {
      constructor() {
        super();
        console.log(super.p()); // 2
      }
    }
    
    let b = new B();

    4、由于super指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super调用的

    class A {
          constructor() {
            this.x = 1
          }
        }
    
        class B extends A {
          constructor() {
            super()
            console.log(super.x) // undefined
          }
        }
        let p = new B()
    

    5、如果属性定义在父类的原型对象上,super就可以取到。

    class A {
          constructor() {
            this.x = 1
          }
        }
        A.prototype.x = 2
    
        class B extends A {
          constructor() {
            super()
            console.log(super.x) //2
          }
        }
        let p = new B()
    

    6、通过super调用父类的方法时,方法内部的this指向子类

    class A {
      constructor() {
        this.x = 1;
      }
      print() {
        console.log(this.x);
      }
    }
    
    class B extends A {
      constructor() {
        super();
        this.x = 2;
      }
      m() {
        super.print();
      }
    }
    
    let b = new B();
    b.m() // 2
    

    上面代码中,super.print()虽然调用的是A.prototype.print(),但是A.prototype.print()内部的this指向子类B,导致输出的是2,而不是1

    7、如果super作为对象,用在静态方法之中,这时super将指向父类,而不是父类的原型对象。

    class Parent {
      static myMethod(msg) {
        console.log('static', msg);
      }
    
      myMethod(msg) {
        console.log('instance', msg);
      }
    }
    
    class Child extends Parent {
      static myMethod(msg) {
        super.myMethod(msg);
      }
    
      myMethod(msg) {
        super.myMethod(msg);
      }
    }
    
    Child.myMethod(1); // static 1
    
    var child = new Child();
    child.myMethod(2); // instance 2
    

    super在静态方法之中指向父类,在普通方法之中指向父类的原型对象。

    8、使用super的时候,必须显式指定是作为函数、还是作为对象使用,否则会报错。

    class A {}
    
    class B extends A {
      constructor() {
        super();
        console.log(super); // 报错
      }
    }
    

    9、由于对象总是继承其他对象的,所以可以在任意一个对象中,使用super关键字

    var obj = {
      toString() {
        return "MyObject: " + super.toString();
      }
    };
    
    obj.toString(); // MyObject: [object Object]
    

      

    四:类的prototype和__proto__属性

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

    class A {
    }
    
    class B extends A {
    }
    
    B.__proto__ === A // true
    

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

    class A {
    }
    
    class B extends A {
    }
    
    B.prototype.__proto__ === A.prototype // true
    

      

  • 相关阅读:
    论文阅读笔记(四)【TIP2017】:Video-Based Pedestrian Re-Identification by Adaptive Spatio-Temporal Appearance Model
    论文阅读目录
    【学习】从.txt文件读取生成编译代码。
    页面显示其他电脑图片(局域网)
    控制台爬取小说(大王饶命)
    【自学】大话设计模式控制台
    将PDF转化为wrod
    【学习】爬糗事百科,可自动翻页。
    AHP(使用于某项目设备重要度评估测试)
    【学习】类重构、通用值交换、释放内存计算时间等
  • 原文地址:https://www.cnblogs.com/momozjm/p/8305679.html
Copyright © 2011-2022 走看看