0
function Shape() {
    this.name = "none"; 
}

function Rect () {        
    this.x = 0;
    this.y = 0;
    this.width = 0;
    this.height = 0;
};

If all the property of Shape should be available to Rect is it correct to write

Rect.prototype = Shape;

In this case will each instance of Rect(i.e. Object.create(Rect)) gets a seperate name from Shape object.

karthikr
  • 97,368
  • 26
  • 197
  • 188
Talespin_Kit
  • 20,830
  • 29
  • 89
  • 135
  • possible duplicate of [What is the reason to use the 'new' keyword at Derived.prototype = new Base](http://stackoverflow.com/q/12592913/1048572) – Bergi Aug 09 '14 at 17:57

2 Answers2

6

Rect.prototype = Shape; is definitely incorrect. Every instance of Rect would have the same properties as the function Shape. That includes methods that every function has, like .call and .apply.

But even Rect.prototype = new Shape; as suggested in the other answer is not a good solution. While this would add name to every instance of Rect, every instance would share the same name property. But name is an instance specific property, it does not belong on the prototype. The prototype chain should only hold properties (values) that are supposed to be shared by every instance.

So, how to do it?

Add Shape.prototype to the prototype chain of Rect instances:

Rect.prototype = Object.create(Shape.prototype, {constructor: {value: Rect}});

You don't have any custom properties on Shape.prototype yet, however, setting this up makes the following work:

var r = new Rect();
r instanceof Shape; // true

You also have to call the super constructor (Shape) inside the Rect constructor, setting this to the new instance:

function Rect () {
    Shape.call(this);

    this.x = 0;
    this.y = 0;
    this.width = 0;
    this.height = 0;
}

Shape.call(this); is the moment where name is assigned to our new Rect instance.

If you come from Java or another class-oriented OO language, this is basically the same as calling super(); in the child constructor.


All of the above is exactly what the new ES6 class syntax does internally.

class Rect extends Shape {
  constructor() {
      super();
      // ...
  }
}
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • With ES6 don't forget that the `Rect` function itself inherits from the `Shape` function as well, i.e. `Object.setPrototypeOf(Rect, Shape)` – Bergi Aug 09 '14 at 18:03
  • @Bergi: Really? I thought it just copies all static methods. Have to check the spec again... – Felix Kling Aug 09 '14 at 18:04
  • 1
    I've just looked it up myself to be sure it's still in the draft: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-classdefinitionevaluation. In the [harmony proposal](http://wiki.ecmascript.org/doku.php?id=strawman:maximally_minimal_classes) it was implemented via that fancy literal-inheritance-operator `|>` :-) – Bergi Aug 09 '14 at 18:05
  • Uh, I didn't get that far, I only read till 2e - you're right :-) – Bergi Aug 09 '14 at 18:12
  • ehehe :) I still have to get used to the new spec :-/ – Felix Kling Aug 09 '14 at 18:15
0

You would have to write the following.

Rect.prototype = new Shape();

That would create a new object for Shape and then assign it as the prototype for Rect. You can't assign a function as a prototype.

Siddharth
  • 1,146
  • 3
  • 15
  • 28
  • 1
    but Doug Crockford advices not to use new operator at all. you mean Rect.prototype = Object.create(Shape); – Talespin_Kit Aug 09 '14 at 17:39
  • Do not listen to Crockford on this, if you need a new instance, use the `new` keyword. Crockford is confused and have for some reason decided that prototypical inheritance is a bad thing, in a language built around prototypical inheritance – adeneo Aug 09 '14 at 17:44
  • 3
    a) Crockford doesn't say much about this b) You really shouldn't use `new` *here* c) you shouldn't use `Object.create(Shape)` either, it needs to be `Object.create(Shape.prototype)` – Bergi Aug 09 '14 at 17:54
  • @adeneo I agree with you to not listen to C on the subject of "Classical inheritance" but for the exact reason that he creates an instance of Parent to set prototype part of Child (as you advice). Then claims the Parent constructor can't be re used (ahem: Parent.call...) So Bergi is correct that Object.create is better then creating an instance. More on prototype here: http://stackoverflow.com/a/16063711/1641941 – HMR Aug 10 '14 at 04:21
  • @Bergi - Crockford has been [talking a lot about this](http://nemisj.com/js-without-new-and-this/) lately, he claims we should stop using the `new` keyword all together and use factories that return objects instead, and at one point he claimed that prototypical inheritance is harmful and should never be user. After criticism he changed that to say that `new` should only be used for constructors (which is correct). I probably didn't get the question, I was thinking the point was to do something like -> **http://jsfiddle.net/adeneo/0kjza73n/** – adeneo Aug 10 '14 at 04:40
  • @adeneo: I don't know about his latest talks, I only know his website (http://javascript.crockford.com/inheritance.html etc) which is interesting, but partially outdated and definitely non-standard. The article you linked doesn't seem to be written by himself (did I miss something?), I would be glad if you could link a statement from him where he admits that `new` is useful with constructors :-) – Bergi Aug 10 '14 at 15:29
  • @Bergi - I've at least seen several questions here on SO about this, here's [**one**](http://stackoverflow.com/questions/383402/is-javascript-s-new-keyword-considered-harmful), I've also attended a talk with Crockford where he proclaimed that prototypical inheritance was dead, and that the `new` keyword was harmful, and I almost choked on my coffee. Here's something he's [**written**](https://groups.yahoo.com/neo/groups/jslint_com/conversations/topics/314) at least. I think Ben Gruenbaum had an argument with C about this as well some time ago. – adeneo Aug 10 '14 at 18:32