views:

63

answers:

2

Trying to bend by head around Javascript's take on OO...and like many others running into confusion about the constructor property. In particular, what it's significance is as I cant seem to make it have any affect. E.g.

function Foo(age) {
    this.age = age;
}

function Bar() {
    this.name = "baz"; 
}

Bar.prototype = new Foo(42); 
var b = new Bar;    

alert(b.constructor); // Shows Foo(), thats OK because we inherit Foos prototype.

alert(b.name); // Shows "baz". Shows that Bar() was called as constructor.
alert(b.age);  // Shows 42, inherited from Foo

In the above example, the object b seems to have had the right constructor called (Bar()) - and it inherits the age property OK from Foo. So why do many people suggest this as a necessary step:

Bar.prototype.constructor = Bar;

Clearly the right Bar constructor was called when constructing b, so what impact does this prototype property have? I am curious to know what practical difference it actually makes to have the constructor property set 'correctly' - as I cant see it having any affect on which constructor is actually called after an object is created.

+1  A: 

The constructor property makes absolutely no practical difference to anything internally. It's only any use if your code explicitly uses it. For example, you may decide you need each of your objects to have a reference to the actual constructor function that created it; if so, you'll need to set the constructor property explicitly when you set up inheritance by assigning an object to a constructor function's prototype property, as in your example.

Tim Down
Thanks - that was exactly the answer I was looking for.
megamic
+2  A: 

Step one is to understand what constructor and prototype are all about. It's not difficult, but one has to let go of "inheritance" in the classical sense.

The constructor

The constructor property does not cause any particular effects in your program, except that you can look at it to see which function was used in conjuction with the operator new to create your object. If you typed new Bar() it will be Bar and you typed new Fooit will be Foo.

The prototype

The prototype property is used for lookup in case the object in question does not have the property asked for. If you write x.attr, JavaScript will try to find attr among x's attributes. If it cant find it, it will look in x.__proto__. If it's not there either, it will look in x.__proto__.__proto__ and so on as long as __proto__ is defiend.

So what is __proto__and what has it got to do with prototype? Shortly put, prototype is for "types" while __proto__ is for "instances". (I say that with quotation marks because there's not really any difference between types and instances). When you write x = new MyType(), what happens (among other things) is that x.__proto___ is set to MyType.prototype.

The question

Now, the above should be all you need to derive what your own example means, but to try and answer your actual question; "why write something like":

Bar.prototype.constructor = Bar;

I personally have never seen it and I find it a little silly, but in the context you've given it will mean that the Bar.prototype-object (created by using new Foo(42)) will pose as have being created by Bar rather than Foo. I suppose the idea is some make something similar to C++/Java/C#-like languages where a type-lookup (the constructor property) will always yield the most specific type rather than the type of the more generic object further up in the prototype-chain.

My advice: don't think very much about "inheritance" in JavaScript. The concepts of interfaces and mixins makes more sense. And dont check objects for their types. Check for the required properties instead ("if it walks like a duck and quacks like a duck, it's a duck").

Trying to force JavaScript into a classical inheritance model, when all that it has is the prototype-mechanism as described above, is what causes the confusion. The many people that suggested to manually set the constructor-property probably tried to do just that. Abstractions are fine, but this manual assignment of the constructor property is not very idiomatic usage of JavaScript.

Jakob
I agree that the `constructor` property is not very useful, but inheriting from another object's prototype can be extremely powerful and I wouldn't discourage that at all.
Tim Down
Thanks - it may not be idiomatic but many of the tutorials on the net (and q/a's on SE) suggest using this particular method is 'needed' - as if the whole prototype model breaks if you don't use it.
megamic
Oh, sorry if that's how it came through. Inheriting from another objects prototype is not the problem; altering the constructor-property is.
Jakob