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:
- Not every object has a prototype. Hence these objects don't have any implicit properties either.
- 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.
- Not every object that has a prototype and is created by a constructor function has an implicit property named
constructor.
- 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.
- 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.
- 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
foo.constructor === Foo // truefoo.constructor === Foo // trueso what? of course it is true as theconstructoris obtained by going up the prototype chain, and is exactly the same asfoo.__proto__.constructor