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
mySquare in almost the same way we might do it in Java.
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
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
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
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
will use the first function it finds, it will use Square's
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
and thus the
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
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
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
However, adding attributes to the
secondSquare does not place them on
Spawn More Protolords
The other way to get squares would be to make a
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
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
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.