JS如何实现继承
第一种使用call。
但是这种方法会存在函数不能使用问题,引出下面方法。
第二种使用原型链
这种方法是利用原型链,那么会存在共享问题,既然都共享一个原型那么修改其中的数组那么其他实例也会跟着变
var s1 = new Child2();
var s2 = new Child2();
s1.play.push(4);
console.log(s1.play, s2.play);
// (4) [1, 2, 3, 4] (4) [1, 2, 3, 4]
其中父类也跟着变了
第三种:call和原型链组合(将前两种组合)
function Parent3 () {
this.name = 'parent3';
this.play = [1, 2, 3];
}
function Child3() {
Parent3.call(this);
this.type = 'child3';
}
Child3.prototype = new Parent3();
var s3 = new Child3();
var s4 = new Child3();
s3.play.push(4);
console.log(s3.play, s4.play);
此时尝试在父类添加方法是可以直接使用的
那么之前俩种的方法问题都解决了,这里又多了Parent3构造函数会执行一次
Child3.prototype = new Parent3();
第四种: 组合继承的优化1
function Parent4 () {
this.name = 'parent4';
this.play = [1, 2, 3];
}
function Child4() {
Parent4.call(this);
this.type = 'child4';
}
Child4.prototype = Parent4.prototype;
var s3 = new Child4();
var s4 = new Child4();
console.log(s3)
注意红线这里,child4实例的构造函数是parent4,这是错的,应该是它自己本身child4才对
第五种: 组合继承的优化2-寄生组合继承(Extend原理)
function Parent5 () {
this.name = 'parent5';
this.play = [1, 2, 3];
}
function Child5() {
Parent5.call(this);
this.type = 'child5';
}
Child5.prototype = Object.create(Parent5.prototype);
Child5.prototype.constructor = Child5;
ES6中的extend 被bable编译后就是使用的寄生继承。
总结
- call继承-问题》父类中的函数无法使用
- 原型链继承-问题》如果改了原型属性则会影响所有实例
- call+原型链-问题》多执行一次构造函数
- 寄生继承1-问题》实例的构造函数是父类的
- 寄生组合继承》extend