About You

This book assumes that you've done at least a mild amount of web development with client-side technologies such as HTML, JavaScript, and CSS. You by no means, however, need to be an expert in any of these skills and you really don't need to know anything at all about what happens on a web server because Dojo is a client-side technology; merely having dabbled with them enough to know what they are and how they are used is more than enough.

If you are an existing web developer or even a hobbyist who is able to construct a very simple web page and apply a dab of JavaScript and CSS to liven it up a bit, then you should definitely keep reading. If you haven't even heard of HTML, JavaScript, or CSS, and have never done so much as written a line of code, then you might want to consider picking up a good introduction on web development as a supplement to this book.

Development Tools

With regard to development tools, although you could use your favorite text editor and any web browser to do some effective development with Dojo, this book makes frequent references to Firefox and the wonderful Firebug add-on that you can use to debug and deconstruct web pages as well as tinker around with JavaScript in its console. Although you could use Firebug Lite with another browser like Internet Explorer, the full version of Firebug is vastly superior and you won't be disappointed by it. (In general, a practice that's commonly accepted is to develop with Firefox using Firebug, but test frequently with IE.) You can get Firefox and Firebug from http://getfirefox.com and http://getfirebug.com, respectively.

Two other tools you may want to consider for Firefox are Chris Pederick's Web Developer Toolbar, available at http://chrispederick.com/work/web-developer/, which provides some additional tools that are useful during development, and the Clear Cache Button Firefox add-on, available at https://addons.mozilla.org/en-US/firefox/addon/1801, which is a button for your toolbar that you can use to quickly clear your cache. Occasionally, it can be the case that your browser may "act up" and serve you stale content; clearing the cache sometimes helps.

Essential Working Knowledge

Closures, context, and anonymous functions are some of the most important fundamental concepts in JavaScript, and because mastery of the toolkit involves more than a casual understanding of these topics, this section is worth a careful read. Even though it may sound like advanced material, these concepts are essential to mastering the JavaScript language and really understanding some of the underlying design within the toolkit. You could try and pick up this knowledge as you go along, but if you spend a little bit of time up front, you'll find that many selections from the ensuing chapters are considerably easier to understand.

Closures

A closure is essentially the coupling of data elements and the scope that contains (or encloses) that data. Although typical situations involving a single global scope that contains some functions are fairly straightforward, nested functions have the ability to really change things up. To illustrate, consider Example 1.

Example 1. Minimalist illustration of closures

function foo(  ) {
  var x = 10;
  return function bar(  ) {
    console.log(x);
  }
}

var x = 5;
var barReference = foo(  );
barReference(  ); //What gets printed? 10 or 5

Depending on your programming background, the previous code snippet might actually surprise you. As it turns out, the value 10 is printed to the screen because, in JavaScript, the entire scope chain is taken into account when evaluating a function. In this case, the scope chain that is returned is associated with bar, which is returned from evaluating foo. Thus, when barReference is evaluated, the value for x is looked up on the fly, and is tracked down in the body of foo. This is directly contrary to many programming languages, which would look up the context in the most immediate scope.

Tip

In JavaScript, functions are "first-class" objects that you can pass around, assign to variables, etc., and many of Dojo's design patterns leverage this characteristic heavily.

Although JavaScript closures are normally considered an advanced topic, the sooner you have a firm grasp on closures, the sooner you'll be on your way toward mastering the language and the better you'll understand many pieces of Dojo's design philosophy. In practical terms, that means you'll be more productive, able to track down tricky bugs a lot faster, and perhaps even become a more interesting person. (Well, two out of three isn't bad.) Consult David Flanagan's legendary JavaScript: The Definitive Guide (O'Reilly) for an excellent analysis of closures.

Context

JavaScript's extreme dynamism equips it with tremendous flexibility, and one of the most interesting yet least understood facets of its dynamism involves context. You probably already know that the default this context for browser-based JavaScript is the global window object. For example, the following statements should evaluate to true for virtually every browser implementation:

//the default context for a document is the window
console.log(window ==this); //true

//document is a shortcut for window.document
console.log(document == window.document); //true

With respect to Function objects, the keyword this is specifically used to refer to its immediate context. For example, you may have seen this used in a JavaScript Function object somewhat like the following:

function Dog(sound) {
    this.sound = sound;
}

Dog.prototype.talk = function(name) {
    console.log(this.sound + "," + this.sound + ". My name is", name);
}

dog = new Dog("woof");
dog.talk("fido"); //woof, woof. my name is fido

If you come from Java or a similar object-oriented background, the way that sound is looked up relative to the current object probably seems familiar enough. Nothing interesting is happening yet. However, matters can get more complicated if you bring in the built-in call function. Take a moment to study the following contrived example that introduces the call function at work:

function Dog(sound) {
    this.sound = sound;
}

Dog.prototype.talk = function(name) {
    console.log(this.sound + "," + this.sound + ". my name is", name);
}

dog = new Dog("woof");
dog.talk("fido"); //woof, woof. my name is fido

function Cat(sound) {
    this.sound = sound;
}

Cat.prototype.talk = function(name) {
    console.log(this.sound + "," + this.sound + ". my name is", name);
}

cat = new Cat("meow");
cat.talk("felix"); //meow, meow. my name is felix

cat.talk.call(dog, "felix") //woof, woof. my name is felix

Whoa! That last line did something pretty incredible. Through the cat object instance, it invoked the talk method that is bound to the cat prototype and passed in the name parameter to be used as usual; however, instead of using the sound that is bound to cat's this, it instead used the sound value that is bound to dog's this because dog was substituted in for the context.

It's well worth a few moments to tinker around with the call function to get more comfortable with it if it's new to you. In many less dynamic programming languages, the ability to redefine this would almost be ludicrous. As a potent language feature, however, JavaScript allows it, and toolkits like Dojo leverage this kind of inherent dynamism to do some amazing things. In fact, some of these amazing things are coming up in the next section.

Tip

Although the intent of this book isn't to provide exhaustive JavaScript language coverage that you could read about in JavaScript: The Definitive Guide, you may find it instructive to know that apply is a function that works just like call except that instead of accepting an unspecified number of parameters to be passed into the target function, it accepts only two parameters, the latter parameter being an Array, which can contain an unsaid number of values that become the built-in arguments value for the target function. Essentially, you'll choose the one most convenient for you.

Anonymous functions

In JavaScript, Function objects may be passed around just like any other type. Although using anonymous functions inline can definitely provide some syntactic sugar that reduces the clutter and makes code more maintainable, a perhaps more significant feature of anonymous functions is that they provide a closure that protects the immediate context.

For example, what does the following block of code do?

//Variable i is undefined.

for (var i=0; i < 10; i++) {
    //do some stuff with i
}
console.log(i); // ???

If you thought that the console statement prints out undefined, then you are sorely mistaken. A subtle but important characteristic of JavaScript is that it does not support the concept of blocked scope outside of functions, and for this reason, the values of i and any other "temporary" variables defined during iteration, conditional logic, etc., live on long after the block executes.

If it's ever prudent to explicitly provide blocked scope, you could wrap the block inside of a Function object and execute it inline. Consider the following revision:

(function(  ) {
  for (var i=0; i < 10; i++) {
    //do some stuff with i
  }
})(  )
console.log(i); // undefined

Although the syntax is somewhat clumsy, keeping it clear of artifacts can sometimes prevent nasty bugs from sneaking up on you. Many Base language functions introduced in the following chapters provide closure (in addition to syntactic sugar and utility) to the code block being executed.

Get Dojo: The Definitive Guide 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.