2

I am unable to understand this loop behavior of the javascript.

Can someone tell me why was it designed in this way? Is there any real use case of this behavior?

why this loop? { Newly created instance inherits properties from the prototype property of the constructor function object. prototype property of the constructor function is an object that keeps constructor property. constructor property is equal to the constructor function object. Again constructor function object keeps prototype property. }

instance1---inhertis(keeps)-->Prototype property of func()-->keep constructor property-->function object func-->keep prototype property.

var func = function(){};
var construct = func.prototype.constructor;

console.log(construct === func); //true

var instance1 = new func();

Updated: Even if in between i assigned something else, instanceof always returns true.

var func1 = function(){};
func1.prototype.constructor = 1;

var instance1 = new func1();
console.log(instance1 instanceof func1); //true


var func2 = function(){};
func2.prototype.constructor = 0;

var instance2 = new func2();
console.log(instance2 instanceof func2); //true

Sorry to ask 2 question in 1 but both may be related.

P K
  • 9,972
  • 12
  • 53
  • 99

3 Answers3

5

Of course it retains the instance. Why wouldn't it? If you're making a duck, it's a duck - its DNA says that it's a duck, no matter if you paint it black or teach it to be a goose.

Also, in your case, setting the constructor has no effect. When you do new func (or new func(), which are identical), you go and grab an internal property of the function (the [[Construct]] property), and not func.prototype.constructor.

obj.constructor is defined on every single object, since it's defined on every "constructor": That is, Object Number Function Date Boolean String and so on. Each have a constructor property in their prototype:

Object.prototype.constructor === Object;
String.prototype.constructor === String;
//etc

Each one has its prototype.constructor pointing to itself.

Since functions can also behave like constructors, their .prototype.constructor property points to themselves as well. AFAIK, that's unused in the language itself.

The terse, technical answer? http://es5.github.com/#x11.8.6

//foo instanceof bar
Return the result of calling the [[HasInstance]] internal method of bar with argument foo.

(slightly paraphrased)

Basically, you're asking mother-duck: "Excuse me ma'am, is this your child?" The child has little say in the matter.

Edit: As mentioned in the comments, changing the prototype does indeed affect the instanceof results. Like above, there's the intuitive answer and the technical answer.

Intuitive answer is simple: The prototype defines the object. Therefore, changing the prototype changes the DNA - you make the duck a goose, not by teaching it to be a goose, but by going to its DNA and changing it to a goose DNA.

The technicality is seeing what [[HasInstance]] does. (the other [[HasIntsance]] calls this one) The spec is really dry and terse, so here's the algorithm written in pseudo-javascript:

//assume Func is the function we're talking about
function HasInstance ( value ) {
    if ( IsntAnObject(value) ) {
        return false;
    }

    var proto = Func.prototype;

    if ( Type(proto) !== "Object" ) {
        return false;
    }

    while ( value !== null ) {
        value = value.prototype;
        if ( value === proto ) {
            return true;
        }
    }
    return false;
}

As can be seen, by changing the prototype, we're changing the behavior - value will be different values.

Zirak
  • 38,920
  • 13
  • 81
  • 92
  • Thanks Zirak, it was a wondeful explanation of instanceof as well as another question. – P K Nov 27 '11 at 13:47
  • `.constructor` is generally used in meta programming constructs or libraries. – Raynos Nov 27 '11 at 13:47
  • still 1 question, instanceof returns false if i change the original prototype as mentioned in below answer. i believe HasInstance is somehow associated with original prototype. – P K Nov 27 '11 at 13:55
  • @Praveen Yep, your belief is correct. Edited answer to include that as well. – Zirak Nov 27 '11 at 14:18
2

Very nice question!

Since prototypes are Object instances (as everything in JavaScript is), they have to share Object's prototype. Which happens to have the constructor property.

Instances share all properties of their constructor prototypes, including the constructor property.

The constructor property of a function's prototype is specified to reflect the function itself. For example:

Object.prototype.constructor === Object
Function.prototype.constructor === Function
/* the same with every other function */

When you overwrite a constructor function's prototype, like this:

Func.prototype = 1

The prototype itself and all instances of Func have a different constructor property, in the case above – Number.


As for the instanceof, it has nothing to do with the constructor property per se. It has to do with the prototype.

function Func() {}
Func.prototype = { a: 1 } // assign a prototype
var fn = new Func() // create an instance
fn instanceof Func // true (reflects connexion to the original prototype) 
Func.prototype = { b: 2 } // assign a completely different prototype
fn instanceof Func // false (the connexion is broken)
katspaugh
  • 17,449
  • 11
  • 66
  • 103
0

Below little code might clear up your confusion. As you can see the new instance actually does not have its own property called "constructor". So when you are asking for instance.constructor, you are actually getting instance.prototype.constructor value due to prototype chaining. To be consistent you want to see instance.constructor set to same value as the function that created it. This is why JS interpreter sets prototype.constructor to the value of the function itself.

function Rabbit() { }

var rabbit = new Rabbit()

alert( rabbit.hasOwnProperty('constructor') ) // false
alert( Rabbit.prototype.hasOwnProperty('constructor') ) // true

This works same for non-function objects. They don't have their own .constructor property and so the call ultimately ends up in Object.prototype.constructor and hence you get same answer for all non-function objects.

A question to ask at this point is why JS designer made this choice for function objects instead of explicitly setting constructor property of instance to function itself. I don't know the answer but I can guess that it adds more "dynamism" in the language. The instance.constructor can be used to create a new instance in generic way even if you don't have the original function that created the instance.

function makeUnicorn(animal) {
    var unicorn = new animal.constructor();
    unicorn.HornOnNose = true;
    return unicorn;
}

var unicornRabbit = makeUnicorn(rabbit);

Notice that above runs without error for any object, even ones that are not an instance of function. You can conceivably use this JavaScript feature to customize behavior of above "generic" function which you otherwise couldn't if constructor was an own property of the instance.

Horse.prototype.constructor = function() {
   var newHorse = new Horse();
   newHorse.Color = "White";       
   return newHorse;
}
Shital Shah
  • 63,284
  • 17
  • 238
  • 185