1

I don't understand something>Let's take a look at MDN's example:

function Product(name, price) {
  this.name = name;
  this.price = price;

  if (price < 0) {
    throw RangeError('Cannot create product ' +
                      this.name + ' with a negative price');
  }

  return this;
}

function Food(name, price) {
  Product.call(this, name, price);
  this.category = 'food';
}

Food.prototype = Object.create(Product.prototype);
Food.prototype.constructor = Food; // Reset the constructor from Product to Food

Why I must write this part:

Food.prototype = Object.create(Product.prototype);
    Food.prototype.constructor = Food;

Isn't the Product.call(this, name, price); already copied that property(Prototype) from Product to Food?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Alexa
  • 418
  • 4
  • 12

1 Answers1

1

This is just how you do pseudoclassical instantiation of a class in JavaScript. Lets first see what happens when you just do the first part, but lets add a bit for clarification:

function Product(name, price) {
  this.name = name;
  this.price = price;

  if (price < 0) {
    throw RangeError('Cannot create product ' +
                      this.name + ' with a negative price');
  }

  return this;
}

Product.prototype.declare = function () {
  console.log('I like ' + this.name);
} 

function Food(name, price) {
  Product.call(this, name, price);
  this.category = 'food';
}

Run this in a console and and run console.dir(Product) vs console.dir(Food). Food has some of the same properties as Product. However, Food doesn't have access to the method "declare" that is on Product's prototype. Thus, we need to set Food's prototype. Run this in console after the above code:

Food.prototype = Object.create(Product.prototype);

run console.dir for Food again. Now, Food has a prototype that has the same properties/methods as Product. However, the prototype's constructor is now 'Product'. The last step to fix this is setting Food.prototype.constructor so Food's constructor is once again Food, but with all of the properties/methods of Product.

Food.prototype.constructor = Food;

It's a strange but logical process to attaining full inheritance with pseudoclassical instantiation in JavaScript.

eddyjs
  • 1,270
  • 10
  • 20
  • thank you for your answer. I don't understand why Call method didn't copied prototype of Product. After all prototype is just another property of Product object and it should copy that property. – Alexa Jul 30 '15 at 15:42
  • I don't see method declare in Food.prototype when I do all that. – Alexa Jul 30 '15 at 15:56
  • It should be under the __proto__ property of Food (because it's inheriting from Product). Try instantiating a new `Food` object: `var steak = new Food('steak', 50);` Then run: `steak.declare();` – eddyjs Jul 30 '15 at 17:07
  • The `call` method does not just copy the object over. It just executes the function. Thus, it will execute whatever is in your function but not any values attached to it's prototype. `call` is a function method that is not specific to object instantiation https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call. – eddyjs Jul 30 '15 at 17:11
  • Ok, I see the declare method now. Tnx... I don't get what are you triying to say here: "Thus, it will execute whatever is in your function but not any values attached to it's prototype"...Why? – Alexa Jul 30 '15 at 19:35
  • That's just how JavaScript works. `call` executes the function `Product`. `Product.prototype` is not within the function code. – eddyjs Jul 30 '15 at 19:53