对象继承的方式
- 原型继承
- 构造函数继承
- 组合继承
- 寄居组合继承(当前最优继承方式)
4种继承形式的区别
使用方式 | 缺点 | |
原型继承 | 通过将子类的原型对象赋值为父类的对象实例, 继承父类的所有内容 例子: function Super(){} function Sub(){} Sub.prototype = new Super() | 原因:当子类原型对象中存在引用类型属性时,子类的所有对象实例将都共享这一属性。
结果: 当修改任意一个子类对象实例的引用属性将导致所有实例的引用型属性同时发生变化。
例子: function Super(){ this.arr = [1,2,3]; }
function Sub(){}
Sub.prototype = new Super()
var s1 = new Sub(); var s2 = new Sub(); s1.arr.push(4);
console.log(s1.arr); // [1,2,3,4] console.log(s2.arr); // [1,2,3,4] |
构造函数继承 | 通过在子类构造函数中调用apply或者call方法,继承父类构造函数中的属性和方法 例子: function Super(){ this.name = "super"; } function Sub(){ Super.apply(this); }
var s1 = new Sub();
| 通过apply调用父类构造函数的继承,子类无法继承父类的原型对象中的属性
例子:
function Super(){ this.name = "super"; }
Super.prototype.age = 12;
function Sub(){ Super.apply(this); }
var s1 = new Sub();
console.log(s1.age); // undefined
|
组合继承 | 将原型继承于构造继承结合起来,互补
例子: function Super(){ this.name = "super"; this.arr = [1,2,3]; } function Sub(){ Super.apply(this); }
Sub.prototype = new Super();
var s1 = new Sub(); var s2 = new Sub(); s1.arr.push(4);
console.log(s1.arr); // [1,2,3,4] console.log(s2.arr); // [1,2,3]
通过构造函数继承,在创建子类对象实例的时候创建引用类型属性,覆盖子类原型对象中对应的引用类型属性。同时,子类的原型对象也可以指向父类的原型对象。 | 缺点: 需要执行两次父类的构造函数,效率不够高。 |
寄居组合继承 | 直接举例: function Super(){
function inheritObject(sub,sup){
var s1 = new Sub(); var s2 = new Sub();
s1.arr.push (4);
console.log(s1.arr); // [1,2,3,4] console.log(s2.arr); // [1,2,3]
思路在于将父类的原型对象的副本赋值给子类的原型对象,这样就不需要执行两次父类构造函数。
最终,子类原型对象以及所有子类实例的constructor属性都指向子类的构造函数。 |
《javascript高级程序设计》对象继承章节阅读笔记