In JavaScript, there is an unfortunate overloading of the term “prototype”.
Prototype 1: relationship between objects
On one hand, we have the prototype relationship between objects. Some properties in the ECMAScript laguage specification are
internal. Internal properties are not directly accessible in JavaScript and their names are written in double square brackets. [[Prototype]], one such property, is used to establish the prototype relationship. An object points to its prototype via [[Prototype]] and inherits all of its properties. In ECMAScript 5, one can read the prototype of an object via
Object.getPrototypeOf().
> Object.getPrototypeOf({}) === Object.prototype
true
And one can create a new object with a given prototype via
Object.create():
> var proto = { foo: 123 };
> var obj = Object.create(proto);
> obj.foo
123
[1] has more on these two functions. ECMAScript 6 will allow you to access an object’s prototype via the special property
__proto__ [2].
Prototype 2: property of constructors
On the other hand, each constructor has the property
prototype which points to an object that becomes the prototype of all instances created by that constructor.
> function Foo() {}
> var f = new Foo();
> Object.getPrototypeOf(f) === Foo.prototype
true
Resolving the name clash
Usually the context makes it clear which of the two prototypes is meant. Should disambiguation be necessary then we are stuck with “prototype” for the relationship between objects, because that name has made it into the standard library, via
getPrototypeOf. We thus need to find a different name for the object referenced by the
prototype property. One possibility is “constructor prototype”, but that is problematic, because constructors have prototypes, too:
> function Foo() {}
> Object.getPrototypeOf(Foo) === Function.prototype
true
Thus, “instance prototype” seems the best option.
References
- JavaScript inheritance by example
- JavaScript: __proto__
7 comments:
If you're referring to an object's 'prototype' then you're almost always referring to its [[Prototype]]. If you're referring to a function's 'prototype' you're almost always referring to its prototype property (you'd instead refer to 'Function.prototype' if you were talking about a function's [[Prototype]]). It's only when it's not clear who's 'prototype' is being referred to is the disambiguation required. I use 'proto' for referring to [[Prototype]] or 'prototype property' to refer to func.prototype.
Good point about context, I edited the post. I’d want to distinguish between the prototype property and the object it points to, though.
Good post, it also helps to see the chained call from Function to Object via
Object.getPrototypeOf(f).__proto__
I can't believe they let prototypes be such a confusing subject in ECMAScript. One can get out of mind while passing through all this confusion.
It's only now after reading this article 3 times that I've got this "a-ha" feeling about prototypes after years of playing with JavaScript. And still I'm not certain.
Is it true that what V8 and few other engines call "__proto__" is the same as what ECMAScript 5 calls "internal property [[Prototype]]"?
Thank you for your helpful writings, Axel Rauschmayer!
Good article - one of those confusing JavaScript subjects.
The rule to keep in mind is: the prototype relationship between objects is simple; constructors are what is complicated about JavaScript. I’ve written a post that explains what JavaScript would be like without constructors:
http://www.2ality.com/2011/06/prototypes-as-classes.html
“Is it true that what V8 and few other engines call "__proto__" is the
same as what ECMAScript 5 calls "internal property [[Prototype]]"?”
__proto__ is a way of accessing the internal property [[Prototype]] from JavaScript (see reference [2] for details).
What you think of this simple diagram, showing the relations of __proto__, prototype & constructor:
http://img443.imageshack.us/img443/993/jsobjects.png
Post a Comment