What’s the difference between these two method of defining a ‘class’ in JavaScript?
Method One
Define method within the constructor:
function MyClass()
{
this.foo = function() { console.log('hello world!'); };
}
Method Two
Define method on the prototype:
function MyClass()
{}
MyClass.prototype.foo = function() { console.log('hello world!'); };
The first will create a new function object on each instantiation of your object, the second will assign a reference to a prototype method to each instance. In short: the second is more efficient, because all instances will share a single function object.
That’s just the logic of a prototype chain, you can try and access anything via any object:
When accessing
objLiteral.fooJS will first look at the properties that the object itself has defined, and return the value if it is found. If JS can’t find the property on the object itself, it’ll check the object’s prototype, hence:But when you use your first method:
That shows that we’re dealing with 2 separate function objects. Move the function definition to the prototype and
f.methd === g.methd;will be true:In response to your comment:
Defining a method on a prototype-level allows you to change a method for a specific task, and then “reset” it back to it’s default behaviour. Suppose you’re in a function that’s creating an AJAX request:
Again JS will check if the object has the
toStringproperty defined on itself, which it has. So JS will delete the function you’ve assigned to thetoStringproperty. Next time thetoStringwill be invoked, JS will start scanning the prototype chain all over again, and use the first occurance of the method (in the prototype). Let’s clarify:Or even better, you can even replace an instance’s method by a method from another prototype:
the last example is pointless, because f has the
valueOfmethod already: its inheritance chain looks like this:var f ---> SomeConstructor ---> Object, giving you access to all Object.prototype methods, too! Neat, isn’t it?These are just dummy examples, but I hope you see this is one of those features that make JS an incredibly flexible (sometimes too flexible, I must admit) and expressive language.