继承就是子类继承父类的特征和行为,避免重复代码提高代码复用性
JS的继承的原理就是用原型链
原型链继承的基本思想是父类的实例作为子类的原型
子类继承的是父类实例的属性方法和实例的原型对象,同时如果子类本身就有名称相同的属性和方法,优先自身的
缺点: 1、通过原型来实现继承时,原型会变成另一个类型的实例,原先的实例属性变成了现在的原型属性,该原型的引用类型属性会被所有的实例共享。 2、在创建子类型的实例时,没有办法在不影响所有对象实例的情况下给超类型的构造函数中传递参数。
基本思想: 在子类型的构造函数中调用超类型构造函数 核心: 使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类 优点: 1可以向超类传递参数 2解决了原型中包含引用类型值被所有实例共享的问题
缺点: 方法都在构造函数中定义,函数复用无从谈起,另外超类型原型 中定义的方法对于子类型而言都是不可见的。
组合继承指的是将原型链和借用构造函数技术组合到一块,从而发挥二者之长的一种继承模式。 基本思路: 使用原型链实现对原型属性和方法的继承,通过借用构造函数来实现对实例属性的继承,既通过在原型上定义方法来实现了函数复用,又保证了每个实例都有自己的属性。 特点:
既是子类的实例,也是父类的实例可传参函数可复用优点:
可以向超类传递参数每个实例都有自己的属性实现了函数复用缺点: 无论什么情况下,都会调用两次超类型构造函数: 一次是在创建子类型原型的时候,另一次是在子类型构造函数内部。
借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。
var parent = { names: ['a'] } function copy(object) { function F() {} F.prototype = object; return new F(); } var child = copy(parent);缺点:同原型链实现继承一样,包含引用类型值的属性会被所有实例共享。
缺点: 同原型链实现继承一样,包含引用类型值的属性会被所有实例共享。
创建一个仅用于封装继承过程的函数,该函数在内部以某种形式来做增强对象,最后返回对象。
function createObj (obj) { var clone = object.create(obj); clone.sayName = function () { console.log('hi'); } return clone; }缺点: 使用寄生式继承来为对象添加函数,会由于不能做到函数复用而效率低下。 同原型链实现继承一样,包含引用类型值的属性会被所有实例共享。
改进组合继承,利用寄生式继承的思想继承原型
function inheritPrototype(subClass, superClass) { // 复制一份父类的原型 var p = copy(superClass.prototype); // 修正构造函数 p.constructor = subClass; // 设置子类原型 subClass.prototype = p;} function Parent(name, id){ this.id = id; this.name = name; this.list = ['a']; this.printName = function(){ console.log(this.name); }}Parent.prototype.sayName = function(){ console.log(this.name);};function Child(name, id){ Parent.call(this, name, id); // Parent.apply(this, arguments);}inheritPrototype(Child, Parent);优点: 只调用了一次超类构造函数,效率更高。避免在 SuberType.prototype
上面创建不必要的、多余的属性,与其同时,原型链还能保持不变。因此寄生组合继承是引用类型最理性的继承范式。