Archive for the ‘Patterns’ Category

arguments considered harmful

Tuesday, February 16th, 2010

Inside every JavaScript function an arguments object is available containing all the parameters passed to the function.

function aha(a, b) {
  console.log(arguments[0] === a); // true
  console.log(arguments[1] === b); // true
}

aha(1, 2);

However, it's not a good idea to use arguments for the reasons of :

  • performance
  • security

The arguments object is not automatically created every time the function is called, the JavaScript engine will only create it on-demand, if it's used. And that creation is not free in terms of performance. The difference between using arguments vs. not using it could be anywhere between 1.5 times to 4 times slower, depending on the browser (more info and bench)

As for the security, there is the POLA (Principle of Least Authority) which is violated when one function A passes arguments to another B. Then a number of bad things can happen including:

  • B calls A through arguments.callee - something A never intended when calling B in the first place
  • B overwrites some arguments and causes A to misbehave

While in these scenarios B looks a little malicious, it can actually cause trouble unvoluntarilly. Consider this example that illustrates the second case (B changing values behind A's unsuspecting back)

function A(obj, ar) {

  console.log(obj); // {p: 1}
  console.log(ar);  // [1, 2, 3]

  B(arguments);

  // oops!
  console.log(obj); // {p: 2}
  console.log(ar);  // [1, 2]
}

function B(args) {

  // convenient innocent-looking local vars
  var o=args[0],
      a=args[1];

  // do something with the local variables
  o.p = 2;
  a.pop();

  // now the original arguments is 
  // messed up because objects/arrays
  // are passed by reference
}

A({p: 1}, [1, 2, 3]);

ECMAScript 5

In ECMAScript's "strict mode", using arguments.callee will throw a syntax error.

Recursive anonymous function

Probably the biggest argument for keeping arguments and arguments.callee is so that recursive anonymous functions can be created, because by using the callee property a function can call itself without knowing its own name. Now, this is not such a common scenario, but even if so, you can wrap a named function inside of an anonymous function and voila! - call that named function recursively without leaking a variable to the global scope.

Function properties

Tuesday, September 15th, 2009

Since functions are objects, and objects are mutable in JavaScript, you can add properties to your functions.

Why? For caching results of computations for example. Here's a memoization done this way.

function myFunc(param){
    if (!myFunc.cache) {
        myFunc.cache = {};
    }
    if (!myFunc.cache[param]) {
        var result = {}; // ...
        myFunc.cache[param] = result;
    }
    return myFunc.cache[param];
}

Here myFunc() gets a cache property which is an object. The function does the complicated computations based on a parameter and ends up with a result object. Using the parameter as a key in the cache object, it stores the result.

Consecutive calls with the same parameter will get the result from the cache, no need to compute the same result again.

Lazy definition function

Tuesday, September 15th, 2009

This has a nice name – a lazy function definition. A lazy function is one that pretends to work but it doesn't really.

It does some work initially and then caches the result. Then on consecutive calls it only returns the pre-computed result, it doesn’t really do anything.

In order to do so, the function redefines itself with a new implementation, one that simply points to the computed result.

function lazy() {
    var result = 2 + 2;
    lazy = function() {
        return result;
    };
    return lazy();
}

lazy(); // 4
lazy(); // 4

Self-overwriting functions

Tuesday, September 15th, 2009

Next pattern – a function that overwrites itself, a self-redefining function. Pretty similar to functions that return functions, but this time the function is re-implemented from the inside, not returned.

function next() {
    var count = 1;
    next = function() {
        return ++count;
    };
    return count;
}

next(); // 1
next(); // 2

Returning functions

Tuesday, September 15th, 2009

Functions are objects, so they can be passed around like callbacks for example and also returned by other functions.

You call a function that does some complicated setup and as a results returns a new function. You assign the result to a new function and use it afterwards.

function setup() {
    alert(1);
    return function() {
        alert(2);
    };
}
var my = setup(); // alerts 1
my(); // alerts 2

Your setup function can store some private data in a closure and use that data somehow.

Here setup() creates a counter function, which gives a next ID for example. But the count variable is not exposed.

function setup() {
    var count = 0;
    return function() {
        return ++count;
    };
}
var next = setup();
next(); // 1
next(); // 2

Callbacks

Tuesday, September 15th, 2009

Since functions are objects they can be passed as arguments to other functions.

function test(a, b, fn) {
    fn(a, b);
}

In this simple example we have a function test() that takes a function fn as a third parameter and calls that function passing the first two parameters.

When you cal the test() function, you can pass a pointer to an existing function myFunc() or you can also pass an anonymous function.

test(1, 2, myFunc);

test(1, 2, function(one, two){
    console.log(arguments);
});

Examples

For examples of this pattern in the wild – well, every time you attach an event listener, you pass a callback function.

document.addEventListener(
    'click',
    animateAndWowUser,
    false
);

Same with timeouts and intervals. setTimeout() and setInterval() expect a function and call it back after the specified number of milliseconds.

var thePlotThickens = function(){
  console.log('500ms later...');
};
setTimeout(thePlotThickens, 500);

And here's a common anti-pattern – passing a string where a function is expected. The JavaScript engine has no choice but to evaluate the string (like with eval()) and execute it, which is unnecessary work.

// anti-pattern
setTimeout("thePlotThickens()", 500);

Self-executing functions

Tuesday, September 15th, 2009

Update: "Immediate functions" sounds like a much better name.

Self-executable functions are simple and powerful.

All you do is add a set of parentheses after the function and this causes it to be executed right there. If it’s an anonymous function you also need to wrap it in parentheses.

(function(){
   var a = 1;
   var b = 2;
   alert(a + b);
})();

You can also pass parameters to the self-executing function if you want.

(function(a, b){
  var c = a + b;
  alert(c);
})(1, 2);

So how is this pattern useful?

It’s useful when you have some work to do, some initialization maybe. You need to do it only once and you don’t want to leave any globals lying around after the work is finished. All the temporary variables you need like c in the case above remain local and don't pollute the namespace.

Useful also when your code is kind of a guest to the page. Like a bookmarklet for example, or a widget of some sorts. You don’t want to add your variables and functions to the host page’s naming space and possibly causing a naming conflict with the page's core code.

Functions are objects

Tuesday, September 15th, 2009

Functions are objects, it’s very important to keep that in mind.

Functions are objects so they can have properties. And they they have methods.

They can be copied, deleted, passed as arguments to other functions, returned by other functions.

They also provide scope.

And they have special feature that sets them apart from the other objects – they are invokable, they can be called.

Prototypal inheritance

Tuesday, September 15th, 2009

Here's the prototypal inheritance pattern suggested by Douglas Crockford.

The implementation looks similar to a classical pattern but the idea is very different.

The idea is that there’s no constructors involved that lead you to think in terms of classes.
You have an object and you want to create another object that gets functionality from the existing object.

And, unlike when we simply copied properties over from the parent, here we involve the prototype and keep the prototype chain.

function object(o) {
  function F(){}
  F.prototype = o;
  return new F();
}

We take an existing object o, create a blank constructor function and set the parent object o to be the prototype.

Then return an object created with the temporary constructor. This child object has all properties of the parent as part of the prototype.

And here’s an example usage:

>>> var parent = {a: 1};
>>> var child = object(parent);
>>> child.a;
1
>>> child.hasOwnProperty(a);
false

The child object has everything the parent has - not as its own properties but as properties of its prototype.

ECMAScript 5

In the proposed version 5 of the ECMAScript standard, there will be a method that will work similarly and also accept another object, so basically you'll be able to inherit and add more functionality at the same time.

var child = Object.create(parent, {more:1})

Classical inheritance

Tuesday, September 15th, 2009

Let's talk a bit about classical inheritance. The word "classical" is not used in the sense of old-school middle-age has-been-around forever kind of meaning.

Classical just means that you think in terms of classes. Your objects are created by constructor functions and you want objects created from one constructor Child() to get properties that come from another constructor Parent().

function Parent(){
  this.name = 'Adam';
}
Parent.prototype.say = function(){
  return this.name;
};

function Child(){}

So we call a function called inherit() and let’s see some patterns for implementing this function.

inherit(Child, Parent);

Option #1 - The ECMA way

Here's the ECMA standard way. You create an object using the Parent() and assign this object to the Child()'s prototype.
Than when you do new Child(), it will get functionality from the Parent() instance via the prototype.

function inherit(C, P) {
  C.prototype = new P();
}

This pattern has the drawback that it’s tough to pass arguments to the parent during the call to new Child()

Option #2 - Rent-a-constructor

This next pattern solves the problem of passing arguments. It borrows the parent constructor passing the child object to be bound to this and passing any arguments.

This way you can only inherit properties added to this inside the parent constructor.
You don't inherits stuff that was added to the prototype.

function C(a, c, b, d) {
  P.call(this, arguments);
}

Option #3 - rent + prototype

Combining the previous two patterns you can pass arguments by borrowing the constructor and also inherit from the prototype.

function C(a, c, b, d) {
  P.call(this, arguments);
}
C.prototype = new P();

Drawback is that the parent constructor is called twice.

Option #3

Here's another way to do classical inheritance that doesn't include calling the parent constructor at all.

The rule of thumb is that reusable stuff should go to the prototype.

So for inheritance purposes, anything interesting should be in the prototype. Can you just say that child’s is the parent’s prototype? Yes, you can.

function inherit(C, P) {
  C.prototype = P.prototype;
}

This gives you really short prototype chain lookups because everybody has the same prototype. But that’s also a drawback because if a child down the inheritance chain modifies the prototype, it affects all parents.

Option #5

This next pattern solves the same-prototype problem by breaking the direct link and benefiting from the prototype chain.

Here you have an empty function which gets the prototype of the parent. The prototype of the child is an instance of the blank function.

function inherit(C, P) {
  var F = function(){};
  F.prototype = P.prototype;
  C.prototype = new F();
}

This pattern has a behavior slightly different from the ECMA standard suggestion because here you only inherit properties of the prototype. And that’s fine, actually preferable. Like I said – the prototype is the place for reusable functionality. Anything the parent ads to this inside the constructor is ignored.

Option #5 + super

Building on top of the previous pattern, you can add a reference to the original parent. This is like having access to the superclass in other languages.

The property is called uber because super is a reserved word and superclass may lead the non-suspecting developer down the path of thinking that JavaScript has classes. And we don’t want that, right?

function inherit(C, P) {
  var F = function(){};
  F.prototype = P.prototype;
  C.prototype = new F();
  C.uber = P.prototype;
}

Option #5 + super + constructor reset

One last thing to do in this almost perfect classical inheritance function is to reset the pointer to the constructor function in case we need it down the road.

function inherit(C, P) {
  var F = function(){};
  F.prototype = P.prototype;
  C.prototype = new F();
  C.uber = P.prototype;
  C.prototype.constructor = C;
}

If you don’t reset the constructor pointer, objects created with the Child() constructor will report that they were created with the Parent() constructor.

A function like this exists in the YUI library and helps you with your classical inheritance needs.