Blog


Simple JavaScript Inheritance

I've been doing a lot of work, lately, with JavaScript inheritance - namely for my work-in-progress JavaScript book - and in doing so have examined a number of different JavaScript classical-inheritance-simulating techniques. Out of all the ones that I've looked at I think my favorites were the implementations employed by base2 and Prototype.

I wanted to go about extracting the soul of these techniques into a simple, re-usable, form that could be easily understood and didn't have any dependencies. Additionally I wanted the result to be simple and highly usable. Here's an example of what you can do with it:

var Person = Class.extend({
  init: function(isDancing){
    this.dancing = isDancing;
  },
  dance: function(){
    return this.dancing;
  }
});

var Ninja = Person.extend({
  init: function(){
    this._super( false );
  },
  dance: function(){
    // Call the inherited version of dance()
    return this._super();
  },
  swingSword: function(){
    return true;
  }
});

var p = new Person(true);
p.dance(); // => true

var n = new Ninja();
n.dance(); // => false
n.swingSword(); // => true

// Should all be true
p instanceof Person && p instanceof Class &&
n instanceof Ninja && n instanceof Person && n instanceof Class

A couple things to note about this implementation:

  • Creating a constructor had to be simple (in this case simply providing an init method does the trick).
  • In order to create a new 'class' you must extend (sub-class) an existing class.
  • All of the 'classes' inherit from a single ancestor: Class. Therefore if you want to create a brand new class it must be a sub-class of Class.
  • And the most challenging one: Access to overridden methods had to be provided (with their context properly set). You can see this with the use of this._super(), above, calling the original init() and dance() methods of the Person super-class.

I'm pleased with the result: It helps to enforce the notion of 'classes' as a structure, maintains simple inheritance, and allows for the super method calling.

Simple Class Creation and Inheritance

And here's the implementation (reasonably sized and commented well) - clocking in at around 25 lines. Feedback is welcome and appreciated.

/* Simple JavaScript Inheritance
 * By John Resig http://ejohn.org/
 * MIT Licensed.
 */

// Inspired by base2 and Prototype
(function(){
  var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

  // The base Class implementation (does nothing)
  this.Class = function(){};
 
  // Create a new Class that inherits from this class
  Class.extend = function(prop) {
    var _super = this.prototype;
   
    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;
   
    // Copy the properties over onto the new prototype
    for (var name in prop) {
      // Check if we're overwriting an existing function
      prototype[name] = typeof prop[name] == "function" &&
        typeof _super[name] == "function" && fnTest.test(prop[name]) ?
        (function(name, fn){
          return function() {
            var tmp = this._super;
           
            // Add a new ._super() method that is the same method
            // but on the super-class
            this._super = _super[name];
           
            // The method only need to be bound temporarily, so we
            // remove it when we're done executing
            var ret = fn.apply(this, arguments);       
            this._super = tmp;
           
            return ret;
          };
        })(name, prop[name]) :
        prop[name];
    }
   
    // The dummy class constructor
    function Class() {
      // All construction is actually done in the init method
      if ( !initializing && this.init )
        this.init.apply(this, arguments);
    }
   
    // Populate our constructed prototype object
    Class.prototype = prototype;
   
    // Enforce the constructor to be what we expect
    Class.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;
   
    return Class;
  };
})();

In my opinion the two trickiest parts are the "initializing/don't call init" and "create _super method" portions. I want to cover those briefly so that you will have a good understanding of what's being achieved in this method.

Initialization

In order to simulate inheritance with a function prototype we use the traditional technique of creating an instance of the super-class function and assigning it to the prototype. Without using the above it would look something like this:

function Person(){}
function Ninja(){}
Ninja.prototype = new Person();
// Allows for instanceof to work:
(new Ninja()) instanceof Person

What's challenging about this, though, is that all we really want is the benefits of 'instanceof', not the whole cost of instantiating a Person object and running its constructor. To counteract this we have a variable in our code, initializing, that is set to true whenever we want to instantiate a class with the sole purpose of using it for a prototype.

Thus when it comes time to actually construct the function we make sure that we're not in an initialization mode and run the init method accordingly:

if ( !initializing )
  this.init.apply(this, arguments);

What's especially important about this is that the init method could be running all sorts of costly startup code (connecting to a server, creating DOM elements, who knows) so circumventing this ends up working quite well.

Super Method

When you're doing inheritance, creating a class that inherits functionality from a super-class, a frequent desire is the ability to access a method that you've overridden. The final result, in this particular implementation, is a new temporary method (._super) which is only accessible from within a sub-classes' method, referencing the super-classes' associated method.

For example, if you wanted to call a super-classes' constructor you could do that with this technique.

var Person = Class.extend({
  init: function(isDancing){
    this.dancing = isDancing;
  }
});

var Ninja = Person.extend({
  init: function(){
          this._super( false );
  }
});

var p = new Person(true);
p.dancing; // => true

var n = new Ninja();
n.dancing; // => false
 

Implementing this functionality is a multi-step process. To start, note the object literal that we're using to extend an existing class (such as the one being passed in to Person.extend) needs to be merged on to the base new Person instance (the construction of which was described previously). During this merge we do a simple check: Is the property that we're attempting merge a function and is what we're replacing also a function? If that's the case then we need to go about creating a way for our super method to work.

Note that we create an anonymous closure (which returns a function) that will encapsulate the new super-enhanced method. To start we need to be a good citizen and save a reference to the old this._super (disregarding if it actually exists) and restore it after we're done. This will help for the case where a variable with the same name already exists (don't want to accidentally blow it away).

Next we create the new _super method, which is just a reference to the method that exists on the super-class' prototype. Thankfully we don't have to make any additional changes, or re-scoping, here as the context of the function will be set automatically when it's a property of our object (this will refer to our instance as opposed to the super-class').

Finally we call our original method, it does its work (possibly making use of _super as well) after which we restore _super to its original state and return from the function.

Now there's a number of ways in which a similar result, to the above, could be achieved (I've seen implementations that have bound the super method to the method itself, accessible from arguments.callee) but I feel that this technique provides the best mix of usability and simplicity.

I'll be covering a lot more of the nitty-gritty behind the JavaScript prototype system in my completed work but I just wanted to get this Class implementation out there to get everyone trying it out and playing with it. I think there's a lot to be said for simplistic code (easier to learn, easier to extend, less to download) so I think this implementation is a good place to start and learn the fundamentals of JavaScript class construction and inheritance.


This topic will be discussed, in depth, in my work-in-progress book: Secrets of the JavaScript Ninja. To be released Fall 2008.

Tags: secrets, javascript, book

Search and Don't Replace

Earlier today a friend of mine, Marc Grabanski, pinged me with a question: What's the optimal way, in JavaScript, to convert a query string like "foo=1&foo=2&foo=3&blah=a&blah=b" into one that looks like this: "foo=1,2,3&blah=a,b". He had already come up with a solution of his own and was curious as to if it could be improved upon.

I pondered this for a moment and came up with a solution:

function compress(data){
    var q = {}, ret = "";
    data.replace(/([^=&]+)=([^&]*)/g, function(m, key, value){
        q[key] = (q[key] ? q[key] + "," : "") + value;
    });
    for ( var key in q )
        ret = (ret ? ret + "&" : "") + key + "=" + q[key];
    return ret;
}

Besides being 10 lines shorter than Mark's solution it also didn't require the use of any libraries (his required the use of jQuery). He was especially surprised at my result - and the replace technique that I used, in particular. I want to outline two quick tricks that I used that some may not be familiar with.

Array Joining Without an Array

One step to solving the above problem is to collect together the various values associated with a key - joining them with a ','. At first glance the obvious solution might be to construct an array for each key, push each of the values on, and then .join() the array results into a string. However all of this is both costly (the overhead of creating all these extra arrays) and verbose.

The alternative is one that I use twice in the program:

q[key] = (q[key] ? q[key] + "," : "") + value;

The key part is that we're concatenating the value onto the q[key] string adding in an extra "," if there's nothing in the string already: q[key] ? q[key] + "," : "". If no existing value is in the key we seed it with an empty string, otherwise we're simply merging on to the already-existing value along with the needed ",".

The end result is that we're only ever dealing with strings and string operations (instead of arrays) but achieving the result of joining a set of values without using an array.

Search and Replace Without Replacing

The second, and arguably more interesting, aspect is in using the JavaScript string replace function as a means of traversing a string for values, rather than as an actual search-and-replace mechanism. The trick is two-fold: Passing in a function as the replace value argument to the .replace() method and, instead of returning a value, simply utilizing it as a means of searching.

Let's examine this piece of code:

data.replace(/([^=&]+)=([^&]*)/g, function(m, key, value){});

The regular expression, itself, captures two things: A key in the query string and its associated value. This match is performed globally, locating all the key-value pairs within the query string.

The second argument to the replace method is a function. It's not uncommon to utilize this function-as-an-argument technique when attempting to replace matches with complex values (that is values that are dependent upon their associated matches). The function is called every time a new match occurs and it receives a variable number of arguments. The first argument is always the entire matched portion of the string and all remaining arguments are each of the (...) capturing blocks, in order. The return value of the function is injected back into the string as its replacement. In this example we don't return a value from the function therefore we end up injecting the serialized "undefined" value, repeatedly, back into the string.

We can see this behavior here:

"a b c".replace(/a/, function(){});
// => "undefined b c"
 

Now that we've collected all of our key values pairs (to be re-serialized back into a query string) the final step isn't really a step at all: We simply don't save the search-and-replaced data query string (which, most likely, looks something like "undefined&undefined&undefined").

In this manner we can use a string's replace method as our very-own string searching mechanism. The result is, not only, fast but also simple and effective. Another excellent tool in your JavaScript toolbox.


This topic will be discussed, in depth, in my work-in-progress book: Secrets of the JavaScript Ninja. To be released Fall 2008.

Tags: javascript, book, secrets

State of the Secrets

I've alluded to it a couple times now but it's probably important to state it definitively: I'm writing a new JavaScript book, to be published by Manning Publishing, called Secrets of the JavaScript Ninja. I published the rough Table of Contents previously and the contents of the book will be staying virtually the same (with a couple minor additions).

I wanted to take this opportunity to give a sort of progress update - letting you know what's happening. Not enough is said about the process of writing a book (especially technical ones) so I wanted to try and fill in some of the gaps.

Dec 28th: I first decided that I wanted to write a new JavaScript book around the end of last year. While it wasn't, explicitly, a new year's resolution - the timing was rather nice.

Dec 28-30th: I then set about collecting some information, trying to decide if the subject matter was worthwhile:

Jan 9th: I decided that I had enough information on hand to warrant a full book on the subject matter (namely advanced JavaScript techniques and cross-browser scripting). I started work on congealing this into a full outline/table of contents.

It was around this time that I started work on my first (non-introductory) chapter: Functions.

Jan 21st: It was around this time that I started talking with various publishers. Luckily I've been able to accrue a number of contacts in the technical publishing industry, over the past couple years, so I already had some starting points and good references. I also received a few contacts after my post on the profits of my previous book.

Jan 25th: I made the decision to go with Manning Publishing as the publisher of my book. I had the opportunity to have a number of long phone calls with Marjan (the head of Manning) and he had some fantastic ideas for the book and its direction. Hearing his ideas and excitement was a huge reason for me to go with them but in the end there were a number of reasons for choosing them:

  • They were very open to trying new techniques with the book - everything from how it was to be published, what the contents were, to even how the writing process worked.
  • When we originally started talks we were looking at the idea of having the book be similar, in style, to other books like Why's Poignant Guide to Ruby. We discussed this, at length, for quite some time. After a few weeks of mulling it over I decided that this wasn't the best course-of-action for this book. The mixture of complex material and narrative would not work well, I felt.
  • However, we agreed to include a heavier use of illustrations and figures to communicate difficult topics (such as timers or closures). We'll have to see how this works out, but that's the current plan.
  • The book will have a companion web site which will be open to those that have purchased a copy of the book. It will behave very similarly to the Django Book, in that you'll be able to comment on any portion of the text - becoming part of the editing and review process.
  • I'll be able to write the book using DocBook, which is a huge win over the old pass-Word-documents-around strategy that a lot of publishers use. Many technical publishers are getting better here - I definitely wouldn't want to go with one who didn't support this, or a similar, strategy.
  • They have a good level of distribution and their books are widely available in book stores.
  • We were able to negotiate a good level of compensation heavily tied to the sale of books, which made me happy.

Feb 3rd: Chapter 2 was completed and submitted on time. I now have an absolute schedule to work against. One chapter every 10 days until the end of August. It's pretty grueling (as is to be expected with book writing) but I'm optimistic. I started with Chapter 2 so that I could get a feel for how an actual chapter would be written (I dislike writing non-code chapters).

Feb. 17th: Chapter 3 (Closures) completed. I also released a portion of this chapter as a blog post: Partially Applying Functions in JavaScript. I fell behind with this chapter because I was traveling to Mountain View, for Mozilla work, during this period. I suspect that this will happen frequently throughout the summer as I'll be traveling a lot more.

Around this time I was assigned an editor for my book, Tom Cirtin. I look forward to working with him more - I'll certainly have plenty of opportunity for that.

Feb. 24th: Chapter 4 (Timers) completed. I'm virtually caught up at this point. However I have to jump back now and finish Chapter 1 (the introductory chapter) before moving on. I released one portion of this chapter as a blog post: How JavaScript Timers Work.

There's a lot that I'm doing differently from my first book and it's already making for a saner experience:

For starters this book is highly specialized, it picks one topic and covers it completely (there's a chapter on closures, on timers, on eval, on with - to name a few). I enjoy giving high-class treatment to obscure topics. Knowing that someone will be able to pick up this book and absolutely see something that they've (probably) never seen before makes for a very invigorating writing experience.

Another thing that I learned from my first book was that I really dislike long chapters. To counter this the book is broken up into 21 "small" 10-12 page chapters. I love it, it's the perfect chapter length, for me. I rarely find that I have more to say on a subject after about 4000 words (which is what 10-12 pages works out to be). With my old book I constantly felt like I had to flush out topics in order to meet page quotas, not so here. This causes me to become much more relaxed, knowing that whatever result I end up with it'll be an ideal length.

While I wouldn't call this book a 'cookbook' it's certainly not a traditional-style technical book. I'd say that it's something of a hybrid between the two. The chapters, thus far, have a structure like: In-depth explanation of topic, simple use of topic, specialized use of topic #1 through #3. For example in the chapter on Timers I dive in to how timers work, look at the minimum timer delays and reliability, explore computationally-expensive processing, build a centralized timer control, and finish up with a look at an asynchronous test suite.

While I don't have a final date for when the book site will be ready (or when the book will be available for pre-order) you can be sure that I'll blog about it here, when that's the case (be sure to subscribe to my blog, if you haven't done so already, to receive more updates).

In short: I'm really excited about this book. Progress is going well, the publisher is friendly, the topics are ideal, and the content is coming out great.

Tags: javascript, book, secrets

How JavaScript Timers Work

At a fundamental level it's important to understand how JavaScript timers work. Often times they behave unintuitively because of the single thread which they are in. Let's start by examining the three functions to which we have access that can construct and manipulate timers.

  • var id = setTimeout(fn, delay); - Initiates a single timer which will call the specified function after the delay. The function returns a unique ID with which the timer can be canceled at a later time.
  • var id = setInterval(fn, delay); - Similar to setTimeout but continually calls the function (with a delay every time) until it is canceled.
  • clearInterval(id);, clearTimeout(id); - Accepts a timer ID (returned by either of the aforementioned functions) and stops the timer callback from occurring.

In order to understand how the timers work internally there's one important concept that needs to be explored: timer delay is not guaranteed. Since all JavaScript in a browser executes on a single thread asynchronous events (such as mouse clicks and timers) are only run when there's been an opening in the execution. This is best demonstrated with a diagram, like in the following:


(Click to view full size diagram)

There's a lot of information in this figure to digest but understanding it completely will give you a better realization of how asynchronous JavaScript execution works. This diagram is one dimensional: vertically we have the (wall clock) time, in milliseconds. The blue boxes represent portions of JavaScript being executed. For example the first block of JavaScript executes for approximately 18ms, the mouse click block for approximately 11ms, and so on.

Since JavaScript can only ever execute one piece of code at a time (due to its single-threaded nature) each of these blocks of code are "blocking" the progress of other asynchronous events. This means that when an asynchronous event occurs (like a mouse click, a timer firing, or an XMLHttpRequest completing) it gets queued up to be executed later (how this queueing actually occurs surely varies from browser-to-browser, so consider this to be a simplification).

To start with, within the first block of JavaScript, two timers are initiated: a 10ms setTimeout and a 10ms setInterval. Due to where and when the timer was started it actually fires before we actually complete the first block of code. Note, however, that it does not execute immediately (it is incapable of doing that, because of the threading). Instead that delayed function is queued in order to be executed at the next available moment.

Additionally, within this first JavaScript block we see a mouse click occur. The JavaScript callbacks associated with this asynchronous event (we never know when a user may perform an action, thus it's consider to be asynchronous) are unable to be executed immediately thus, like the initial timer, it is queued to be executed later.

After the initial block of JavaScript finishes executing the browser immediately asks the question: What is waiting to be executed? In this case both a mouse click handler and a timer callback are waiting. The browser then picks one (the mouse click callback) and executes it immediately. The timer will wait until the next possible time, in order to execute.

Note that while mouse click handler is executing the first interval callback executes. As with the timer its handler is queued for later execution. However, note that when the interval is fired again (when the timer handler is executing) this time that handler execution is dropped. If you were to queue up all interval callbacks when a large block of code is executing the result would be a bunch of intervals executing with no delay between them, upon completion. Instead browsers tend to simply wait until no more interval handlers are queued (for the interval in question) before queuing more.

We can, in fact, see that this is the case when a third interval callback fires while the interval, itself, is executing. This shows us an important fact: Intervals don't care about what is currently executing, they will queue indiscriminately, even if it means that the time between callbacks will be sacrificed.

Finally, after the second interval callback is finished executing, we can see that there's nothing left for the JavaScript engine to execute. This means that the browser now waits for a new asynchronous event to occur. We get this at the 50ms mark when the interval fires again. This time, however, there is nothing blocking its execution, so it fires immediately.

Let's take a look at an example to better illustrate the differences between setTimeout and setInterval.

  setTimeout(function(){
    /* Some long block of code... */
    setTimeout(arguments.callee, 10);
  }, 10);
 
  setInterval(function(){
    /* Some long block of code... */
  }, 10);

These two pieces of code may appear to be functionally equivalent, at first glance, but they are not. Notably the setTimeout code will always have at least a 10ms delay after the previous callback execution (it may end up being more, but never less) whereas the setInterval will attempt to execute a callback every 10ms regardless of when the last callback was executed.

There's a lot that we've learned here, let's recap:

  • JavaScript engines only have a single thread, forcing asynchronous events to queue waiting for execution.
  • setTimeout and setInterval are fundamentally different in how they execute asynchronous code.
  • If a timer is blocked from immediately executing it will be delayed until the next possible point of execution (which will be longer than the desired delay).
  • Intervals may execute back-to-back with no delay if they take long enough to execute (longer than the specified delay).

All of this is incredibly important knowledge to build off of. Knowing how a JavaScript engine works, especially with the large number of asynchronous events that typically occur, makes for a great foundation when building an advanced piece of application code.


This is an excerpt from my work-in-progress book: Secrets of the JavaScript Ninja. To be released Fall 2008.

Previous excerpt: Partial Function Application in JavaScript

Tags: book, javascript, secrets

JavaScript Books

Secrets of the JavaScript Ninja

JavaScript Secrets

Secret techniques of top JavaScript programmers.

Pro JavaScript Techniques

Pro JavaScript

The best techniques for professional JavaScript. Published by Apress.

Micro Updates

John Resig Twitter Updates

@jeresig

Infrequent, short, updates and links.

JavaScript Jobs



Hosting provided by: Ruby Hosting by Engine Yard