Embrace prototypal object-oriented programming

JavaScript, the lowest-level programming interface
to the web, is everywhere. As the web becomes increasingly a part of daily life, JavaScript
becomes more and more relevant. JavaScript is an often-misunderstood language,
considered by some a toy language or a "baby Java™ language." One of its more maligned
features is its prototypal object system. Though it's undeniable that JavaScript has
warts, the prototypal object system isn't one of them. In this article, learn about the
tremendous power, simplicity, and elegance of
JavaScript prototypal object-oriented programming.

Delon Newman has been programming for fun since 1997. He started with C and C++ and
later moved on to HTML, Perl, and JavaScript. He has worked in IT since 1999 as
a help desk support technician, graphic designer, web designer, systems administrator,
programmer, analyst, and software engineer. While working for his own company and as a
consultant, Delon has explored many languages and environments including Ruby, Python, Java, C#,
PHP, Smalltalk, Lisp, Haskell, Erlang, Scala, and Clojure. You can reach Delon at
delon.newman@gmail.com.

A world of objects

As you go about the day—driving to work, sitting at a desk performing
a task, eating a meal, walking through a park—you can usually manipulate and
interact with your world without having
to know the detailed physical laws that govern it. You can treat
the various systems you deal with each day as units, or objects. You take for
granted their complexity and focus instead on your interactions with them.

History

Simula, a language for modeling, is generally considered the first
object-oriented language. Then came Smalltalk, C++, the
Java language, and C#. At that point, in most
OO languages objects were defined by class. Later,
developers of the Self programming language, a Smalltalk-like system, created
an alternative and lighter-weight method of defining objects called prototype-based or
prototypal OO programming.

Eventually, JavaScript was developed with a prototype-based object system.
JavaScript's popularity has brought prototype-based objects to the mainstream.
Though many developers find this distasteful, upon closer inspection
prototype-based systems have many advantages.

Object-oriented (OO) programming, which is an attempt to create software systems that work
similarly, is a powerful and wildly popular
modeling tool for software development. It's popular because it
reflects the way we view the world: as a collection of objects that
can interact with each other and be manipulated in various ways. The power of
OO programming lies in its two core principles:

Encapsulation

Lets developers conceal the inner workings of their data structures
and reveal reliable programming interfaces that can be used to create modular,
adaptable software. Think of it as information hiding.

Inheritance

Amplifies the power of encapsulation
by allowing objects to inherit the encapsulated behavior of other objects. Think of it
as information sharing.

These principles are well known to most developers because every mainstream
programming language supports OO
programming (and, in many cases, enforces it). Although all OO languages
support the two core principles, in
one form or another, over the years there have been at least two fundamentally
different ways of defining objects.

In this article, learn about the benefits of prototypal OO programming and
JavaScript object patterns.

Prototypo-what? Classes and prototypes

A class provides an abstract definition of objects that defines
shared data structures and methods for an entire class or collection of objects.
Each object is defined as an instance of its class. Classes are also given the
responsibility of constructing class objects according to their definitions and
(optionally) by user parameters.

A classic example is the Point class and its child
Point3D for defining two-dimensional and
three-dimensional points, respectively. Listing 1 shows how the classes would look in
Java code.

In contrast to defining objects by class, prototypal object systems support a more
direct method of object creation. For example, in JavaScript an object
is a simple list of properties. Each object contains a special reference to
another parent, or prototype, object from which it inherits behavior.
You can mimic the Point example in JavaScript, as shown in Listing 2.

There's a fundamental difference between classical and prototypal object systems.
Classical objects are defined abstractly as part of a conceptual
group and inherit characteristics from other classes, or groups, of
objects. In contrast, prototypal objects are defined concretely as
specific objects and inherit behavior from other specific objects.

Thus, a class-based OO language has a dual nature that requires at least two fundamental constructs: classes and objects. As
a result of this duality,
as class-based software grows, complex class hierarchies tend to develop. It's generally impossible to predict all the ways classes will need to be used
in the future, so the class hierarchy needs to be constantly refactored
to facilitate changes.

Prototype-based languages eliminate the need for the above-mentioned duality and facilitate
the direct creation and manipulation of objects. Without objects being bound by
class, more loosely bound systems of objects can be created that help to maintain
modularity and reduce the need for refactoring.

Being able to directly define objects also adds tremendous power and simplicity to
object creation and manipulation. For instance, in Listing 2, you can
simply declare your point object with one line:
var point = { x: 0, y: 0 };.
With this one line, you have a complete working object that inherits behavior from
JavaScript's Object.prototype, such as the
toString method. To extend your
object's behavior, you simply declare another object with point
as its prototype. In contrast, even with the most concise classical OO
language, you would have to first define a class, then instantiate it before you
have a manipulatable object. To inherit, you would have to define another
class to extend the first class.

The prototype pattern is conceptually simpler. As humans, we often think in terms
of prototypes. For example, in Steve Yegge's blog entry "The Universal
Design Pattern" (see Resources), he cites the example of an American football player—say,
Emmitt Smith—who with his speed, agility, and shear force becomes the
prototype for all new players in the National Football League (NFL). Then, when an
exceptional new running back, LT, gets picked up, commentators say:

"LT's got legs like Emmitt."
"He can plow through the line just like Emmitt."
"But he runs the mile in five minutes flat!"

The commentators are modeling a new object—LT—in terms of a
prototype object, Emmitt Smith. In JavaScript, such a model would look
something like Listing 3.

Listing 3. JavaScript model

You could contrast the example to classical modeling, where you might define a class
RunningBack that inherits from the class
FootballPlayer. LT and emmitt would be instances of
RunningBack. These classes might look like
Listing 4 in Java code.

The classical model comes with considerably more conceptual
overhead but
without the fine-grained control over class instances emmitt
and lt that you get with the prototype model. (To be fair,
the FootballPlayer class isn't
100% necessary; it's there for comparison with the next example.) At times,
this overhead
can be helpful, but often it's just baggage.

It's quite easy to emulate
classical modeling with a prototypal object system. (Admittedly, it's also possible to
do the reverse, though perhaps not easily.) For instance, you can create an object
footballPlayer with another runningBack
object that inherits from footballPlayer as its prototype.
In JavaScript these objects would look like Listing 5.

Listing 8. Creating objects

Because the lt object inherits from the emmitt object,
you can even treat the emmitt object as a class, as shown in Listing 9.

Listing 9. Inheritance and classes

emmitt.height = "6ft";
lt.height // => "6ft";

If you were to try the examples above in a language that features static, classical
objects (like Java code), you would have to use the decorator pattern, requiring yet more conceptual
overhead, and you still couldn't inherit directly from the emmitt object
as an instance. In contrast, the properties pattern used in prototype-based languages
like JavaScript let you decorate your objects in a much more liberated way.

JavaScript isn't the Java language

JavaScript and some of its features, such as prototypal objects, have been the victim of unfortunate historical blunders and marketing
decisions. For example, Brendan Eich (the
father of JavaScript) discussed in a blog entry why a new language was needed: "The
diktat from upper engineering management was that the language must
'look like Java.' That ruled out Perl, Python, and Tcl, along with Scheme." So,
JavaScript looks like Java code, and its name is linked to the Java lanuage, which is
confusing for anyone not familiar with either or both. Though JavaScript looks like
the
Java language on the surface, on a deeper level it is nothing like Java—leading to missed expectations.
From Brendan Eich:

I'm not proud, but I'm happy that I chose Scheme-ish first-class functions and Self-ish
(albeit singular) prototypes as the main ingredients. The Java influences, especially y2k Date
bugs but also the primitive vs. object distinction (e.g., string vs. String), were unfortunate.

Unmet expectations are tough to deal with. When you expect a static,
enterprise-y language like the Java language but end up with a language that has Java
code-like
syntax but behaves more like Scheme and Self you're justifiably surprised. If you like dynamic languages, this would be a welcomed surprise; if
you don't, or they're just unfamiliar to you, then programming in JavaScript might
be unpleasant.

JavaScript also has some genuine warts: forced global
variables, scoping issues, semicolon insertion, the inconsistent behavior of
==, and more. For these issues, JavaScript programmers have
developed an array of patterns and best practices to aid the development of
reliable software. The next section discusses a few patterns to use, and some to avoid, to make the best use of JavaScript's prototypal object system.

JavaScript object patterns

While trying to make JavaScript look like Java code, its designers included
constructor functions, which are necessary in classical languages
but usually unnecessary overhead in a prototypal language. Consider the pattern below,
where an object can be declared using a constructor function as shown in
Listing 10.

Listing 10. Declaring an object

function Point(x, y) {
this.x = x;
this.y = y;
}

You can then create the object using the new keyword,
similar to Java code, as shown in Listing 11.

Listing 11. Creating the object

var p = new Point(3, 4);
p.x // => 3
p.y // => 4

In JavaScript, functions are also objects, so methods can be added to the prototype
of the constructor function, as shown in Listing 12.

Although this is certainly a valid way of defining objects in JavaScript
(and at times it may be the best way),
it feels a bit clumsy. It adds unnecessary noise to your code compared to
embracing the prototypal pattern and defining objects purely in this style. To recap,
you define your object using an object literal, as shown in Listing 14.

Listing 15. Inherit using Object.create

This method of object creation feels natural in JavaScript and highlights the
advantages of its prototypal objects. One disadvantage of both the prototypal and
pseudoclassical patterns, however, is that they don't provide any member
privacy. Sometimes privacy doesn't matter and sometimes it does. Listing 16 shows a
pattern that lets you create objects with private members. In his book,
JavaScript: The Good Parts, Douglas Crockford calls this the
functional inheritance pattern.

Listing 17. Creating instances

Conclusion

This article just scratched the surface of prototypal OO programming. Many other languages, such as
Self, Lua, Io, and REBOL
implement the prototype pattern. The prototype pattern can be implemented in any
language, including statically typed languages. It is also useful when designing
any system where simplicity and flexibility are desired.

Prototypal OO programming provides
tremendous power and simplicity and fulfills the goals of OO programming
with great clarity and elegance. It is among JavaScript's assets, not its warts.

Resources

Learn

Brian Eich's
blog: Check out the Popularity blog for background information
about JavaScript.

Get products and technologies

Self programming language: Download Self, which includes a programming language, a collection of objects defined in the Self language, and a programming environment built in Self for writing Self programs.

The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.