Constructor naming convention

September 14th, 2009

Constructors are just functions, it all depends on how they are invoked - with or without new.

So a naming pattern is pretty useful to help you visually distinguish between the two. It gives you a clue that the uppercase functions are meant to be called with new.

MyConstructor
myFunction

Constructors

September 14th, 2009

A simple way to create objects in JavaScript is using object literal notation. An other way, a bit more involved is to use a constructor function.

var adam = new Person("Adam");
adam.say(); // "I am Adam"

The invocation of the constructor looks a bit like a class in other languages, but the constructor is still just a function. (JavaScript doesn’t have classes). So the constructor is the blueprint, the recipe for the object.

And here's how the constructor Person is defined, it adds all members to the this object.

var Person = function(name) {
 
  this.name = name;
  this.say = function() {
    return "I am " + this.name;
  };
 
};

When you define a constructor, something like the following happens behind the scenes. It's as if you defined an object using the literal notation and then returned it.

var Person = function(name) {
  // var this = {};
  this.name = name;
  this.say = function() {
    returnI am ” + this.name;
  };
  // return this;
};

Singleton

September 14th, 2009

According to Wikipedia:

...the singleton pattern is a design pattern that is used to restrict instantiation of a class to one object.

How does this apply to JavaScript? Well, in JavaScript there are no classes, just objects. So when you create a new object, there's no other object like it and the new object is already a singleton.

var obj = {
  myprop: 'my value'
};

This is an example of creating a simple object in JavaScript using the object literal and it's also an example of a singleton.

Using new

The other question is how about if you want to use the Java-like syntax:

var obj = new Constructor();

This is more of classic-like syntax so the idea of a singleton here is that when you use new to create several objects using the same constructor, you should only get one object.

var obj = new Constructor();
var obj2 = new Constructor();
alert(obj === obj2); // true

obj is created only the first time the constructor is called, the second time (and the third, fourth, etc) the obj created the first time is returned. How to achieve this in JavaScript?

Basically you need your Constructor to cache the object instance this once it's created and then pull this instance the second time it's called. You can cache the object instance:

  • in a global variable - not recommended, general principle is that globals are bad, plus anyone can overwrite this global, even by accident;
  • in a Constructor property - functions in JavaScript are objects, so they can have properties. You can have something like Constructor.instance and cache the object there. This is a nice clean solution with the only drawback that this property is accessible and code outside of yours might change it, so you lose the instance;
  • wrap the instance in a closure

Let's take a look at an example implementation of the last option.

function Constructor() {
  return Constructor.getInstance(this);
}
Constructor.getInstance = function(){
  var instance;
  return function(that) {
    if (typeof instance === 'undefined') {
      instance = that;
    }
    return instance;
  }
}();

And a simpler new

Here's another way to do the class-like singleton. Secret sauce: using a closure to keep the reference to the single object and then rewrite the constructor.

function Single() {
 
  var instance = this; 
 
  // add more to this…
 
  Single = function (){
    return instance;  
  };
}
 
// test
var my1 = new Single();
var my2 = new Single();
alert(my1 === my2) //true

Init-time branching

September 14th, 2009

Probably virtually every web developer has done something like this at one point or another:

function myEvent(el, type, fn) {
  if (window.addEventListener) {
    el.addEventListener(type, fn, false);
  } else if (window.attachEvent) {
    el.attachEvent("on" + type, fn);
  }
}

This is absolutely normal, browsers are different, we have to take this fact into account and branch our code. One way to improve similar bits of code is by branching only once, when the function/method is defined as opposed to every time it's called. Like this:

if (window.addEventListener) {
  var myEvent = function (el, type, fn) {
    el.addEventListener(type, fn, false);
  }
} else if (window.attachEvent) {
  var myEvent = function (el, type, fn) {
    el.attachEvent("on" + type, fn);
  }
}

This way you get browser-dependent myEvent() function and there's no branching every time the function is called. While this may sound unnecessary, it could have an impact when a function is called many times in performance-critical situations, such as during drag-n-drop.

In a drag-drop case, it's likely that you need to get the current (computed) style of an element and also set it. Getting the computed style is different in browsers and is an ideal candidate for load-time branching. This is how it's done in the YUI DOM utility (source code), where this pattern was actually isolated from.

The DOM utility does more stuff, but the purpose of simply demonstrating the pattern you can say that it does something like:

// load-time branching
if (document.defaultView && document.defaultView.getComputedStyle) {
  var getStyle = function(el, property) {
    return document.defaultView.getComputedStyle(el, '')[property];
  }
} else if (document.documentElement.currentStyle) {
  var getStyle = function(el, property) {
    return el.currentStyle[property];
  }
}
 
// usage
var style = getStyle($('something'), 'fontWeight');

Another benefit of load-time branching is that you can branch only once and define multiple functions. For example if you've detected that the browser supports window.addEventListener it's very likely that it will support window.removeEventListener as well and not window.removeEvent. This should be approached carefully though, so that you keep in mind to branch based on object/feature detection and not on browser detection. For example don't be tempted to define getStyle() based on detection for window.addEventListener, although it will most likely work.

Using literals

September 14th, 2009

Array literals

In JavaScript you can define an array like this:

var a = new Array();

A better pattern to do so is by using the array literal, basically a comma-delimited list of values, wrapped in square brackets:

var a = []; // array with no elements
var a = [1, 2, 3]; // array with three elements
var a = [[1, 2, 3], ['a', 'b', 'c']]; // array of two arrays

Object literals

Similarly, an empty object can be defined as:

var o = new Object();

A much better pattern is to use the object literal:

var o = {}; // empty object
var o = {p: 'one'}; // object with a "p" property
var o = { 
  prop: 1,  // a property
  meth: function() { // a method
    alert('Boo!');
  }
};

Separating behavior

September 14th, 2009

The modern understanding of a web page is that it consists of three distinct parts:

  1. Content (HTML)
  2. Presentation (CSS)
  3. Behavior (JavaScript)

These should be kept separate, ideally each in its own file (or files). What it means for JavaScript is that there should be no inline such as onclick, onmouseover, etc. Ideally there should be little to no inline scripts.

The idea is that content (the text on the page) is independent of:

  • how it looks like, so the page should be usable even with CSS disabled, or not supported by the browser, and
  • how it behaves, meaning the page should be usable even with JavaScript disabled. The content should be accessible independent of any mouseovers, animations, and so on.

JavaScript includes and DOMContentLoaded event

July 26th, 2008

My article about the non-blocking behavior of javascript includes was recently published on the YUI blog. Luke Chambers asked how does this method affect DOMContentLoaded event, so I gave it a shot.

The test examples are:

Basically, I added an event listener to document DOMContentLoaded event and to the onload events of every script, image and the document. I also exaggerated the loading time of scripts and images.

Results

Normal script tag

js: Sat Jul 26 2008 15:53:33 GMT-0700 (Pacific Daylight Time)
DOMContentLoaded: Sat Jul 26 2008 15:53:33 GMT-0700 (Pacific Daylight Time)
img2: Sat Jul 26 2008 15:53:37 GMT-0700 (Pacific Daylight Time)
img1: Sat Jul 26 2008 15:53:37 GMT-0700 (Pacific Daylight Time)
img6: Sat Jul 26 2008 15:53:37 GMT-0700 (Pacific Daylight Time)
img3: Sat Jul 26 2008 15:53:37 GMT-0700 (Pacific Daylight Time)
img5: Sat Jul 26 2008 15:53:37 GMT-0700 (Pacific Daylight Time)
img4: Sat Jul 26 2008 15:53:37 GMT-0700 (Pacific Daylight Time)
img8: Sat Jul 26 2008 15:53:40 GMT-0700 (Pacific Daylight Time)
img7: Sat Jul 26 2008 15:53:40 GMT-0700 (Pacific Daylight Time)
onload: Sat Jul 26 2008 15:53:40 GMT-0700 (Pacific Daylight Time)

DOM-included script

DOMContentLoaded: Sat Jul 26 2008 15:55:29 GMT-0700 (Pacific Daylight Time)
img1: Sat Jul 26 2008 15:55:32 GMT-0700 (Pacific Daylight Time)
img2: Sat Jul 26 2008 15:55:32 GMT-0700 (Pacific Daylight Time)
img6: Sat Jul 26 2008 15:55:32 GMT-0700 (Pacific Daylight Time)
img4: Sat Jul 26 2008 15:55:32 GMT-0700 (Pacific Daylight Time)
img3: Sat Jul 26 2008 15:55:32 GMT-0700 (Pacific Daylight Time)
img5: Sat Jul 26 2008 15:55:32 GMT-0700 (Pacific Daylight Time)
img8: Sat Jul 26 2008 15:55:35 GMT-0700 (Pacific Daylight Time)
img7: Sat Jul 26 2008 15:55:35 GMT-0700 (Pacific Daylight Time)
script: Sat Jul 26 2008 15:55:39 GMT-0700 (Pacific Daylight Time)
onload: Sat Jul 26 2008 15:55:39 GMT-0700 (Pacific Daylight Time)

In any event, the document onload waits for the script, no matter how it's included.

Progress indicator by animating background position

July 23rd, 2008

This post experiments with different patterns for indicating progress, you know, those "loading...", "Please wait..." type of things. The progress is shown by using JavaScript to animate the CSS background position.

TheSixtyOne.com

There's this cool site called http://www.thesixtyone.com/, great for discovering new music (if they only agree to ban Foo Fighters, the site will be perfect). Discovering music but also discovering interesting web design patterns, as it turns out.

TheSixtyOne.com shows a progress indicator when you click a song, as if the background shows how the song gets loaded. So I had to try implementing this myself and I also played with two other variants of the background animation.

Here's a video, a little screencast to demonstrate how the loading looks like:

Here are the three examples, take a look at the code, there are no external JavaScript libraries, just some do-it-yourself animation with setInterval()

Example #1 - filling the background

For this you get an image that is at least as long as the container you're about to animate. The height of the background image doesn't matter, could be just one pixel. Here's the image I used.

Ar the start of the animation, the background image is so to the left, it's invisible. At the end of the animation, the background fills out the whole container.

Run example #1

Example #2 - overflowing background

This is a modified version of the previous pattern. Once the background is filled the animation keeps going, so the background escapes from view. Then it's moved back at the beginning and the animation repeats.

Run example #2

Example #3 - dancing arrow

If you remember old radios, this pattern looks like you're playing with the dial. Here, the background image is different, just a small square basically. It gets repeated vertically. Here's the backgournd.

Run example #3

Literal Notations

May 17th, 2008

A little something from my forthcoming book "Object-Oriented JavaScript" I thought would be nice to share.

Literal Notations
name literal constructor example
object {} new Object() {prop: 1}
array [] new Array() [1,2,3,'test']
regular expression
/pattern/modifiers new RegExp('pattern', 'modifiers') /java.*/img

Doug Crockford on inheritance

May 6th, 2008

JavaScript, the good parts

From YUI blog today, there is a free chapter of Douglas Crockford's JavaScript book.

It's a great read. I had the pleasure of reading drafts of the book and giving some inputs (Whoa, giving Doug Crockford input with his JavaScript book! Yeah, I know.) and I can only highly recommend the book. But don't take my word for it, go download the free chapter and decide for yourself.