js的继承有两种,一种是ES5继承,另一种是ES6的类继承。
ES5继承主要是是通过修改原型链来实现的继承。实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。Class的继承是通过external来继承,实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this。
继承后的原型链
class A {}
class B extends A {}
b.__proto__ === B.prototype
B.prototype.constructor === B;
B.__proto__ === A;
B.prototype.__proto__ === A.prototype
代码实现ES5继承
列举了主要的两种方式
- 常见的原型链继承
造成的问题:因为引用类型的原型属性会被所有实例共享,导致如果
Person里的this.name如果是引用类型的话,通过Man生成的实例都会共享,有一个实例修改,另一个实例拿到的结果也会变。
function Person(name) {
this.name = name;
this.getName = () => {
return this.name;
};
}
Person.prototype.setName = function(name) {
this.name = name;
};
function Man(name){
this.sex='male';
this.getSex = () => {
return this.sex;
};
}
//* 直接修改原型链
Man.protoType = new Person('参数');
Man.protoType.constructor = Man;
- 寄生式继承(推荐)
function Person(name) {
this.name = name;
this.getName = () => {
return this.name;
};
}
Person.prototype.setName = function(name) {
this.name = name;
};
function Man(name){
Person.call(this,name);//等同于class继承里的super作用
this.sex='male';
this.getSex = () => {
return this.sex;
};
}
const protoType = Object.create(Person.prototype);
protoType.constructor = Man;
Man.protoType = protoType;
Object.creat:这个方法接收两个参数:一个作用新对象原型的对象和(可选的)一个为新对象定义额外属性的对象;