上一篇:JS实现继承的方式原生版
ES6的继承
主要是依赖extends关键字来实现继承,且继承的效果类似于寄生组合继承。
class Parent() {
}
class Child extends Parent {
constructor(x, y, color) {
super(x, y);
this.color = color;
}
}
子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。
class Parent {
constructor() {}
}
class Child extends Parent {
constructor() {
this.num = 10//报错
super()
this.num = 10//正确写法
}
}
没有 constructor 会被默认添加,相当于 constructor(...args) { super(...args) }
super
super的使用方式:
1、当函数使用。作为函数调用时,代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次super函数。
super虽然代表了父类A的构造函数,但是返回的是子类B的实例,即super内部的this指的是B的实例,因此super()在这里相当于A.prototype.constructor.call(this)。
作为函数时,super()只能用在子类的构造函数之中,用在其他地方就会报错。
2、当对象使用。在普通方法中,指向父类的原型对象A.prototype;在静态方法中,指向父类。
// 当函数使用
class A {}
class B extends A {
constructor() {
super();
}
}
// 当对象使用,当对象使用时,相当于引用A原型上的方法。
class A {
p() {
return 2;
}
}
class B extends A {
constructor() {
super();
console.log(super.p()); // 2
}
}
let b = new B();
prototype和__proto__
类中:
子类的__proto__指向父类
子类prototype属性的__proto__指向父类的prototype属性
class A {
}
class B extends A {
}
B.__proto__ === A // true
B.prototype.__proto__ === A.prototype // true
实例中:
子类实例的__proto__的__proto__指向父类的__proto__。也就说子类实例的原型的原型指向父类实例的原型
class A {
}
class B extends A {
}
const a = new A();
const b = new B();
b.__proto__.__proto__ === a.__proto__ // true