【继承系列】JS中的原型式继承

1. 原型式继承

注意:是原型式继承,不是原型链继承

该方法的原理是创建一个构造函数,构造函数的原型指向对象,然后调用 new 操作符创建实例,并返回这个实例,本质是一个浅拷贝。

伪代码如下:

function objcet (obj) {
  function F () {};
  F.prototype = obj;
  return new F();
}
1.1 题目一

我们先看一个比较熟悉的东西

const cat = {
  heart: '❤️',
  colors: ['white', 'black']
}

const guaiguai = Object.create(cat)
const huaihuai = Object.create(cat)
guaiguai.colors.push('test')
console.log(guaiguai)
console.log(huaihuai)

console.log(guaiguai.colors)
console.log(huaihuai.colors)

答案:

{}
  __proto__: colors: (2) ["white", "black","test"]heart: "❤️"
    __proto__: Object
{}
  __proto__: colors: (2) ["white", "black","test"]heart: "❤️"
    __proto__: Object
❤️
["white", "black","test"]
["white", "black","test"]

这里用到了我们之前提到过的Object.create()方法。

在这道题中,Object.create(cat)会创建出一个__proto__属性为cat的空对象。

注意:父类引入类型属性被共享了,记住!

1.2 题目二

在ES6之前没有Object.create()方法,所以才会有开头的那段伪代码。

现在可以尝试自己实现一个Object.create()

想一下Object.create()的作用

  • 接受一个对象A
  • 返回一个新对象B
  • 并且B.__proto__ --> A

所以就有了这么一个方法

function objcet (obj) {
  function F () {};
  F.prototype = obj;
  return new F();
}

接下来看看效果是否和1.1一样

function object (obj) {
    function F () {};
    F.prototype = obj;
    return new F();
}
const cat = {
  heart: '❤️',
  colors: ['white', 'black']
}

const guaiguai = object(cat)
const huaihuai = object(cat)

console.log(guaiguai)
console.log(huaihuai)

console.log(guaiguai.heart)
console.log(huaihuai.colors)

答案:

F {}
  __proto__: colors: (2) ["white", "black","test"]heart: "❤️"
    __proto__: Object
F {}
  __proto__: colors: (2) ["white", "black","test"]heart: "❤️"
    __proto__: Object
❤️
["white", "black","test"]

效果是和Object.create()差不多(只不过我们自定义的object返回的对象是构造函数F创建的)。

注意:模拟后父类引入类型属性也被子例共享

现在我们尝试画张图

在这里插入图片描述
这就有小伙伴要问了,既然是需要满足

B.__proto__ --> A

这个条件的话,我这样写也可以实现啊

function object (obj) {
  const newObj = {}
  newObj.__proto__ = obj
  return newObj;
}

可以用上面的例子试一试,确实可以实现

不过,我们是要模拟Object.create()方法,如果你都能使用__proto__,那为何不直接使用Object.create()呢?

1.3 题目三

无法向父类构造函数传参,并且父类构造函数中的属性无法继承,只能继承父类构造函数中的原型对象中的属性
要想继承父类构造函数中的属性,还得借用Parent.call

function Parent(){
  this.name = 'a';
  this.colors = ['red','yellow']
}

Parent.prototype.age = 21

function object (obj) {
  function F () {
    // Parent.call(this)
  };
  F.prototype = obj;
  return new F();
}

const child1 = object(Parent.prototype)
const child2 = object(Parent.prototype)

console.log(child1);
console.log(child2);

答案:

在这里插入图片描述

2 总结

  • 优点:

    • 没有优点。⊙﹏⊙‖∣
  • 缺点:

    • 无法向父类构造函数传参
    • 如果父类是构造函数,无法继承父类构造函数中的属性,只能继承父类构造函数的原型对象的属性(题1.3)
    • 如果父类是普通对象,引入类型属性依然被子例共享(题1.2)

如果不当,还请老哥指出。

参考文章:

48道原型题目

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值