【问题标题】:Why is nesting level for prototypal inheritance in Javascript is always 1?为什么Javascript中原型继承的嵌套级别总是1?
【发布时间】:2021-03-09 03:29:08
【问题描述】:

我试图了解 Javascript 中原型继承和经典继承之间的区别。我遇到了一些声称The abstraction level for prototypal inheritance is never deeper than 1 的文章,但我不明白为什么。这是因为最后继承的原型可以访问其所有祖先的方法或属性,而经典继承只能访问其最后一个祖先

从所有祖先访问方法的示例:

显示继承的简单图表:

Human ---> Zombie ---> ZombieBoss

代码

function Human(name, hp){
  this.name = name
  this.hp = hp
}

Human.prototype = {
  sleep: function (){
    this.hp += 50
    console.log('human recovered')
  },
  constructor: Human
}

function Zombie(name, hp){
  Human.call(this, name, hp)
}

Zombie.prototype = {
  ...Human.prototype,
  sleep: function (){
    this.hp += 100
    console.log('zombie recovered')
    Human.prototype.sleep.call(this)
  },
  constructor: Zombie
}

function ZombieBoss(name, hp){
  Zombie.call(this, name, hp)
}

ZombieBoss.prototype = {
  ...Zombie.prototype,
  sleep: function (){
    this.hp += 500
    console.log('zombie boss recovered')
    Human.prototype.sleep.call(this) //Method from ancestor's ancestor can be accessed as well. Which is not possible with super()
    Zombie.prototype.sleep.call(this) //Method from last ancestor 
  },
  constructor: ZombieBoss
}

const king = new ZombieBoss('king', 1000)
king.sleep() //hp should be 1700

如果这不是唯一的原因,那么剩下的原因是什么?如果有一些简单的例子就好了。

【问题讨论】:

    标签: javascript


    【解决方案1】:

    这是一种复杂的说法:“在 JavaScript 中,一切都是存在于 JS 引擎中的具体对象,而不是抽象。”

    这很重要!这意味着泛化(如总体鞋概念)只是其他对象。对于经典继承,泛化是抽象的抽象……一直到最近的后代。

    这里的抽象级别永远不会超过1; 原型继承发生的唯一抽象是对现实世界事物的抽象。

    所以,按照他的说法,唯一的抽象是:

    JavaScript object <----- real world object that the JavaScript object represents
    

    不管有问题的 JS 对象有哪些其他 JS 对象作为内部原型。

    他看待事物的方式:

    Human ---> Zombie ---> ZombieBoss
    

    并不重要,因为它们中的每一个都是存在于解释器中的 具体 对象,并且每一个都离这些 JS 对象各自代表的可能的现实世界对象只有一步之遥。


    另外,您的代码没有正确实现原型继承:

    Zombie.prototype = {
      ...Human.prototype,
      sleep: function (){
    
    ZombieBoss.prototype = {
      ...Zombie.prototype,
      sleep: function (){
    

    上面的方法可以帮助避免代码重复,但每个对象:Human.prototypeZombie.prototypeZombieBoss.prototype都有同一个对象的内部原型Object.prototype .您正在实现的原型链是

    Object.prototype -> Human.prototype 
    Object.prototype -> Zombie.prototype 
    Object.prototype -> ZombieBoss.prototype 
    

    如果您希望原型相互继承并达到您可能想要做的事情,您必须使用Object.create

    Zombie.prototype = Object.create(Human.prototype);
    Zombie.prototype.sleep = function() {
      // ...
    
    ZombieBoss.prototype = Object.create(Zombie.prototype);
    // ...
    

    【讨论】:

    • 我现在明白为什么使用Object.assign() 不是链接原型的正确方法。如果是这样,是否可以在同一级别继承多个原型?比如AB可以通过继承同级的A和B来创建吗?我可以让AB继承A和B,而不让A继承B或B继承A吗?
    • 不是以任何合理的方式。 stackoverflow.com/questions/9163341/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-03
    相关资源
    最近更新 更多