JavaScript的继承方式
提示:仅是个人总结,可能有误
原型链继承
父类实例作为子类原型对象
- 优点:继承了父类的模板,又继承了父类的原型对象
- 缺点:无法实现多继承,来自原型对象的所有属性被所有实例共享,修改时会影响父类属性;
/*直接继承父类的原型对象,原型对象的constructor应该指向其构造函数,所
以必须写第二行代码;*/
Child.prototype = new Parent();
Child.prototype.constructor = Child;
构造函数继承
在子类构造函数中使用 call() 调用父类构造函数
- 优点:解决了原型链继承中不能传参且引用值共享问题。
- 缺点:只是继承了父类实例对象的属性,子类原型本身没有改变,不能调用父类原型上的方法,因为 Children.prototype 和 Parent.prototype 根本没有任何关系
/*在Children类中调用,相当于把Parent中的this替换为Children的this,创
建Children实例时就相当于运行Parent构造函数,但是此时Parent中的this
就是Children中的this,最后就等价于是Children声明的实例相当于每个子
类都有父类实例的副本;*/
function Children(){
Parent.apply(this, arguments);
}
组合继承(原型链+构造函数继承)
同时书写原型链继承和构造函数继承即可实现
- 优点:解决了原型链继承中不能传参且引用值共享问题以及构造函数继承无法访问父类原型方法的问题。
- 缺点:调用两次父类构造函数,占用内存;
原型式继承
创建了一个临时性的构造函数,然后将传入的对象作为这个构造函数的原型,最后返回这个临时类型的一个新实例,本质上是一次浅复制;
- 缺点:无法复用函数;
/*//不能直接Children.prototype = Parent.prototype,如果使用,另一
个子类也继承 Parent的话,如果Children或者该子类修改了他们对应的原型上
的方法的话,另外一个类的实例也会受到影响*/
function object(o) {
function F(){};
F.prototype = o;
return new F();
}
//使用
const parentObj = new Parent()
const childrenObj = object(parentObj)
寄生式继承
在原型式继承的基础上再次包装;
- 优点:解决了原型式继承无法实现复用的问题;
function object(o) {
function F(){};
F.prototype = o;
return new F();
}
function Children(o) {
var clone = object(o);
clone.sayHi = function(){ // 增强对象,用于添加属性或方法
console.log('hello, world');
}
return clone; // 返回新对象
}
//使用
const parentObj = new Parent()
const childrenObj = Children(parentObj)
寄生组合式继承
- 优点:解决了组合继承调用两次父类构造函数的问题;
function object(o) {
function F(){};
F.prototype = o;
return new F();
}
var o = object(Parent.prototype)//继承父类原型
function Children(){
Parent.call(this)//继承父类构造函数的属性
}
Children.prototype = o;
o.constructor = Children
const parentObj = new Parent()
希望对您有帮助!!!