13

In the book Secrets of the JavaScript Ninja, 2013, page 125, it says:

Each object in JavaScript has an implicit property named constructor that references the constructor that was used to create the object. And because the prototype is a property of the constructor, each object has a way to find its prototype.

It actually might be one of the most flawed things I heard about JavaScript, and it came from a supposedly expert of JavaScript. Isn't it true that

  1. any JavaScript object "has a way to find its prototype" using the internal [[prototype]] property (as in the ECMA-262 specs, page 32). It is accessible on Chrome and Firefox using __proto__, and in more recently versions of IE, using Object.getPrototypeOf

  2. any object gets to the constructor property by getting it in the prototype object that __proto__ is pointing to. The constructor property is sometimes even not set correctly as some JavaScript libraries or frameworks don't use it at all. constructor is a property of the prototype object, not a property of the object itself:

(as seen in Chrome's developer's tool):

> function Foo() {}
undefined

> var foo = new Foo()
undefined

> foo.hasOwnProperty("constructor")
false

> foo.__proto__.hasOwnProperty("constructor")
true

> foo.__proto__.constructor === Foo
true

Is the above (1) and (2) true? What is the "implicit property named constructor" in JavaScript as in the quoted text? Does it try to mean something like [[prototype]] which is an internal property? But more importantly, I'd like to know whether (1) and (2) above are true and not what the quoted text says it is.

6
  • 1
    foo.constructor === Foo // true Commented Jun 21, 2013 at 13:48
  • @Mathletics foo.constructor === Foo // true so what? of course it is true as the constructor is obtained by going up the prototype chain, and is exactly the same as foo.__proto__.constructor Commented Jun 21, 2013 at 13:51
  • @動靜能量 As far as I know, you are absolutely right. Commented Jun 21, 2013 at 13:52
  • Yes, 1 and 2 are correct. Commented Jun 25, 2013 at 9:06
  • AFAICT from reading the spec, the constructor property is only defined for built-in objects; and for everything else, all bets are off. Commented Jun 30, 2013 at 22:46

3 Answers 3

2

The quoted text is very accurate and explains this mechanism very simply.

"Each object in JavaScript has an implicit property named constructor that references the constructor that was used to create the object."

This is absolutely true, as @Mathletics pointed out:

foo.constructor === Foo // true

..."And because the prototype is a property of the constructor, each object has a way to find its prototype."

This also can be understood plainly as read. Getting the prototype from the constructor is a valid way for an instance to find its prototype.

foo.constructor.prototype // Foo {}

And also

foo.constructor.prototype === foo.__proto__ // true

I think that the way the book describes it, is the most proper one of doing it. The "__proto__" property is named with double underscore on each side for a reason. As you pointed out, it is an internal property, and the double underscore is a widely used convention for naming internal properties. It is not "visible" with hasOwnProperty. Not specifically because it is an internal property, but because it is not set directly on the object itself. This might better explain what hasOwnPropery means more clearly:

foo.a = 4;
foo.a; // 4
foo.hasOwnProperty("a"); // true
foo.constructor.prototype.b = 5;
foo.b; // 5
foo.hasOwnProperty("b"); // false
Sign up to request clarification or add additional context in comments.

2 Comments

var F = function(){}; F.prototype = {}; var x = new F(); x.constructor === F; // false
Yeah, that's true, and it might look confusing. The thing is, that the constructor property isn't a part of each object directly- x.hasOwnProperty('constructor') //false but x.constructor.prototype.hasOwnProperty('constrcutor') //true SO, this means that if you set the prototype of F, you're also overriding the constructor property of its instances implicitly. If you want to keep your constructor property pointing where you expect it to, make sure to add F.prototype.constructor = F; after F.prototype = {} in your example.
1

John Resig is Wrong

Yes, the author of jQuery can make mistakes too. This is what he stated:

Each object in JavaScript has an implicit property named constructor that references the constructor that was used to create the object. And because the prototype is a property of the constructor, each object has a way to find its prototype.

Here are the reasons why his statement is false:

  1. Not every object has a prototype. Hence these objects don't have any implicit properties either.
  2. Not every object that has a prototype is created by a constructor function. This however doesn't include object, array and regular expression literals and functions since these objects are implicitly created by constructor functions.
  3. Not every object that has a prototype and is created by a constructor function has an implicit property named constructor.
  4. Not every object that has a prototype, is created by a constructor and has an implicit property named constructor has that property point to the constructor function that created that object.
  5. Not every object that has a prototype, is created by a constructor and has an implicit property named constructor that points to the constructor function that created that object, has a property called prototype on its constructor function.
  6. Not every object that has a prototype, is created by a constructor, has an implicit property named constructor that points to the constructor function that created that object and has a property called prototype on its constructor function, has that property point to the prototype of that object.

Let's prove these statements by example to prove that John Resig's statement is false. Since all these statements begin with the assertion "not every object" we only need to find one example of each statement to prove that John Resig's statement is false.

Proof for Statement 1

The Object.create method can be used to create a new object and set its internal [[prototype]] property. Hence it can be used to create an object which has no prototype:

var o = Object.create(null); // o has no prototype

The object in the above example has no prototype - it's internal [[prototype]] property is set to null. Hence it doesn't have any implicit properties either.

Proof for Statement 2

Now let's create another object p which inherits from object o as follows:

var p = Object.create(o); // the prototype of p is o

Hence the object p has a prototype but it wasn't created by a constructor.

Proof for Statement 3

Alright let's create the object p from a constructor instead (actually this is precisely how the Object.create function is implemented):

function F() {}  // F is a constructor
F.prototype = o; // objects constructed by F inherit from o
var p = new F;   // p is an object which is constructed by F

Here the object p is created by the constructor F. However it doesn't have any implicit property named constructor.

Proof for Statement 4

What if the variable o was assigned an object literal and then used as the prototype property of constructor F?

var o = {};      // object literals inherit from Object.prototype
function F() {}  // F is a constructor
F.prototype = o; // objects constructed by F inherit from o
var p = new F;   // p is an object which is constructed by F

Now the object p has an implicit property named constructor but it points to Object instead of F. Hence p.constructor.prototype points to Object.prototype instead of o.

Proof of Statement 5

Perhaps you think the problem is inheritance? Alright, let's do away with inheritance altogether. Starting from scratch:

var p = new F;      // p is constructed by F, it inherits from F.prototype
delete F.prototype; // devious isn't it? I love being naughty
function F() {}     // declarations are hoisted

Alright so now the object p inherits from F.prototype and it has an implicit property named constructor which points to F itself. However since we deleted the prototype property from F we can't access the prototype of p via p.constructor.prototype (it will now return undefined).

Proof of Statement 6

Let's modify the last example a bit. Instead of deleting F.prototype we'll set it to something else. For instance:

var o = {};      // object literals inherit from Object.prototype
var p = new F;   // p is constructed by F, it inherits from F.prototype
F.prototype = o; // oops, what will happen now?
function F() {}  // declarations are hoisted

Now the object p inherits from F.prototype and it has an implicit property named constructor which points to F itself. However since we set F.prototype to o when we access p.constructor.prototype we'll get o instead of the original F.prototype.

Conclusion

As you can see John Resig's statement is totally false. We didn't need 6 examples to prove this. Any one example would suffice. However I wanted to show just how wrong his statement is. Hence I wrote every possible example that I could think of that disproves his statement.

JavaScript is a prototypal object oriented programming language which means that objects inherit from other objects. Constructors are not strictly required to create objects. However they are given undue importance because unfortunately that's the way prototypal inheritance works in JavaScript.

The constructor pattern of prototypal inheritance is often confusing and misleading. In addition it hides the true way of prototypal inheritance which doesn't use constructors (the prototypal pattern of prototypal inheritance). To know more about it read the following answer: https://stackoverflow.com/a/17008403/783743

5 Comments

Your examples are valid and somewhat amusing, but I find them to be mostly misleading for developers that are trying to understand the meaning of the constructor and prototype properties. JS is a dynamic OO language, and that also means you can break its default behavior by using such magic tricks. I could also just call delete ({}).constructor.prototype.constructor which will make all objects lose their constructor property, thus disproving John's statement, but that would be silly. Perhaps he should've ended his quote with ... unless you try to break something on purpose
@NaorBiton JavaScript is a prototypal object oriented programming language. However inheritance in JavaScript is constructor-oriented instead of prototype-oriented. That's the reason it's so confusing. The code you provided doesn't make all objects lose their constructor property. It simply deletes Object.prototype.constructor. That's it. If an object f inherits from F.prototype which in turn inherits from Object.prototype then f.constructor will still point to F.
You're right about the code I wrote, I should've pointed out that it would remove the constructor from all object literals and others that are inheriting from Object directly. Still, using such examples to prove that John Resig is wrong, could be misleading, because what he describes are valid concepts. I agree that there is more to JS inheritance than constructors, and that you don't have to use them to properly structure your objects (the other answer you referenced shows exactly that), but sometimes constructors are useful with a variety of patterns you can use with JS.
@NaorBiton They are only valid under very specific circumstances. Hence beginning the statement with the assertion "every object in JavaScript" is logically wrong. Subject to rigorous mathematical reasoning the statement doesn't hold true. Hence John Resig's statement is misleading. Not mine.
That is not "precisely" how Object.create is implemented. It ignores the second argument and for example in V8 the implementation doesn't create a new function object just to use new on it.
0

How I learned it and what can be observed

Every object has a __proto__ property, every function has an additional prototype property. That prototype is an object itself and has a property called constructor that points to the original function:

function C(){}
console.log(C.hasOwnProperty("prototype")); //true
console.log(C.prototype.hasOwnProperty("constructor")); //true
console.log(C.prototype.constructor === C); //true

When an object is created, the __proto__ property of it is set to point to the prototype property of its constructor function:

var c = new C();
console.log(c.__proto__ === C.prototype) //true

All the information about what c is, does it know from its __proto__ property. That can be observed by simply changing the __proto__ property by hand:

function D(){}
c.__proto__ = D.prototype;
console.log(c.constructor === D) //true
console.log(c instanceof D) //true

So considering all of this, it would be really hard to believe that there is a constructor property from which everything derives. But there still could be in internal constructor property (i.e. __constr__), that we cannot access but which is accessed, when the prototype is requested. At least it would be possible I guess.

One thing that also does confuse me a little, is this:

console.log(c.hasOwnProperty("__proto__")) //false

My guess would be that __proto__ just doesn't get grabbed by the hasOwnProperty method, but maybe someone else can shed some light on this.

FIDDLE

What does ECMA say

Here are also some excerpts from the ECMA Spec:

All objects have an internal property called [[Prototype]]. The value of this property is either null or an object and is used for implementing inheritance. Whether or not a native object can have a host object as its [[Prototype]] depends on the implementation. Every [[Prototype]] chain must have finite length (that is, starting from any object, recursively accessing the [[Prototype]] internal property must eventually lead to a null value). Named data properties of the [[Prototype]] object are inherited (are visible as properties of the child object) for the purposes of get access, but not for put access. Named accessor properties are inherited for both get access and put access

And:

8.12.2 [[GetProperty]] (P)

When the [[GetProperty]] internal method of O is called with property name P, the following steps are taken:

  1. Let prop be the result of calling the [[GetOwnProperty]] internal method of O with property name P.

  2. If prop is not undefined, return prop.

  3. Let proto be the value of the [[Prototype]] internal property of O.

  4. If proto is null, return undefined.

  5. Return the result of calling the [[GetProperty]] internal method of proto with argument P.

My Conclusion

ECMA clearly states that there IS an internal prototype property, which wouldn't really make sense if JavaScript still would access some internal constructor property first, to access something that is already there. Also, everything that can be tested points to the idea of the constructor being a property of the prototype and not the other way around.

So I would say it is safe to say, that this is how it works.

I also reread your quote from Jon Resig. I think what he means with the prototype is a property of the constructor is the prototype property that we can directly access and that every function has. He is also not super specific here. I guess he just wanted a simple explanation and didn't want to confuse people right off.

2 Comments

I think c.hasOwnProperty("__proto__") is false because __proto__ is an internal property and it is not to be checked by using hasOwnProperty -- or hasOwnProperty won't report the internal property
@動靜能量 yes, i guess that's it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.