Mixins

September 15th, 2009

Taking the idea of inheritance by property copying a step further, consider this this mixin implementation.

Instead of copying from one object, you can copy from any number of objects.

The implementation is pretty simple - just loop through arguments and copy every property of every object passed to the function.

function mixInThese() {
  var arg, prop, child = {};
  for (arg = 0; arg < arguments.length; arg++) {
    for (prop in arguments[arg]) {
      child[prop] = arguments[arg][prop];
    }
  }
  return child;
}

Here's how to use it. Pass any number of objects and you and up with a new object that has the properties of them all.

var cake = mixInThese(
 {eggs: 2, large: true},
 {butter: 1, salted: true},
 {flour: "3 cups"},
 {sugar: "sure!"}
);

Inheritance by copying properties

September 14th, 2009

Let's take a look at an inheritance pattern – inheritance by copying properties. In this pattern an object gets functionality from another object, simply by copying it.

function extend(parent, child) {
  var i, child = child || {};
  for (i in parent) {
    child[i] = parent[i];
  }
  return child;
}

In this implementation child is optional, if you don't pass an existing object to augmented, than a brand new is created and returned.

It's a very simple implementation, just looping through the parent’s members and copy them over.

Now you may say "Hey, hey, hey, what about performance? Isn’t it inefficient to copy around properties like this?". Technically yes, but if that’s your performance bottleneck, you probably have the fastest JavaScript app ever.

This works for many applications, Firebug has an extend() methods that does this. Firebug is a pretty complex app and this works for it, so it should work for many other applications.

And one more heads-up - this is a "shallow copy" of the object, if you need you can do a "deep copy" - checking if the property you're about to copy is an object and if so, recursively iterate through the properties.

Borrowing methods pattern

September 14th, 2009

Functions in JavaScript are objects, they come with some cool methods of their own, like call() and apply(). The only difference between both is that one takes an array of parameters, the other one takes parameters one by one.

And you can use these methods to borrow functionality. Here's how:

// call() example
notmyobj.doStuff.call(myobj, param1, p2, p3);
// apply() example
notmyobj.doStuff.apply(myobj, [param1, p2, p3]);

So your object is called myobj and you know some other object called notmyobj has an extraordinary useful method called doStuff().
Instead of going through the inheritance hassle and inherit a bunch of stuff you don’t need, you can simply borrow the method you like temporarily.

You pass your object and any parameters and the other binds your object as its own this. Basically you pretend to be the other object, benefit from the method you like and move on.

It’s like getting an inheritance but without paying the inheritance tax. Where tax that comes in the form of useless properties.

Example: borrow from Array

A common use for this pattern is borrowing array methods.

Arrays have useful methods which array-like objects such as arguments do not. So arguments can borrow methods, like the slice() method.

function f() {
   var args = [].slice.call(arguments, 1, 3);
   return args;
}

// example
f(1, 2, 3, 4, 5, 6) // return [2,3]

In the example above, there’s an empty array created just for the sake of using its method.
A slightly longer way to do the same is to borrow the method from the Array.prototype directly. This saves creating one empty array.

Array.prototype.slice.call(...)

A case against inheritance

September 14th, 2009

Provocative title, right? Good. The point is not that inheritance is all that bad, it's that you should stop and think or a moment before you jump into long inheritance chains and complex UML.

In fact, the Object-Oriented Design Patterns book from "the gang of four" has this to say about inheritance:

“Prefer object composition to class inheritance”

It’s pretty easy to follow this advice in JavaScript. Remember - no classes in JavaScript. And how about the object literal, how simple it is? If you can add functionality to your objects from elsewhere – why do you need inheritance.

You can start with a blank slate and add stuff – either implement it yourself or grab from someone else.

Keep your eyes on the prize. You don’t need inheritance, you need functionality. In other languages inheritance may be your only choice. Not in JavaScript.

Further blog posts will show patterns such as borrowing methods, copying properties, mixins...

Prototype

September 14th, 2009

The prototype is an object that every function gets automatically, as soon as you create it.

You can add properties and methods to the prototype property of your constructor function. Then all objects created with this constructor will have access to everything you add to the prototype.

var Person = function(name) {
  this.name = name;
};
Person.prototype.say = function() {
  return this.name;
};

if you add properties to the prototype of a "normal" function, meaning function that you don't invoke as a constructor, these will not be used.

Using the prototype

var adam = new Person('Adam');
alert(adam.name); // "Adam"
alert(adam.say()); // "Adam"

As you can see the object has access to the prototype’s members.

The prototype properties are shared among all objects.

Rule of thumb

And a general rule of thumb – the properties and methods that are meant to be reused and shared and inherited, should be added to the prototype.

Enforcing `new` in constructors

September 14th, 2009

A constructor is just a function and failing to invoke a constructor with new leads to errors. Not syntax errors but logical errors. Following a naming convention can certainly help, but it doesn't enforce the correct behavior. If you invoke a constructor without new, then this will refer to the global object, called window in browsers.

Here's a pattern that helps you make sure your constructor always behaves as constructor. Instead of adding all members to this, you add them to that.

In this implementation that is the same as this unless this is window which means someone forgot to use new.

function Person() {
  var that = (this === window) ? {} : this;

  that.name = name;
  that.say = function() {
    return "I am " + that.name;
  };

  return that;
}

window is only in browsers

Another way, if you work in non-browser environment is to check if this is an instance of your Person constructor.

Or name-agnostic, general-purpose way is to use arguments.callee instead of hard-coding the constructor name.

this instanceof Person
this instanceof arguments.callee

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.