The Classical Form
new key word in an attempt to match a Classical implementation. The function
Square() defines a class with a side attribute. It also has two instance methods,
We can then create
new works differently. It creates an empty object and then calls the
Square() function (or the constructor) passing the empty object into
The constructor then populates that object with the specified behavior before returning it. This is particularly scary, because if you forget to put
new in front of the constructor,
this will refer to the Global Object, as will
mySquare (meaning any further changes made to
mySquare would also be on the
Ok, so we have our
Square, but say we want to create a square that holds a
X or an
O. Well, we would want to inherit the properties of our current
Square class and then add to them. We might do something like this:
We create a new class for the
ContainerSquare which uses the Square's constructor to define the
side attribute, along with the two instance methods. We then define our new
contents attribute, along with an accessor method to go with it.
Line 6 sets up a prototypal inheritance structure so that a
ContainerSquare object will be linked to the proper prototype chain.
The prototype chain is the hierarchy of objects that a method or attribute call will traverse until it finds what it is looking for. In other words, when I call
myContainer object has that function.
If not, it will proceed to check the object's prototype, which is the
ContainerSquare doesn't have the function, next in line is the
ContainerSquare prototype, which is just
Square does in fact have a
Thus, by setting the
ContainerSquare prototype to
Square, we inherit any of the attributes or methods of
The Prototypal Form
We can start with the
square. There are few pretty simple ways to achieve the same functionality using regular objects and their prototypes, and we will look at two of them. The first will create a
square object we can use.
Then if we need more
squares, we can make a copy of that object using its prototype. The second will create a
squareMaker function, which can then be used to produce new
Here, we already have a new and usable
square at our disposal. We don't need to call a constructor and define any types. We can just take an object and mold it into the form we want.
Say we want another
square though. We can't just write something like
secondSquare would just point to the
What we can do, and this is a technique developed by Douglas Crockford, is make a copy of our object by calling a new constructor with a
prototype that points to our object. This new constructor creates a new empty object and assigns the values of our old object to the new empty object.
You can do this yourself, or you can use Crockford's technique as follows:
You can see that we are actually defining an on-the-fly constructor
F, using our object
o to define
F.prototype. Then we create a new object using that constructor. This will give us a new copy of our object, with all its attributes and functions. If we now called
secondSquare.area(); we would get 36.
If you wanted to then make a
ContainerSquare, you could simply add a contents attribute to the
secondSquare, and then make copies of the
secondSquare if you need more Containers.
Keep in mind that since
firstSquare is the prototype of
secondSquare, if you were to add a contents attribute to
firstSquare, you would then have that attribute on
secondSquare. However, adding attributes to the
secondSquare does not place them on the
Spawn More Protolords
The other way to get squares would be to make a
squareMaker function. This function will return a new object with whatever attributes you define. I am also going to show you some closure so that the attributes are private, and only accessible through accessor methods.
You will notice that the return value of the
squareMaker is almost exactly like how we defined our
firstSquare object. We are just returning the definition
square, and thats quite awesome.
Another thing you will notice is the bit of closure. We pass a value into the
squareMaker, but it isn't stored anywhere. It is held in the scope of the
squareMaker function, allowing those internal methods to use it, but hiding it from the outside (unlike the side attribute defined in the
To get the container functionality we create a
containerMaker using the
squareMaker, and some more closure, to make a new square object. We then dynamically add a
getContents method to provide access to our private contents attribute.
I will admit one slight inefficiency with the two solutions I showed you (although there are ways around this). Using the
squareMaker, or making copies of the objects will make full copies, including the function objects defined inside.
If you use the classical scheme I showed, you are defining functions on the prototype rather than the object itself, thus there will only be one copy of the function.
Trying to fit a square into a circular hole will just get you stuck. All languages are unique with a variety of their own advantages, and as good developers we should recognize these differences and reap all the benefits they have to offer.