0

I've probably read 15 different books, articles, or SO questions related to JavaScript Prototypal Inheritance and each had slightly different ways of doing things, so I wanted to get this figured out once and for all:

Example

function Rectangle(h, w){
  this.height = h;
  this.width = w;
  console.log("Rectangle ctor: "+ this.height + "x" + this.width);
}

Rectangle.prototype.getArea = function(){
  return this.height * this.width;
}

var a = new Rectangle(3, 4);

console.log(a.getArea());

function Square(l){
  this.height = l;
  this.width = l;
  console.log("Square ctor");
}

Square.prototype = new Rectangle();
Square.prototype.constructor = Square;

var b = new Square(5);

console.log(b.getArea());

This example works as expected. The Square object inherits from the Rectangle, therefore, it has the ability to use the getArea() method. However, there is 1 thing I always see being done differently depending on where I look.

Instead of doing Square.prototype = new Rectangle(), I have seen people use Square.prototype = Object.create(Rectangle.prototype). When I test this out, both appear to function in the same way, the only difference I notice is when I do this:

console.log(new Rectangle());
console.log(Object.create(Rectangle.prototype));

This logs the new Rectangle() which includes the height and width properties, then logs the Object.create(Rectangle.prototype) which logs the same thing except for the height and width.

So my question is, why do some people do it with one and not the other? Is one more beneficial than the other? The way I understand it, the one that uses new Rectangle() will get the height and width properties on its prototype which could result in issues, correct?

Can someone please shed some light on this? Thanks!

EDIT

I also realized that when using new Rectangle() as the prototype of Square, it actually calls the constructor (which may do something useful in some cases), whereas the Object.create() method does not. Is the reasoning behind the 2 different usages related to the use case in terms of whether or not the constructor should be called to generate some object state that may be needed in the subtype?

Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
Matt Hintzke
  • 7,744
  • 16
  • 55
  • 113
  • Once and for all? Use ES6 `class` syntax. – Bergi Sep 14 '16 at 17:59
  • Yes, but not all browsers can use ES6 yet and I am not using Babel at the moment. Plus its more about understanding whats going on under the hood that I am interested in. – Matt Hintzke Sep 14 '16 at 18:01

1 Answers1

1

I think you answered your question yourself. The difference between new Rectangle() and Object.create(Rectangle.prototype) is that the former calls the constructor and the latter doesn't. Because of that, you should always use Object.create(). Otherwise the constructor will be called twice (as you can see in your example).

Also, in ECMAScript 6 you can use the class syntax, which simplifies many things, like inheritance.

Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
  • Ok thanks, I guess I am more trying to determine if one version is technically "deprecated" or if they are both completely valid depending on your use case. After playing around with both, it appears that `Object.create(Rectangle.prototype)` is a cleaner way of doing things because you 1) Don't have to call the constructor an extra time and 2) You don't have prototype properties shadowed by the subtype objects (when using 'new', height and width get added to the `Square.prototype` which then gets shadowed by the this.height and this.width on the Square's constructor) – Matt Hintzke Sep 14 '16 at 17:36
  • @MattHintzke IMO only the `Object.create()` option is valid. – Michał Perłakowski Sep 14 '16 at 17:38
  • 1
    @MattHintzke It's cleaner and less error-prone. `new` for creating prototypes is effectively deprecated, even when there are edge cases where it works the same. – Bergi Sep 14 '16 at 18:02