What is the benefit/point of replacing an object's constructor property?

I was recently perusing the source of a JavaScript library, and noticed some interesting code that I can’t for the life of me figure out.

I will not go into too much detail, but the following code should summarize well what I’m looking at:


    var Something = function(options) {
        var obj = options.func;
        obj.constructor = Something;
        obj.prototype.constructor = obj;
        return obj;
    };

    var SomethingElse = new Something({
        func: function() {}
    });

This is pretty easy to follow, but I don’t see the point of replacing the object’s constructor. It doesn’t cause the returned object to inherit from the Something function, and

(SomethingElse instanceof Something)

still returns false.

Also, as I understand it, every new object’s prototype property already has a constructor property that points to itself. So,

obj.prototype.constructor = obj

just seems redundant.

Am I completely missing something here?

I have actually seen those videos, and that particular video doesn’t go into too much detail about the significance of the constructor property. And that is what confuses me. The constructor property seems completely useless, unless you are going to use it to tie that object to the assigned constructor function. However, this particular library does that nowhere.

I guess my question is, in the example I gave earlier, why does it matter that SomethingElse’s constructor property equals Something, and not just Function?

Perhaps this video that goes into depth about functions and inheritance will help:

Crockford On JavaScript: Act III: Function the Ultimate ([url=“http://www.slideshare.net/douglascrockford/crockford-on-javascript-act-iii-function-the-ultimate”]slides)

The time segments that most closely relate to this are:
50:24 Pseudoclassical Inheritance
53:23 Prototypal Inheritance

I feel Object constructor is a regular JS function and can be used for creating a object “type” and this object type can be used several times by avoiding in redefining the object every time for particular instance needs.

mwistrand, did you make any headway with this. I had a look myself, and it’s a tad confusing.

Not really. I can understand replacing an object’s constructor property if you want to create some sort of a link between two objects. However, the library I’m looking at doesn’t make use of that functionality anywhere else.

Here’s what I get from the slides

When using pseudoclassical inheritance there is no need to set prototype.constructor as that’s already done for you. (slide 52)

Setting the prototype.constructor is only needed when you are manually constructing a new object (slide 54)

I watched the vid. Very good. Unfortunately got side tracked on #54 wanting to find out more about the ECMA 5 methods object.create and methods.keys. In fact I think it should be Object.keys(methods).

As for needed, he did seem to imply that it was more optional, but it’s still worth understanding why.

Reading up on patterns and code re-use at the moment, but will come back to that or this:)

RLM

It’s not that it’s optional, it’s that when the object inherits from something other than Object, the constructor gets lost.

Here’s a partial transcript:

This does the same thing as new, except that we don’t use new.

And then a little bit of extra plumbing - we don’t really need to do this but just to be nice - we’ll set the function’s prototype property to the prototype because in the case of the hoozit, prototype got replaced and so we lost the constructor value, and we’ll fix that there as well.


var prototype = ...
func.prototype = prototype;
prototype.constructor = func;

That’s why the prototype.constructor assignment is required. When assign a different function as the prototype, the prototypes constructor winds up getting smashed, so you have to replace that constructor.

That is not an issue with the OP code, but it’s something to watch out for whenever you reassign the prototype method of an object.

Thanks for that. I tend to get the wrong end of the stick so forgive me for the following.

Am I right in saying that the constructor property is key really to when you need to debug or run checks on instances?

RLM

I apologize if I’m a little slow, but why does losing that constructor matter? The constructor property is not involved in inheritance, and in fact it doesn’t seem to affect the code at all. It does look like a nice way to tie things up, but I’m trying to wrap my mind around what makes the constructor property so important when it doesn’t really appear to do anything.

As I say mwistrand, I think it comes down to debugging and giving a clearer picture. If you’re trying to figure out an issue and your instances are reporting the wrong constructor it could be confusing.

Example

// no constructor set for child
function inherit(child, parent){
	var F =function(){}
	F.prototype = parent.prototype;
	child.prototype = new F();
}

Make our constructors, inherit, instance and log

function Parent(){} // Parent constructor
Parent.prototype.method1 = function(){};

function Child(){} // Child constructor

inherit(Child, Parent);

var newChild = new Child();

console.log(newChild);

Output in say Google Chrome

Parent
__proto__: Parent
__proto__: Parent
constructor: function Parent(){}
method1: function (){}
__proto__: Object

Change the method to set the constructor

function inherit(child, parent){
	var F =function(){}
	F.prototype = parent.prototype;
	child.prototype = new F();
	child.prototype.constructor = child; // reset constructor
}

Output this time

Child
__proto__: Child
constructor: function Child(){}
__proto__: Parent
constructor: function Parent(){}
method1: function (){}
__proto__: Object

RLM

That’s one possible reason for it.

Myself I believe that a better reason is that it helps to ensure consistency. Regardless of whether you use pseudoclassical inheritance or prototypal inheritance, the resulting object will be identical, which is how things should be.

Thanks RLM2008 and pmw57. That makes sense. I just couldn’t figure out if the constructor property did something I wasn’t aware of.