-1

I'm new to JS, still struggling in understanding 'this' in Chaining Constructor Functions. Below is an example:

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

let TaxedProduct = function(name, price, taxRate) {
   Product.call(this, name, price);
   this.taxRate = taxRate;
}

let hat = new TaxedProduct("Hat", 100, 1.2); 

I don't understand why we should use Product.call(this, name, price);, why can't we just use Product(name, price);? I understand 'this' is used for binding, but in the construction of TaxedProduct, this is already referred to newly created TaxedProduct object, so use Product(name, price); is pretty much like copy and paste the Product construction content into TaxedProduct's as:

let TaxedProduct = function(name, price, taxRate) {
   //Product(name, price);  just like copy and paster below two statements
   this.name = name;
   this.price = price;     

   this.taxRate = taxRate;
}
  • Did you actually try to run it? Because you wouldn't have needed to post the question if you did... – Jared Smith Sep 09 '19 at 01:44
  • Possible duplicate of [How does the "this" keyword work?](https://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work) – Jared Smith Sep 09 '19 at 01:45
  • @JaredSmith of course I ran it, but I want to know why. Running sth just means you know whether it will run or not, not going to tell you why it is not running,so could you remove the duplicated tag, it is not the same question you identified –  Sep 09 '19 at 01:56
  • The answers to the other question explain why. I realize that it's a somewhat complex and frequently counter-intuitive topic, but googling will get you literally several million explanations of how the 'this' context works in Javascript (including a fair number of SO Q&As). We don't need yet another question about it. So no, the tag stays. I however am only one vote and it takes five (or a gold badge holder) to close a question as a dupe, so we'll see what everyone else thinks. CertainPerformance could have insta-closed this and didn't, so there's that. – Jared Smith Sep 09 '19 at 02:16
  • @JaredSmith oh, I just double checked the answer, one does answered my question in another way. I have to throw my java/C# mind away when work with javascript –  Sep 09 '19 at 02:28
  • "I have to throw my java/C# mind away" always a good decision when working in a language that isn't Java/C#. Which is not to be construed as a criticism: they're fine it's just that they occupy their own odd phylum in the Animal Kingdom of programming languages. As does Javascript for that matter. – Jared Smith Sep 09 '19 at 12:16

1 Answers1

0

If Product is called without a calling context - that is, if you do Product(name, price), then it will attempt to assign name and price properties to the global object (or to undefined in strict mode, throwing an error), which definitely isn't desirable:

'use strict';

let Product = function(name, price) {
   this.name = name; // error thrown
   this.price = price;
}

let TaxedProduct = function(name, price, taxRate) {
   Product(name, price);
   this.taxRate = taxRate;
}

let hat = new TaxedProduct("Hat", 100, 1.2);
console.log(hat.price);

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

let TaxedProduct = function(name, price, taxRate) {
   Product(name, price);
   this.taxRate = taxRate;
}

let hat = new TaxedProduct("Hat", 100, 1.2);
console.log(hat.price); // undefined - wrong
console.log(window.price); // oops, we assigned to window - wrong

You need to somehow pass the this (the instance being created) from inside the TaxedProduct function to the Product function, so that the Product function can assign to properties of the instance being created. .call allows you to do this, by calling a function with a custom calling context (or this).

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Thanks for your answer. I know how this works in binding, but I don't know why calling `Product(name, price);` is called without a calling context, it did get called in `TaxedProduct `'s construction function, so the context is `TaxedProduct `, maybe I have difficulty in understanding it becuase I'm from Java/C# background, in those languages, to call the super class, you don't to bind anything, just call `base()` –  Sep 09 '19 at 02:03
  • Generally, a function is called with a calling context if the function is called as a property is an object. Eg `foo.bar()` will call `bar` with a calling context of `foo`. If you use `new` when calling a function, the calling context will be the `.prototype` of the function, eg with `new Foo()`, the `this` inside it will be an object whose internal prototype is `Foo.prototype`. – CertainPerformance Sep 09 '19 at 03:21
  • Here, when you do `Product(name, price);`, `Product` gets called with no calling context, because it's not being called as part of an object - it's being called as a standalone function, without `new`, so the `this` inside will be the global object or `undefined`. – CertainPerformance Sep 09 '19 at 03:22
  • I see. Thanks. I need to get rid of Java/C# mind when work with JS –  Sep 09 '19 at 03:29