Prototype keyword in Javascript

html, javascript

Solution

"Prototype" is something that plays a role in objects.

In Javascript, everything is an object. Every object has a kind, and thus inherits the `prototype` of that kind.

For example, take a simple array: `var a = []`. You can make operations with it, like `a.push(10)`. Where does this `push` method come from? From the prototype of `Array` object, which `a` is.

You can add your own methods to `Array` objects just by defining them in the `prototype` object. For example:

Array.prototype.sortNum = function() {this.sort(function(a, b) {return a - b});};

This way you can do something like `a.sortNum()` with all arrays, even the ones created before you defined the `sortNum` method.

(Note: for compatibility reasons, it's usually not recommended to extend the prototype of native objects like `Array`s. But this particular example is usually a welcome addition, as well as normalizing methods like `map` and `forEach` for older browsers.)

(Just never ever extend `Object.prototype`! Unless you don't care to mess up `for...in` statements, the `in` operator and these sort of cases.)

If you want to define your own classes, like the name `MyConstructor` suggests, you'll have to define its `prototype` to define the methods for all the instances of that class:

function MyConstructor(name) {this.name = name};
MyConstructor.prototype = {
    print: function() {return this.name;}
};

var mc = new MyConstructor("foo");
alert(mc.print()); // alerts "foo"

You can define more than just functions in `prototype`s, too:

MyConstructor.prototype.age = 30;

alert(mc.age); // alerts 30

Watch out when you do this to define "default" object values, because changing it may cause a change in all instances of that class.

But this comes handy with `Object.defineProperty`:

Object.defineProperty(MyConstructor.prototype, "wholeString", {
    get: function() {return this.name + "=" + this.age;},
    set: function(v) {this.name = v.substring(3);}
});

alert(mc.wholeString); // alerts "foo = 30"

(Unfortunately, IE<9 allows this only for DOM objects...)

When you define `MyConstructor.age = 30` instead, what you're actually doing is defining a member of the function `MyConstructor`, so `mc.age` would be undefined. Every instance of `MyConstructor` inherits the methods and members defined in `MyConstructor.prototype`, not the ones of the function `MyConstructor`.

There's much more to say, actually. Objects can be of a subclass of another class, thus inheriting the `prototype` of the superclass, too. For example, `document.body` is an instance of `HTMLBodyElement`, which is a subclass of `HTMLElement`, which is a subclass of `Element` and so on, until you get `Object` as the upmost superclass. So, `document.body` inherits all the methods defined in the prototype of `HTMLBodyElement`, `HTMLElement`, `Element` and `Object`. This is called the prototype chain.

Doing the same with custom objects is a bit tricky:

function Class() {};
Class.prototype.foo = function() {alert("foo");};

function Subclass() {};
Subclass.prototype = new Class();
Subclass.prototype.bar = function() {alert("bar");};

var a = new Class(), b = new Subclass();
a.foo(); // alerts"foo"
a.bar(); // throws an error
b.foo(); // alerts "foo"
b.bar(); // alerts "bar"

a instanceof Class;    // true
a instanceof Subclass; // false
b instanceof Class;    // true
b instanceof Subclass; // true

Problem

What is `prototype` property, and why is it necessary? So far, I have learnt that this provides public access to more intrinsic, and private `prototype` of the object; is that correct? Also, what's the difference between following statements? ``` MyConstructor.age = 30; MyConstructor.prototype.age = 30; ``` In short, I need a better understanding of keyword `prototype`. Thanks

Original source

Related problems