这种模式父类的属性、方法一开始就是定义好的,无法向父类传参,不够灵活。
sonFn.prototype = new fatherFn() 借用构造函数继承(call) function fatherFn(...arr) { this.some = '父类的this属性'; this.params = arr // 父类的参数 } fatherFn.prototype.fatherFnSome = '父类原型对象的属性或者方法'; function sonFn(fatherParams, ...sonParams) { fatherFn.call(this, ...fatherParams); // 核心步骤: 将fatherFn的this指向sonFn的this对象上 this.obkoro1 = '子类的this属性'; this.sonParams = sonParams; // 子类的参数 } sonFn.prototype.sonFnSome = '子类原型对象的属性或者方法' let fatherParamsArr = ['父类的参数1', '父类的参数2'] let sonParamsArr = ['子类的参数1', '子类的参数2'] const sonFnInstance = new sonFn(fatherParamsArr, ...sonParamsArr); // 实例化子类 console.log('借用构造函数子类实例', sonFnInstance) 借用构造函数继承的子类实例 借用构造函数继承做了什么?声明类,组织参数等,只是辅助的上下文代码,核心是借用构造函数使用call做了什么:
一经调用call/apply它们就会立即执行函数,并在函数执行时改变函数的this指向
fatherFn.call(this, ...fatherParams);在子类中使用call调用父类,fatherFn将会被立即执行,并且将fatherFn函数的this指向sonFn的this。
因为函数执行了,所以fatherFn使用this声明的函数都会被声明到sonFn的this对象下。
实例化子类,this将指向new期间创建的新对象,返回该新对象。
对fatherFn.prototype没有任何操作,无法继承。
该对象的属性为:子类和父类声明的this属性/方法,它的原型是
PS: 关于call/apply/bind的更多细节,推荐查看我的博客:js基础-面试官想知道你有多理解call,apply,bind?[不看后悔系列]
借用构造函数继承的优缺点优点:
可以向父类传递参数
解决了原型链继承中:父类属性使用this声明的属性会在所有实例共享的问题。
缺点:
只能继承父类通过this声明的属性/方法,不能继承父类prototype上的属性/方法。
父类方法无法复用:因为无法继承父类的prototype,所以每次子类实例化都要执行父类函数,重新声明父类this里所定义的方法,因此方法无法复用。
组合继承(call+new)原理:使用原型链继承(new)将this和prototype声明的属性/方法继承至子类的prototype上,使用借用构造函数来继承父类通过this声明属性和方法至子类实例的属性上。
function fatherFn(...arr) { this.some = '父类的this属性'; this.params = arr // 父类的参数 } fatherFn.prototype.fatherFnSome = '父类原型对象的属性或者方法'; function sonFn() { fatherFn.call(this, '借用构造继承', '第二次调用'); // 借用构造继承: 继承父类通过this声明属性和方法至子类实例的属性上 this.obkoro1 = '子类的this属性'; } sonFn.prototype = new fatherFn('原型链继承', '第一次调用'); // 原型链继承: 将`this`和`prototype`声明的属性/方法继承至子类的`prototype`上 sonFn.prototype.sonFnSome = '子类原型对象的属性或者方法' const sonFnInstance = new sonFn(); console.log('组合继承子类实例', sonFnInstance) 组合继承的子类实例从图中可以看到fatherFn通过this声明的属性/方法,在子类实例的属性上,和其原型上都复制了一份,原因在代码中也有注释:
原型链继承: 父类通过this和prototype声明的属性/方法继承至子类的prototype上。
借用构造继承: 父类通过this声明属性和方法继承至子类实例的属性上。
组合继承的优缺点优点:
完整继承(又不是不能用),解决了:
父类通过this声明属性/方法被子类实例共享的问题(原型链继承的问题)
每次实例化子类将重新初始化父类通过this声明的属性,实例根据原型链查找规则,每次都会
父类通过prototype声明的属性/方法无法继承的问题(借用构造函数的问题)。
缺点:
两次调用父类函数(new fatherFn()和fatherFn.call(this)),造成一定的性能损耗。
因调用两次父类,导致父类通过this声明的属性/方法,生成两份的问题。
原型链上下文丢失:子类和父类通过prototype声明的属性/方法都存在于子类的prototype上
原型式继承(Object.create()) 继承对象原型-Object.create()实现