Search code examples
javascriptprototypal-inheritance

Can you explain the differences between these two code snippets?


That's my first question in this platform. If there is any fault, sorry for this. I could not understand the differences between these two code snippets. I got these errors and I could not understand the reasons.

Dog should inherit the eat() method from Animal.

beagle should be an instanceof Animal.

beagle.eat() should log "nom nom nom"

function Animal() { }
Animal.prototype.eat = function() { console.log("nom nom nom"); };

function Dog() { }

// Only change code below this line

Dog.prototype=Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark= function(){
  console.log("Woof!");
}



// Only change code above this line

let beagle = new Dog();
function Animal() { }
Animal.prototype.eat = function() { console.log("nom nom nom"); };

function Dog() { }

// Only change code below this line

Dog.prototype=Object.create(Animal.prototype);

Dog.prototype={
  constructor:Dog,
  bark:function(){
    console.log("Woof!")
  }
}


// Only change code above this line

let beagle = new Dog();


Solution

  • When you do

    Dog.prototype=Object.create(Animal.prototype);
    

    The Dog.prototype object is now an empty object whose internal prototype points to Animal.prototype. (so, eg, if Dog.prototype.eat is referenced, the eat property isn't found on the empty object, so via prototypal inheritance, the interpreter looks to the internal prototype object and finds eat on `Animal.prototype)

    That's the object you want to use. But if you do

    Dog.prototype = {
      // object initializer...
    

    Now you're assigning Dog.prototype to a completely different object. The old Object.create(Animal.prototype); is no longer the object at Dog.prototype, since its value was completely reassigned. As a result, the object at Dog.prototype doesn't inherit from Animal.prototype in the end. That's the problem with the second snippet.

    If you want a concise object initializer with this sort of pattern, you can use Object.assign:

    function Animal() {}
    Animal.prototype.eat = function() {
      console.log("nom nom nom");
    };
    
    function Dog() {}
    
    // Only change code below this line
    
    Dog.prototype = Object.assign(
      Object.create(Animal.prototype), {
        constructor: Dog,
        bark: function() {
          console.log("Woof!")
        }
      }
    );
    
    
    // Only change code above this line
    
    let beagle = new Dog();
    beagle.eat();
    console.log(beagle instanceof Animal);