javascript一般认为有6种继承方法,但笔者将原型式继承归为一种对 “复制函数中的原型属性而不复制该函数的本地属性” 的实现方法,做为寄生式继承的一个实现步骤,在寄生式继承中实现。故本博文只排版了5种继承方法。
// 父类声明
function SuperClass(){
this.superValue = true;
this.referData = ['first', 'second', 'third'];
}
SuperClass.prototype.superPublicFunc = function(){
console.log(`I'm superClass!`);
}
一、原型链继承
- 实现: 将父类的实例赋值给子类的原型对象
function SubClass(){ this.subValue = true; } SubClass.prototype = new SuperClass(); // 父类的实例赋值给子类的原型对象 SubClass.prototype.constructor = SubClass; // 修正子类的构造器,指回子类对象
- 存在的问题: 父类数据类型为引用数据类型的公有属性会被子类所有实例共享
let o1 = new SubClass(); let o2 = new SubClass(); o1.referData[0] = 'modified'; console.log(o2.referData); // 'modified'
二、构造函数继承
- 实现: 借助
call()
在子类中将父类的公有属性和特权方法复制一遍。function SubClass(){ SuperClass.call(this); // 相当于调用SuperClass函数,将SuperClass中的公有属性和公有方法在SubClass中复制一遍 this.subValue = true; }
- 特点: 解决原型链继承中子类实例共享父类引用数据类型的公有属性的问题。
- 存在的问题: 构造函数继承不涉及父类原型,因此父类原型上的属性和方法无法被子类继承。
三、组合继承
- 实现: 原型链继承和构造函数继承的组合。父类的公有属性和特权方法使用构造函数继承;父类原型上的公有属性和公有方法使用原型链继承。
function SubClass(){ SuperClass.call(this); // 构造函数继承父类的公有属性和特权方法 this.subValue = true; } // 类式继承父类原型上是公有属性和公有方法 SubClass.prototype = new SuperClass(); SubClass.prototype.constructor = SubClass();
- 特点: 结合了原型链继承和构造函数继承各自的优点。
- 存在的问题:
(1)子类的原型是父类的实例(暂不知有何实际影响,望评论赐教,蟹蟹!)
(2)子类对象存在两份父类公有属性和特权方法数据SubClass.prototype instanceof SuperClass; // true
四、寄生式继承
- 描述: 本质是对原型链继承做了封装,用于继承父类原型上的公有属性和公有方法,同时忽略父类的对象公有属性和特权方法。
- 实现: 使用一个构造函数内容为空的过渡类来忽略父类的对象公有属性和特权方法
/** * 继承类的原型对象(忽略类的本地属性)。也称原型式继承。在此作为寄生式继承的一个步骤。 * @param {Object} _prototype: 父类的原型对象 */ function inheritObject(_prototype){ function F(){} // 过渡函数,其构造函数内容为空,对应新建的对象本地属性也为空 F.prototype = _prototype; return new F(); // 返回F的一个实例,该实例含有父类的原型,但本地属性为空 } /** * 寄生式继承父类原型上的公有属性和公有方法 */ function inheritPrototype(_subClass, _superClass){ let p = inheritObject(_superClass.prototype) // 使用原型链继承的方法,不同的是示例(p)中没有父类的对象公有属性和特权方法。 p.constructor = _subClass; // 修正子类的构造器,指回子类对象 _subClass.prototype = p; }
- 注: 并非完整的继承方法(缺少父类上的对象公有属性和特权方法),只是构成寄生组合式继承的一个部分。
五、寄生组合式继承——终极继承者
- 描述: 结合寄生式继承和构造函数继承。用构造函数继承来补齐寄生式继承所忽略父类的对象公有属性和特权方法。
- 实现: 父类原型上的公有属性和公有方法用寄生式继承;父类的对象公有属性和特权方法用构造函数继承。
function SubClass(){ SuperClass.call(this); // 构造函数继承父类的对象公有属性和特权方法 this.subValue = true; } inheritPrototype(SubClass, SuperClass); // 寄生式继承父类原型上的公有属性和公有方法
- 特点: 解决了组合式继承中子类对象存在两份父类公有属性和特权方法数据的问题。