What's the difference between
var A = function () {
this.x = function () {
//do something
};
};
and
var A = function () { };
A.prototype.x = function () {
//do something
};
What's the difference between
var A = function () {
this.x = function () {
//do something
};
};
and
var A = function () { };
A.prototype.x = function () {
//do something
};
What's the difference? => A lot.
I think, the
this
version is used to enable encapsulation, i.e. data hiding. It helps to manipulate private variables.Let us look at the following example:
Now, the
prototype
structure can be applied as following:Different adults have different ages, but all of the adults get the same rights.
So, we add it using prototype, rather than this.
Lets look at the implementation now.
Hope this helps.
Think about statically typed language, things on
prototype
are static and things onthis
are instance related.I believe that @Matthew Crumley is right. They are functionally, if not structurally, equivalent. If you use Firebug to look at the objects that are created using
new
, you can see that they are the same. However, my preference would be the following. I'm guessing that it just seems more like what I'm used to in C#/Java. That is, define the class, define the fields, constructor, and methods.EDIT Didn't mean to imply that the scope of the variable was private, I was just trying to illustrate how I define my classes in javascript. Variable name has been changed to reflect this.
Let me give you a more comprehensive answer that I learned during a JavaScript training course.
Most answers mentioned the difference already, i.e. when prototyping the function is shared with all (future) instances. Whereas declaring the function in the class will create a copy for each instance.
In general there is no right or wrong, it's more a matter of taste or a design decision depending on your requirements. The prototype however is the technique that is used to develop in an object oriented manner, as I hope you'll see at the end of this answer.
You showed two patterns in your question. I will try to explain two more and try to explain the differences if relevant. Feel free to edit/extend. In all examples it is about a car object that has a location and can move.
Object Decorator pattern
Not sure if this pattern is still relevant nowadays, but it exists. And it is good to know about it. You simply pass an object and a property to the decorator function. The decorator returns the object with property and method.
Functional Classes
A function in JavaScript is a specialised object. In addition to being invoked, a function can store properties like any other object.
In this case
Car
is a function (also think object) that can be invoked as you are used to do. It has a propertymethods
(which is an object with amove
function). WhenCar
is invoked theextend
function is called, which does some magic, and extends theCar
function (think object) with the methods defined withinmethods
.This example, though different, comes closest to the first example in the question.
Prototypal Classes
The first two patterns allow a discussion of using techniques to define shared methods or using methods that are defined inline in the body of the constructor. In both cases every instance has its own
move
function.The prototypal pattern does not lend itself well to the same examination, because function sharing via a prototype delegation is the very goal for the prototypal pattern. As others pointed out, it is expected to have a better memory footprint.
However there is one point interesting to know: Every
prototype
object has has a convenience propertyconstructor
, which points back to the function (think object) it came attached to.Concerning the last three lines:
In this example
Car
links to theprototype
object, which links viaconstructor
toCar
itself, i.e.Car.prototype.constructor
isCar
itself. This allows you to figure out which constructor function built a certain object.amy.constructor
's lookup fails and thus is delegated toCar.prototype
, which does have the constructor property. And soamy.constructor
isCar
.Furthermore,
amy
is aninstanceof
Car
. Theinstanceof
operator works by seeing if the right operand's prototype object (Car
) can be found anywhere in the left operand's prototype (amy
) chain.Some developers can be confused in the beginning. See below example:
The
instanceof
operator returnsfalse
, becauseDog
's prototype cannot be found anywhere infido
's prototype chain.fido
is a simple object that is created with an object literal, i.e. it just delegates toObject.prototype
.Pseudoclassical patterns
This is really just another form of the prototypal pattern in simplified form and more familiar to do those who program in Java for example, since it uses the
new
constructor.It does the same as in the prototypal pattern really, it is just syntactic sugar overtop of the prototypal pattern.
However, the primary difference is that there are optimizations implemented in JavaScript engines that only apply when using the pseudoclassical pattern. Think of the pseudoclassical pattern a probably faster version of the prototypal pattern; the object relations in both examples are the same.
Finally, it should not be too difficult to realize how object oriented programming can be done. There are two sections.
One section that defines common properties/methods in the prototype (chain).
And another section where you put the definitions that distinguish the objects from each other (
loc
variable in the examples).This is what allows us to apply concepts like superclass or subclass in JavaScript.
Feel free to add or edit. Once more complete I could make this a community wiki maybe.
As others have said the first version, using "this" results in every instance of the class A having its own independent copy of function method "x". Whereas using "prototype" will mean that each instance of class A will use the same copy of method "x".
Here is some code to show this subtle difference:
As others have mentioned, there are various reasons to choose one method or the other. My sample is just meant to clearly demonstrate the difference.
I know this has been answered to death but I'd like to show an actual example of speed differences.
Here we're creating 2,000,000 new objects with a
print
method in Chrome. We're storing every object in an array. Puttingprint
on the prototype takes about 1/2 as long.