JS继承-五种继承实现方式 优点&缺点

1.原型链继承
优点:共享了父类构造函数的say方法
缺点1:不能向父类构造方法传参
缺点2:子类实例共享了父类构造函数的引用属性,比如arr属性

/*
原型链继承


*/
function Parent(name){
    this.name=name; //父亲
    this.arr=[1]
}
Parent.prototype.say=function(){
    console.log('hello')
}
function Child(like){
    this.like=like;
}

Child.prototype=new Parent();
Child.prototype.constructor=Child 

let boy1=new Child();
let boy2=new Child();

//优点:共享了父类构造函数的say方法
console.log(boy1.say(),boy2.say(),boy1.say===boy2.say)//undefined,undefined, true

//缺点1:不能向父类构造方法传参
console.log(boy1.name,boy2.name,boy1.name===boy2.name);//父亲,父亲,true

//缺点2:子类实例共享了父类构造函数的引用属性,比如arr属性
boy1.arr.push(2);
//修改boy1的arr属性,boy2的arr属性,也会变化,因为两个实例的原型上有了父类构造函数的实例属性arr;

console.log(boy2.arr)//[1,2]

//注意:修改boy1的name属性,是不会影响到boy2.name,因为设置boy1.name相当于在子类实例上新增了name属性

2.构造函数继承
优点1:可向父类构造函数传参
优点2:不共享父类构造函数的引用类型
缺点1:方法不能复用
缺点2:不能继承父类原型上的方法

/*
构造函数继承
*/
function Parent(name) {
    this.name = name;
    this.arr = [1];
    this.say = function () {
        console.log('hello')
    }
}


function Child(name,like) {
    Parent.call(this,name);//拷贝了父类的实例属性和方法
    this.like = like;
}

//优点1:可向父类构造函数传参
let boy1 = new Child('小红','apple');
let boy2 = new Child('小明','orange');

//优点2:不共享父类构造函数的引用类型
boy1.arr.push(2);
console.log(boy2.arr) //[1]

//缺点1:方法不能复用
console.log(boy1.say(), boy2.say(), boy1.say === boy2.say) //hello,hello,false

//缺点2:不能继承父类原型上的方法
Parent.prototype.walk=function(){
    console.log('我会走路')
}
boy1.walk;//undefined (说明实例不能获得父类原型上的方法)

3.组合继承
核心:通过调用父类的构造函数,继承父类的属性并保留传参的特点,然后通过将父类实例作为子类原型,实现函数复用
优点1:可向父类构造函数传参
优点2:不共享父类构造函数的引用类型
优点3:方法可以复用
缺点1:由于调用了2次父类的构造方法,会存在一份多余的父类实例属性

/*
组合继承
*/
function Parent(name) {
    this.name = name;
    this.arr = [1];
}
Parent.prototype.say = function () {
    console.log('hello')
}

function Child(name,like) {
    Parent.call(this,name);//拷贝了父类的实例属性和方法
    this.like = like;
}


Child.prototype = new Parent();
Child.prototype.constructor = Child


//优点1:可向父类构造函数传参
let boy1 = new Child('小红','apple');
let boy2 = new Child('小明','orange');


//优点2:不共享父类构造函数的引用类型
boy1.arr.push(2);
console.log(boy2.arr) //[1]

//优点3:方法可以复用
console.log(boy1.say(), boy2.say(), boy1.say === boy2.say) //hello,hello,true

//缺点1:由于调用了2次父类的构造方法,会存在一份多余的父类实例属性

组合继承优化1 解决了:由于调用了2次父类的构造方法,会存在一份多余的父类实例属性
/优点1:可向父类构造函数传参
优点2:不共享父类构造函数的引用类型
优点3:方法可以复用
缺点1:当修复子类构造函数的指向后,父类实例的构造函数指向也会跟着变了

/*
组合优化继承
解决了:由于调用了2次父类的构造方法,会存在一份多余的父类实例属性
*/
function Parent(name) {
    this.name = name;
    this.arr = [1];
}
Parent.prototype.say = function () {
    console.log('hello')
}

function Child(name,like) {
    Parent.call(this,name);//拷贝了父类的实例属性和方法
    this.like = like;
}


Child.prototype = Parent.prototype
Child.prototype.constructor = Child      //修复子类的构造函数指向


优点1:可向父类构造函数传参
let boy1 = new Child('小红','apple');
let boy2 = new Child('小明','orange');
let p1=new Parent('爸爸')

优点2:不共享父类构造函数的引用类型
boy1.arr.push(2);
console.log(boy2.arr) //[1]

优点3:方法可以复用
console.log(boy1.say(), boy2.say(), boy1.say === boy2.say) //hello,hello,true

缺点1:当修复子类构造函数的指向后,父类实例的构造函数指向也会跟着变了
console.log(p1.constructor)  //Child

没修复之前:console.log(boy1.constructor)//Parent
修复代码:Child.prototype.constructor = Child  
修复之后:console.log(boy1.constructor)//child
        console.log(p1.constructor) //Child(我们希望是parent)
 具体原因:修复的Child.prototype和Parent.prototype都是引用类型,指向同一块地址,对Child.prototype更改会引起Parent.prototype的修改。

4.寄生组合继承 对上述缺点进行优化 完美!

/*
组合优化继承
解决了:由于调用了2次父类的构造方法,会存在一份多余的父类实例属性
*/
function Parent(name) {
    this.name = name;
    this.arr = [1];
}
Parent.prototype.say = function () {
    console.log('hello')
}

function Child(name,like) {
    Parent.call(this,name);//拷贝了父类的实例属性和方法
    this.like = like;
}


Child.prototype = Object.create(Parent.prototype) //关键代码
Child.prototype.constructor = Child      //修复子类的构造函数指向


//优点1:可向父类构造函数传参
let boy1 = new Child('小红','apple');
let boy2 = new Child('小明','orange');
let p1=new Parent('爸爸')

//优点2:不共享父类构造函数的引用类型
boy1.arr.push(2);
console.log(boy2.arr) //[1]

//优点3:方法可以复用
console.log(boy1.say(), boy2.say(), boy1.say === boy2.say) //hello,hello,true

console.log(p1.constructor) //Parent

*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值