JS面向对象 继承的几种方式

1. 借助构造函数实现继承

function Parent1() {
    this.name = 'Parent1';
}

Parent1.prototype.say = function() {
    console.log('你好');
}

function Child1() {
    Parent1.call(this); // !!!关键点 apply也可以
    this.type = 'child1';
}

let s1 = new Child1();

console.log(s1);
s1.say(); // 此处会报错

关键是 Parent1.call() 这一句,是通过call(apply)改变函数运行上下文,将Parent1的this挂载到Child1的实例上

缺点1:Parent1原型链上边的属性方法等不会被继承。

2.借助原型链继承

function Parent2() {
    this.name = 'parent2';
    this.arr = [1,2,3];
}

function Child2() {
    this.name = 'child2'
}

Child2.prototype = new Parent2(); // 此处为关键

let s2 = new Child2();
let s3 = new Child2();
console.log(s2.arr, s3.arr) // [1,2,3] [1,2,3]

如上,关键在于将Child2的原型指向Parent2的实例

缺点2:这样构造的Child2的实例,都是同一个原型,改变其中一个,其他的实例也会改变

如,接上边,再增加一句

s2.arr.push(4);
console.log(s2.arr, s3.arr); //[1,2,3,4] [1,2,3,4] 

可见,修改s2的arr属性,s3实例也跟着变化

3.组合继承 (解决上边缺点1、2)

// 组合继承
function Parent3() {
    this.name = 'parent3';
    this.arr = [1,2,3];
}

function Child3() {
    Parent3.call(this);
    this.name = 'child3'
}

Child3.prototype = new Parent3();

let s4 = new Child3();
let s5 = new Child3();
s4.arr.push(4)
console.log(s4.arr, s5.arr) // [1,2,3,4] [1,2,3]

缺点3: Child3每次实例化,都要执行Parent3 构造函数,

4.组合继承的优化1

function Parent4() {
    this.name = 'parent4';
    this.arr = [1,2,3];
}

function Child4() {
    Parent4.call(this);
    this.name = 'child4'
}

Child4.prototype = Parent4.prototype; // !!!此处为关键

let s6 = new Child4();
let s7 = new Child4();
s6.arr.push(4)
console.log(s6.arr, s7.arr)

缺点4: 无法区分实例是由Child4还是Parent4直接实例化而来

console.log(s6 instanceof Child4, s6 instanceof Parent4); // 可以发现此时均为 true
console.log(s6.constructor, s7.constructor); // 均为Parent4

5.组合继承2

function Parent5() {
    this.name = 'parent5';
    this.arr = [1,2,3];
}

function Child5() {
    Parent5.call(this);
    this.name = 'child5'
}

Child5.prototype = Object.create(Parent5.prototype); //  !! 此处为关键

let s8 = new Child5();
let s9 = new Parent5();

console.log(s8 instanceof Child5, s9 instanceof Child5); // true, false
console.log(s8.constructor, s9.constructor); // 均为Parent5

关键在于,通过 Object.create 构造一个中间对象,用以区分

缺点:两者 constructor 还是全部指向 Parent5

可通过如下手动设置,解决

Child5.prototype.constructor = Child5;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端卡卡西呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值