Chapter 1. Introduction

JavaScript is the language of the Web. It started as a way to manipulate a few selected types of elements in a web page (such as images and form fields), but it has grown tremendously. In addition to client-side browser scripting, these days you can use JavaScript to program for an increasing variety of platforms. You can write server-side code (using .NET or Node.js), desktop applications (that work on all operating systems) and application extensions (e.g., for Firefox or Photoshop), mobile applications, and command-line scripts.

JavaScript is also an unusual language. It doesn’t have classes, and functions are first-class objects used for many tasks. Initially the language was considered deficient by many developers, but in more recent years these sentiments have changed. Interestingly, languages such as Java and PHP started adding features such as closures and anonymous functions, which JavaScript developers have been enjoying and taking for granted for a while.

JavaScript is dynamic enough that you can make it look and feel like another language you’re already comfortable with. But the better approach is to embrace its differences and study its specific patterns.

Patterns

A pattern in the broader sense of the word is a “theme of recurring events or objects…it can be a template or model which can be used to generate things” (http://en.wikipedia.org/wiki/Pattern).

In software development, a pattern is a solution to a common problem. A pattern is not necessarily a code solution ready for copy-and-paste but more of a best practice, a useful abstraction, and a template for solving categories of problems.

It is important to identify patterns because:

  • They help us write better code using proven practices and not reinvent the wheel.

  • They provide a level of abstraction—the brain can hold only so much at a given time, so when you think about a more complex problem, it helps if you don’t bother with the low-level details but account for them with self-contained building blocks (patterns).

  • They improve communication between developers and teams, which are often in remote locations and don’t communicate face to face. Simply putting a label on some coding technique or approach makes it easier to make sure we’re talking about the same thing. For example, it’s easier to say (and think) “immediate function,” than “this thing where you wrap the function in parentheses and at the end of it put another set of parentheses to invoke the function right where you’ve defined it.”

This book discusses the following types of patterns:

  • Design patterns

  • Coding patterns

  • Antipatterns

Design patterns are those initially defined by the “Gang of Four” book (named so after its four authors), originally published in distant 1994 under the title Design Patterns: Elements of Reusable Object-Oriented Software. Examples of design patterns are singleton, factory, decorator, observer, and so on. The thing about design patterns in relation to JavaScript is that, although language-independent, the design patterns were mostly studied from the perspective of strongly typed languages, such as C++ and Java. Sometimes it doesn’t necessarily make sense to apply them verbatim in a loosely typed dynamic language such as JavaScript. Sometimes these patterns are workarounds that deal with the strongly typed nature of the languages and the class-based inheritance. In JavaScript there might be simpler alternatives. This book discusses JavaScript implementations of several design patterns in Chapter 7.

The coding patterns are much more interesting; they are JavaScript-specific patterns and good practices related to the unique features of the language, such as the various uses of functions. JavaScript coding patterns are the main topic of the book.

You might come across an occasional antipattern in the book. Antipatterns have a bit of negative or even insulting sound to their name, but that needn’t be the case. An antipattern is not the same as a bug or a coding error; it’s just a common approach that causes more problems than it solves. Antipatterns are clearly marked with a comment in the code.

JavaScript: Concepts

Let’s quickly go over a few important concepts that provide a context for the following chapters.

Object-Oriented

JavaScript is an object-oriented language, which often surprises developers who have previously looked at the language and dismissed it. Anything you look at in a piece of JavaScript code has a good chance of being an object. Only five primitive types are not objects: number, string, boolean, null, and undefined, and the first three have corresponding object representation in the form of primitive wrappers (discussed in the next chapter). Number, string, and boolean primitive values are easily converted to objects either by the programmer or sometimes behind the scenes by the JavaScript interpreter.

Functions are objects, too. They can have properties and methods.

The simplest thing you do in any language is define a variable. Well, in JavaScript when you define a variable, you’re already dealing with objects. First, the variable automatically becomes a property of an internal object known as an Activation Object (or a property of the global object if it’s a global variable). Second, this variable is actually also object-like because it has its own properties (called attributes), which determine whether the variable can be changed, deleted, or enumerated in a for-in loop. These attributes are not directly exposed in ECMAScript 3, but edition 5 offers special descriptor methods for manipulating them.

So what are the objects? Because they do so many things they must be quite special. Actually they are extremely simple. An object is just a collection of named properties, a list of key-value pairs (almost identical to an associative array in other languages). Some of the properties could be functions (function objects), in which case we call them methods.

Another thing about the objects you create is that you can modify them at any time. (Although ECMAScript 5 introduces APIs to prevent mutations.) You can take an object and add, remove, and update its members. If you’re concerned about privacy and access, we’ll see patterns for this as well.

And one last thing to keep in mind is that there are two main types of objects:

Native

Described in the ECMAScript standard

Host

Defined by the host environment (for example, the browser environment)

The native objects can further be categorized as built-in (for example, Array, Date) or user-defined (var o = {};).

Host objects are, for example, window and all the DOM objects. If you’re wondering whether you’re using host objects, try running your code in a different, nonbrowser environment. If it works fine, you’re probably using only native objects.

No Classes

You’ll see this statement repeated on several occasions throughout the book: There are no classes in JavaScript. This is a novel concept to seasoned programmers in other languages and it takes more than a few repetitions and more than a little effort to “unlearn” classes and accept that JavaScript deals only with objects.

Not having classes makes your programs shorter—you don’t need to have a class to create an object. Consider this Java-like object creation:

// Java object creation
HelloOO hello_oo = new HelloOO();

Repeating the same thing three times looks like an overhead when it comes to creating simple objects. And more often than not, we want to keep our objects simple.

In JavaScript you create a blank object when you need one and then start adding interesting members to it. You compose objects by adding primitives, functions, or other objects to them as their properties. A “blank” object is not entirely blank; it comes with a few built-in properties already but has no “own” properties. We talk about this more in the next chapter.

One of the general rules in the Gang of Four book says, “Prefer object composition to class inheritance.” This means that if you can create objects out of available pieces you have lying around, this is a much better approach than creating long parent-child inheritance chains and classifications. In JavaScript it’s easy to follow this advice—simply because there are no classes and object composition is what you do anyway.

Prototypes

JavaScript does have inheritance, although this is just one way to reuse code. (And there’s an entire chapter on code reuse.) Inheritance can be accomplished in various ways, which usually make use of prototypes. A prototype is an object (no surprises) and every function you create automatically gets a prototype property that points to a new blank object. This object is almost identical to an object created with an object literal or Object() constructor, except that its constructor property points to the function you create and not to the built-in Object(). You can add members to this blank object and later have other objects inherit from this object and use its properties as their own.

We’ll discuss inheritance in detail, but for now just keep in mind that the prototype is an object (not a class or anything special) and every function has a prototype property.

Environment

JavaScript programs need an environment to run. The natural habitat for a JavaScript program is the browser, but that’s not the only environment. The patterns in the book are mostly related to the core JavaScript (ECMAScript) so they are environment-agnostic. Exceptions are:

  • Chapter 8, which specifically deals with browser patterns

  • Some other examples that illustrate practical applications of a pattern

Environments can provide their own host objects, which are not defined in the ECMAScript standard and may have unspecified and unexpected behavior.

ECMAScript 5

The core JavaScript programming language (excluding DOM, BOM, and extra host objects) is based on the ECMAScript standard, or ES for short. Version 3 of the standard was accepted officially in 1999 and is the one currently implemented across browsers. Version 4 was abandoned and version 5 was approved December 2009, 10 years after the previous.

Version 5 adds some new built-in objects, methods, and properties to the language, but its most important addition is the so-called strict mode, which actually removes features from the language, making the programs simpler and less error-prone. For example the usage of the with statement has been disputed over the years. Now in ES5 strict mode it raises an error, although it’s okay if found in nonstrict mode. The strict mode is triggered by an ordinary string, which older implementations of the language simply ignore. This means that the usage of strict mode is backward compatible, because it won’t raise errors in older browsers that don’t understand it.

Once per scope (either function scope, global scope, or at the beginning of a string passed to eval()), you can use the following string:

function my() {
    "use strict";
    // rest of the function...
}

This means the code in the function is executed in the strict subset of the language. For older browsers this is just a string not assigned to any variable, so it’s not used, and yet it’s not an error.

The plan for the language is that in the future strict mode will be the only one allowed. In this sense ES5 is a transitional version—developers are encouraged, but not forced, to write code that works in strict mode.

The book doesn’t explore patterns related to ES5’s specific additions, because at the time of this writing there’s no browser that implements ES5. But the examples in this book promote a transition to the new standard by:

  • Ensuring the offered code samples will not raise errors in strict mode

  • Avoiding and pointing out deprecated constructs such as arguments.callee

  • Calling out ES3 patterns that have ES5 built-in equivalents such as Object.create()

JSLint

JavaScript is an interpreted language with no static compile-time checks. So it’s possible to deploy a broken program with a simple typing mistake without realizing it. This is where JSLint helps.

JSLint (http://jslint.com) is a JavaScript code quality tool created by Douglas Crockford that inspects your code and warns about potential problems. It’s highly recommended that you run your code through JSLint. The tool “will hurt your feelings” as its creator warns, but only in the beginning. You can quickly learn from your mistakes and adopt the essential habits of a professional JavaScript programmer. Having no JSLint error in your code also helps you be more confident in the code, knowing that you didn’t make a simple omission or syntax error in a hurry.

Starting with the next chapter, you’ll see JSLint mentioned a lot. All the code in the book successfully passes JSLint’s check (with the default settings, current at the time of writing) except for a few occasions clearly marked as antipatterns.

In its default settings, JSLint expects your code to be strict mode–compliant.

The Console

The console object is used throughout the book. This object is not part of the language but part of the environment and is present in most current browsers. In Firefox, for example, it comes with the Firebug extension. The Firebug console has a UI that enables you to quickly type and test little pieces of JavaScript code and also play with the currently loaded page (see Figure 1-1). It’s also highly recommended as a learning and exploratory tool. Similar functionality is available in WebKit browsers (Safari and Chrome) as part of the Web Inspector and in IE starting with version 8 as part of Developer Tools.

Most code examples in the book use the console object instead of prompting alert()s or updating the current page, because it’s an easy and unobtrusive way to print some output.

We often use the method log(), which prints all the parameters passed to it, and sometimes dir(), which enumerates the object passed to it and prints all properties. Here’s an example usage:

console.log("test", 1, {}, [1,2,3]);
console.dir({one: 1, two: {three: 3}});
Using the Firebug console

Figure 1-1. Using the Firebug console

When you type in the console, you don’t have to use console.log(); you can simply omit it. To avoid clutter, some code snippets skip it, too, and assume you’re testing the code in the console:

window.name === window['name']; // true

This is as if we used the following:

console.log(window.name === window['name']);

and it printed true in the console.

Get JavaScript Patterns now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.