ES6 浅谈class继承机制

2019-03-21  本文已影响0人  宋乐怡

文章来源阮一峰ES6入门,这里做要点掌握大纲。
class——构造函数的语法糖
ES5的继承:修改原型链
先创造子类的实例对象,再将父类的方法添加到this(Parent.apply(this) )

ES6的继承:通过extends实现继承
先将父类实例 的属性方法加到this上(super),然后再用子类的构造函数修改this

  1. 子类必须在构造函数中调用super方法,用来创建父类的this对象。因为子类this通过父类构造函数塑造,得到和父类一样的实例属性和方法(实例属性和类的本身属性参考上一节class的基本语法。)不调用super,子类就得不到this。
    在子类的构造函数中,只有调用super之后才可以使用this 关键字,因为super 之后子类才有了自己的this。
  2. super关键字可以当函数使用也可以当对象使用。用法不同。必须显示指定super的数据类型
class A {}

class B extends A {
  constructor() {
    super();
    console.log(super.valueOf() instanceof B); // true,valueOf()返回该对象的原始值。
  }
}

let b = new B();

作为函数使用时,代表父类的构造函数,只能在子类构造函数中使用,super内部的this指向子类实例。

class A {
  constructor() {
    console.log(new.target.name);
  }
}
class B extends A {
  constructor() {
    super();
  }
}
new A() // A
new B() // B

作为对象使用时,在静态方法中指向父类,在普通方法中,指向父类原型对象。
注意:super指向父类的原型对象,而不是父类实例,所以父类实例上的属性方法无法通过super调用。(父类构造函数里this调用的属性方法就是实例属性方法)

class A {
  constructor() {
    this.p = 2;
  }
}

class B extends A {
  get m() {
    return super.p;
  }
}

let b = new B();
b.m // undefined

定义在父类实例上的属性应该是这样子

class A {}
A.prototype.x = 2;

class B extends A {
  constructor() {
    super();
    console.log(super.x) // 2
  }
}

let b = new B();

在普通方法中使用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

var obj = {
  toString() {
    return "MyObject: " + super.toString();
  }
};

obj.toString(); // MyObject: [object Object]
let cp = new ColorPoint(25, 8, 'green');

cp instanceof ColorPoint // true
cp instanceof Point // true
Object.getPrototypeOf(child) === parent
// true

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

(2)子类prototype属性的proto属性,表示方法的继承,总是指向父类的prototype属性。
我知道这张图可能不准确,但是这样记能让我一下子找到对应关系。

image.png
var p1 = new Point(2, 3);
var p2 = new ColorPoint(2, 3, 'red');

p2.__proto__ === p1.__proto__ // false
p2.__proto__.__proto__ === p1.__proto__ // true
image.png
这里有个作用就是通过子类的实例可以修改父类的实例
子类实例.proto.proto.attr = whatever;,修改父类,进而音箱父类的实例。
上一篇下一篇

猜你喜欢

热点阅读