Archive for the JavaScript category.

JavaScript first-class function limitation

Yesterday I needed to use a specific Object Oriented pattern to program a JavaScript module. My module was kind of a big object that contains other objects (sub-module).

The object literal notation

var bigModule = {

        subModule1: {
                method1: function () { },
                method2: function () { }
        },

        subModule2: {
                method1: function () { },
                method2: function () { }
        }

};

Because I needed to use closures for the module and it’s sub-modules, so I can keep the state of my system within the proper module, I didn’t want to use the object literal notation to code my module.

Instead I used functions to return my module properties, so I can declare variables just above the return statement of the module, so every properties can access them EVEN WHEN the function will return, e.g. until the program is loaded in memory.

The real way I did it

var bigModule = function () {
        var foo;

        return {

                subModule1: function () {
                        var bar;

                        return {
                                method1: function () { },
                                method2: function () { }
                        };
                }(),

                subModule2: function () {
                        var bar;

                        return {
                                method1: function () { },
                                method2: function () { }
                        };
                }()

        };

}();

I realized that it was not possible to refer to the properties of the precedent subModules within a subModule closure section (above the return statement), since the subModules are not an object literal, but a function that return an object.

I was astonished that I cannot access the bigModule properties, but deeper from within another function:

var bigModule = undefined; // used for the debugging
                           // purpose of this article
                           // to make sure it has never
                           // already returned the object.
var bigModule = function () {
        var foo;

        return {

                subModule1: function () {
                        var bar;

                        return {
                                method1: function () {
                                        alert("subModule1.method1() called");
                                },
                                method2: function () { }
                        };
                }(),

                subModule2: function () {
                        // Error: bigModule has no properties //
                        bigModule.subModule1.method1();

                        return {
                                method1: function () {
                                        // OK!, bigModule has already returned here //
                                        bigModule.subModule1.method1();
                                },
                                method2: function () { }
                        };
                }()

        };

}();

Even if I can do some hacks (some ugly, some ok, depending of what I want to achieve) to make it possible to access the bigModule variable once returned, before the return statement of the subModule2 property, I’m still confused and wonder if that pattern of programmation is really powerful or is limited (e.g. nested function literals).

I’m going to study it and understand that behavior. It seems that a function literal won’t be executed until it stops stacking deeper function literals.

Any explications?

Filed under: JavaScript | Comments (0)

The jQuery later “plugin”

You can extend jQuery.fn by assigning a later function to it to avoid always defining a callback function just to use setTimeout. later returns the object that called the function, so it do not breaks the chainability magic in jQuery.

The later plugin for jQuery

[ Thanks to Douglas Crockford for his teaching ]

jQuery.fn.later = function(msec, method) {
    var that = this;
    var args = Array.prototype.slice.apply(arguments, [2]);
    if (typeof method === "string") {
        method = that[method];
    }
    setTimeout(function () {
        method.apply(that, args);
    }, msec);
    return that;
};

It was almost my first plugin, but that is too short to make it a plugin :-)

It is more likely a feature. Let’s see examples of how to use it.

Samples of use for the later function

// Show "Saved!" for 3 seconds
$(‘#myid’).before("Saved!")
.prev().later(3000, "hide");

// Show "Saved!" for 3 seconds, hiding slowly
$(‘#myid’).before("Saved!")
.prev().later(3000, "hide", "slow");

// Chaining later …
// Change the appearance of the list for 4 seconds,
//   show a "saved" notice before it
//   and fade it slowly 3 seconds after if appears
$(‘#list_id’)
.addClass("success")
.later(4000, "removeClass", "success")
.before("Saved!")
.prev()
.later(7000, "fadeOut", "slow");

When *not* to use it

  • If you want to call a jQuery function right after an effect has finished, use the jQuery callback instead
  • If you are unsure that the function called by later will be executed after the previous one has finished and that the order matters

When to use it

  • If you can’t or don’t want to use the jQuery callback function
  • You would use the jQuery callback function just to use the setTimeout function to join two actions that are not dependent
  • When you can control the exact sequence of execution and you are sure it will be executed in that order

I’ve post a small article on using the later method with your own object. Read it.

Filed under: JavaScript | Comments (0)

later is better

I really enjoy hanging out at the YUI theater sometimes. There are very good conferences given mainly by the Yahoo! staff. I particularly like those one from Douglas Crockford, a Yahoo! JavaScript architect teach us very good stuff. In his “Advanced JavaScript” talk, he gives us a more OO solution to the setTimeout function. Let’s look at the later function code

The later function

Object.prototype.later = function(msec, method) {
    var that = this;
    var args = Array.prototype.slice.apply(arguments, [2]);
    if (typeof method === "string") {
        method = that[method];
    }
    setTimeout(function () {
        method.apply(that, args);
    }, msec);
    return that;
};

Examples of use

var duck = {
    say: function(what) {
        alert(what);
    },
    shout: function(n, what) {
        for (var i = 0; i < n; i++) {
            this.say(what.toUpperCase());
        }
    }
};

duck.later(6000, "say", "Quack!").later(12000, "shout", 3, "Quack!");

Arguments [2..n] are the arguments to pass to the function

Since it extends Object itself, later will be available to every functions. That is a very bad idea to extend the Object prototype. Why? Because you don’t want to break code that is not yours, as with libraries or api. Looping over each properties of that Object is often the only way they have to accomplish their goal. We must never touch the Object prototype. I know, I b
reak my code using that later function with jQuery.

If you do not use any code that’s not yours, you can augment Object.prototype otherwise you’ll have to find another way not to break other’s code. In order to use later you could extend your own object depending on the pattern you use for programming JavaScript. The following is an example of how you could use it.

The later function in a simple pattern

function Animal() {}

Animal.prototype.later = function(msec, method) {
  var that = this,
      args = Array.prototype.slice.apply(arguments, [2]);
  if (typeof method === "string") {
    method = that[method];
  }
  setTimeout(function () {
    method.apply(that, args);
  }, msec);
  return that;
};

Animal.prototype.say = function(what) {
    alert(what);
};

Animal.prototype.shout = function(n, what) {
    for (var i = 0; i < n; i++) {
        this.say(what.toUpperCase());
    }
};

duck = new Animal();
duck.later(6000, "say", "Quack!").later(12000, "shout", 3, "Quack!");

Update: How to use the later function through chaining in jQuery? Read my post.

Filed under: JavaScript | Comments (0)

Phil Rathe.com is powered by WordPress, theme: Clean Royal