1.原型链继承
简单来说就是让一个实列对象的__proto__属性(构造器函数的prototype属性)指向另外一个对象的实列,从而达到前一个实列对象能够使用后一个实列对象种的属性和方法。
代码说明
function Father() {
this.name = "jack"
}
const f = new Father()
function Son() {
this.sonname = "rose"
}
Son.prototype = f
const s = new Son()
console.log(s.name); //jack
console.log(s.sonname); //rose
在实例s中 并没有name属性,这边打印出jack是因为继承了Father的实列对象种的name属性。
这里注意更换Son.prototype属性需要在创建Son实例之前,否则无法继承Father中的name属性
画图说明
1.这是没有修改Son的protootype属性之前原型图
2.修改之后
优点:写法简单,容易理解
缺点:
1.对象实例共享所有继承的属性和方法,一个对象修改继承的属性和方法,所有实例对象都会修改
2.创建实例对象时,无法传递参数,因为子类无法使用父类的构造器传参
2.构造参数继承
function Fanther(name) {
this.name = name
}
function Son(sonname) {
Fanther.apply(this, [sonname])
}
const s = new Son("jack")
console.log(s.name); //jack
console.log(s.sonname); //undefined
const s2 = new Son("rose")
console.log(s2.name); //rose
在子构造函数当中使用call()、apply()、bind()方法修改this的指向,这里修改的时Father构造函数当中的this指向,指向为子对象实例
画图说明
修改this指向后,子类实例也可以继承父类构造函数当中的属性和方法,而不能继承父类构造函数原型对象中的属性和方法
优点:可以给父类构造器传递参数,每个实例对象中的属性和方法都是独有的,不和其他对象共享
缺点:不能继承父类构造器原型对象中的属性和方法
3.组合继承
组合继承是由原型链继承和构造函数继承的组合继承,解决了原型链中不能给父类构造函数传参的问题,也解决了构造函数继承中不能继承原型对象成员的问题
function Father(name) {
}
function Son(sonname) {
Father.call(this, name)
}
const f = new Father()
Son.prototype = f
const s = new Son()
这样s实例对象即可以给父类构造函数传参,也可以继承父类构造函数原型对象上的成员
画图说明
4.原型式继承
说到原型式继承,则必须要引用Object构造函数上的静态方法 Object.create()。该方法可以传一个参数,创建出来的对象会以该参数为原型对象来创建。
Object.create()底层代码
function object(obj){
function F(){} //创建一个构造函数
F.prototype = obj; //将传进来的参数对象重写构造函数的原型
return new F(); //返回出去一个F构造函数的实例对象
}
var person = {
name:'阿轩',
age:'20',
}
var obj = Object(person);
在来看代码
const father = {
name: "jack",
age: 16
}
const son = Object.create(father)
console.log(son.__proto__.__proto__.constructor);
和原型链继承存在关联
画图说明
缺点:引用类型的属性会被所有对象实例共享
5.寄生式继承
这种继承方法相当于对原型链继承的一种增强,给原型式继承方法添加一个功能,可以往对象上额外添加属性和方法
function createChild(parent) {
const child = Object.create(parent);
child.name = 'Child';
child.sayHello = function() {
console.log(`Hello, I'm ${this.name}`);
};
return child;
}
const parent = {
name: 'Parent'
};
const child = createChild(parent);
child.sayHello(); // 输出 "Hello, I'm Child"
画图说明
6.寄生组合式继承
这种继承方式式构造函数继承和原型式继承的组合,变相解决了原型式继承成员被所有对象
function SuperType(age){
this.color = 'red';
this.age = age;
}
SuperType.prototype.name = '阿轩';
function Type(age){
SuperType.call(this,age); //绑定this
}
Type.prototype = Object.assign(Type.prototype,SuperType.prototype)
Type.prototype.constructor = Type
var type = new Type(18);
console.log(instance.color)
console.log(instance.name)
console.log(instance.age)
这里用 Object.assign 去代替了 Object.create ,把父类的原型融入到子类的原型上,且以对象的形式放到 Type 的原型上,且这些原型一般是不会发生改变的,故即引用类型的属性始终会被继承所共享也是没有关系的,变相的解决了这些问题。