JS实现继承的几种方式
原型链继承
function A(name,age){
this.name =name;
this.age =age;
this.happy=['跳舞','篮球','喝酒']
}
A.prototype.say=function(){
console.log('我是'+this.name+'我喜欢'+this.happy);
}
function B(){
}
B.prototype =new A('zf',18);
let Bb =new B();
console.log(Bb.name,Bb.age);
Bb.say();
结果
原型链继承的问题:属性以堆的形式存在的,都发生变化,基础类型类型不发生变化。
let Ba =new B();
let Bb =new B();
Bb.happy.push('唱歌');
Bb.name='李四';
console.log(Ba.name,Bb.name);
console.log(Ba.happy,Bb.happy);
Bb的name发生改变,Ba的name没有改变, Bb数组里添加了值,Ba一起改变。
构造函数继承
function A(name,age){
this.name =name;
this.age =age;
this.happy=['跳舞','篮球','喝酒']
}
A.prototype.say=function(){
console.log('我是'+this.name+'我喜欢'+this.happy);
}
function B(name,age){
A.call(this,name,age)
}
let Ba =new B('zf' ,18);
let Bb =new B('zff',188);
console.log(Ba.name,Ba.age);
console.log(Bb.name,Bb.age);
Bb.happy.pop();
console.log(Ba);
console.log(Bb);
结果:
构造函数使父类的引用属性不会被共享,但是只能继承父类的实例属性和方法,不能继承原型的属性或者方法。
组合继承
结合原型链继承和构造函数继承
function A(name,age){
this.name =name;
this.age =age;
this.happy=['跳舞','篮球','喝酒']
}
A.prototype.say=function(){
console.log('我是'+this.name+'我喜欢'+this.happy);
}
function B(name,age){
A.call(this,name,age)
}
B.prototype =new A();
let Ba =new B('zf' ,18);
let Bb =new B('zff',188);
console.log(Ba.name,Ba.age);
console.log(Bb.name,Bb.age);
Bb.happy.pop();
console.log(Ba);
console.log(Bb);
结果: 即继承了属性和方法,也继承了原型的属性和方法 缺点:性能不好,实例化过多
寄生组合继承
不再实例化A ,创建一个新的对象,指向A的prototype
function A(name,age){
this.name =name;
this.age =age;
this.happy=['跳舞','篮球','喝酒']
}
A.prototype.say=function(){
console.log('我是'+this.name+'我喜欢'+this.happy);
}
function B(name,age){
A.call(this,name,age);
}
B.prototype=Object.create(A.prototype);
let Ba =new B('zf' ,18);
let Bb =new B('zff',188);
console.log(Ba.name,Ba.age);
console.log(Bb.name,Bb.age);
Bb.happy.pop();
console.log(Ba);
console.log(Bb);
结果: