facebook@jsbanktwitter@js_bankgoogle+javascriptbanknewsletterrss@jsbank
Guest, register






ieoBIN.com - The Best IEO List to Discover, Invest in 2019

JavaScript Prototype: Some Basic Concepts A short JavaScript article tutorial to give an overview of prototype in JavaScript, with some JavaScript code examples. Please go to the inner page for full detailed instructions and JavaScript codes.


JavaScript's prototype object generates confusion wherever it goes. Seasoned JavaScript professionals, even authors frequently exhibit a limited understanding of the concept. I believe a lot of the trouble stems from our earliest encounters with prototypes, which are almost always related to new, constructor and the very misleading prototype property attached to functions. In fact prototype is a remarkably simple concept. To understand it better, we just need to forget what we 'learned' about constructor prototypes and start again from first principles.

What is a prototype?

A prototype is an object from which other objects inherit properties

Can any object be a prototype?

Yes.

Which objects have prototypes?

Every object has a prototype by default. Since prototypes are themselves objects, every prototype has a prototype too. (There is only one exception, the default object prototype at the top of every prototype chain. More on prototype chains later)

OK back up, what is an object again?

An object in JavaScript is any unordered collection of key-value pairs. If its not a primitive (undefined, null, boolean, number or string) its an object.

You said every object has a prototype. But when I write ({}).prototype I get null. Are you crazy?

Forget everything you learned about the prototype property - it's probably the biggest source of confusion about prototypes. The true prototype of an object is held by the internal [[Prototype]] property. ECMA 5 introduces the standard accessor Object.getPrototypeOf(object) which to-date is only implemented in Firefox and Chrome. In addition all browsers except IE and Opera support the non-standard accessor __proto__. Failing that we need to ask the object's constructor for its prototype property.

01var a = {};
02 
03//Firefox 3.6 and Chrome 5
04Object.getPrototypeOf(a); //[object Object]
05 
06//Firefox 3.6, Chrome 5 and Safari 4
07a.__proto__; //[object Object]
08 
09//all browsers
10a.constructor.prototype; //[object Object]

Ok fine, but false is a primitive, so why does false.__proto__ return a value?

When a primitive is asked for it's prototype it will be coerced to an object.

1//(works in IE too, but only by accident)
2false.__proto__ === Boolean(false).__proto__; //true

I want to use prototypes for inheritance. What do I do now?

It rarely makes sense to set a prototype for one instance and only one instance, since it would be equally efficient just to add properties directly to the instance itself. I suppose if we have created a one off object which we would like to share the functionality of an established object, such as Array, we might do something like this (in __proto__ supporting browsers).

1//unusual case and does not work in IE
2var a = {};
3a.__proto__ = Array.prototype;
4a.length; //0

But the real power of prototype is seen when multiple instances share a common prototype. Properties of the prototype object are defined once but inherited by all instances which reference it. The implications for performance and maintenance are obvious and significant.

So is this where constructors come in?

Yes. Constructors provide a convenient cross-browser mechanism for assigning a common prototype on instance creation.

Just before you give an example I need to know what this constructor.prototype property is all about?

OK. Firstly JavaScript makes no distinction between constructors and other functions, so every function gets a prototype property. Conversely, anything that is not a function does not have such a property.

01//function will never be a constructor but it has a prototype property anyway
02Math.max.prototype; //[object Object]
03 
04//function intended to be a constructor has a prototype too
05var A = function(name) {
06    this.name = name;
07}
08A.prototype; //[object Object]
09 
10//Math is not a function so no prototype property
11Math.prototype; //null

So now the definition: A function's prototype property refers to the object that will be assigned as the prototype to all instances created when this function is used as a constructor.

It's important to understand that a function's prototype property has nothing to do with it's actual prototype.

1//(example fails in IE)
2var A = function(name) {
3    this.name = name;
4}
5 
6A.prototype == A.__proto__; //false
7A.__proto__ == Function.prototype; //true - A's prototype is set to its constructor's prototype property

Example please?

You've probably seen and used this a hundred times but here it is once again, maybe now with added perspective.

01//Constructor. <em>this</em> is returned as new object and its internal [[prototype]] property will be set to the constructor's default prototype property
02var Circle = function(radius) {
03    this.radius = radius;
04    //next line is implicit, added for illustration only
05    //this.__proto__ = Circle.prototype;
06}
07 
08//augment Circle's default prototype property thereby augmenting the prototype of each generated instance
09Circle.prototype.area = function() {
10   return Math.PI*this.radius*this.radius;
11}
12 
13//create two instances of a circle and make each leverage the common prototype
14var a = new Circle(3), b = new Circle(4);
15a.area().toFixed(2); //28.27
16b.area().toFixed(2); //50.27

That's great. And if I change the constructor's prototype, even existing instances will have access to the latest version right?

Well....not exactly. If I modify the existing prototype's property then this is true, because a.__proto__ is a reference to the object defined by A.prototype at the time it was created.

01var A = function(name) {
02    this.name = name;
03}
04 
05var a = new A('alpha');
06a.name; //'alpha'
07 
08A.prototype.x = 23;
09 
10a.x; //23

But if I replace the prototype property with a new object, a.__proto__ still references the original object.

01var A = function(name) {
02    this.name = name;
03}
04 
05var a = new A('alpha');
06a.name; //'alpha'
07 
08A.prototype = {x:23};
09 
10a.x; //null

What does a default prototype look like?

An object with one property, the constructor.

1var A = function() {};
2A.prototype.constructor == A; //true
3 
4var a = new A();
5a.constructor == A; //true (a's constructor property inherited from it's prototype)

What does instanceof have to do with prototype?

The expression a instanceof A will answer true if a's prototype falls within the same prototype chain as A's prototype property. This means we can trick instanceof into failing

01var A = function() {}
02 
03var a = new A();
04a.__proto__ == A.prototype; //true - so instanceof A will return true
05a instanceof A; //true;
06 
07//mess around with a's prototype
08a.__proto__ = Function.prototype;
09 
10//a's prototype no longer in same prototype chain as A's prototype property
11a instanceof A; //false

So what else can I do with prototypes?

Remember I said that every constructor has a prototype property which it uses to assign prototypes to all instances it generates? Well that applies to native constructors too such as Function and String. By extending (not replacing!) this property we get to update the prototype of every instance of the given type.

I've used this technique in numerous previous posts to demonstrate function augmentation. For example the tracer utility I introduced in my last post needed all string instances to implement times, which returns a given string duplicated a specified number of times

1String.prototype.times = function(count) {
2    return count < 1 ? '' : new Array(count + 1).join(this);
3}
4 
5"hello!".times(3); //"hello!hello!hello!";
6"please...".times(6); //"please...please...please...please...please...please..."

Tell me more about how inheritance works with prototypes. What's a prototype chain?

Since every object and every prototype (bar one) has a prototype, we can think of a succession of objects linked together to form a prototype chain. The end of the chain is always the default object's prototype.

1a.__proto__ = b;
2b.__proto__ = c;
3c.__proto__ = {}; //default object
4{}.__proto__.__proto__; //null

The prototypical inheritance mechanism is internal and non-explicit. When object a is asked to evaluate property foo, JavaScript walks the prototype chain (starting with object a itself), checking each link in the chain for the presence of property foo. If and when foo is found it is returned, otherwise undefined is returned.

What about assigning values?

Prototypical inheritance is not a player when property values are set. a.foo = 'bar' will always be assigned directly to the foo property of a. To assign a property to a prototype you need to address the prototype directly.

And that about covers it. I feel I have the upper hand on the prototype concept but my opinion is by no means the final word. Please feel free to tell me about errors or disagreements.

Where can I get more information on protoypes?

I recommend this excellent article by Dmitry A. Soshnikov

JavaScript by day


Google Safe Browsing McAfee SiteAdvisor Norton SafeWeb Dr.Web