Chaining: Prototype vs Nested

Benchmark created by Brandon Griffin on


Description

In reference to a JSFiddle (http://jsfiddle.net/codernator/xaPPw/3/) in which is defined a function to dynamically create function-chainging on an object. Compares the performance of using chain method in Function constructor vs. simply defining chained functions in a prototype pattern.

Note that the functions in the test objects don't actually do anything.

Setup

// Assign an anonymous function to instance[funcName] that executes
    // either baseHandler, or the existing instance[funcName] (if baseHandler
    // is not provided) and then returns instance. This allows creates the
    // ability to chain function calls together on the same instance.
    function chain(instance, funcName, baseHandler) {
        if (!baseHandler && !instance.hasOwnProperty(funcName)) {
            throw "function does not exist in instance.";
        }
        
        var handler = baseHandler || instance[funcName];
        if (typeof handler !== "function") {
            throw "Specified funcName or base does not correspond to a function.";
        }
        
        instance[funcName] = function () {
            handler.apply(instance, arguments);
            return instance;
        };
    }

Test runner

Ready to run.

Testing in
TestOps/sec
Nested Function Object
function Example() {
    var alwaysHandler = function () { },
        successHandler = function () { },
        failHandler = function() { };

    chain(this, 'always', function (handler) { alwaysHandler = handler; });
    chain(this, 'success', function (handler) { successHandler = handler; });
    chain(this, 'fail', function (handler) { failHandler = handler; });

    this.go = function (succeed) {
        if (succeed) {
            successHandler();
        } else {
            failHandler();
        }
        alwaysHandler();
    };
}

var example = new Example()
    .success(function () { })
    .always(function () { })
    .fail(function () { });

example.go(true);
example.go(false);
 
ready
Prototype Object - Manual Chaining
// INVALID - prototype gets jacked by the chain method.  Still looking 
// for other way to use prototype construction with chain method.
function ExampleP() {
    this._alwaysHandler = function () { },
    this._successHandler = function () { },
    this._failHandler = function() { };
}

ExampleP.prototype.go = function (succeed) {
        if (succeed) {
            this._successHandler();
        } else {
            this._failHandler();
        }
        this._alwaysHandler();
    };

ExampleP.prototype.always = function (handler) { this._alwaysHandler = handler; return this; };
ExampleP.prototype.success = function (handler) { this._successHandler = handler; return this; };
ExampleP.prototype.fail = function (handler) { this._failHandler = handler; return this; };

var example2 = new ExampleP()
    .success(function () { })
    .always(function () { })
    .fail(function () { });

example2.go(true);
example2.go(false);
ready
Hybrid
function ExampleH() {
    this._alwaysHandler = function () { },
    this._successHandler = function () { },
    this._failHandler = function() { };

    chain(this, 'always', function (handler) { this._alwaysHandler = handler; });
    chain(this, 'success', function (handler) { this._successHandler = handler; });
    chain(this, 'fail', function (handler) { this._failHandler = handler; });
}

ExampleH.prototype.go = function (succeed) {
        if (succeed) {
            this._successHandler();
        } else {
            this._failHandler();
        }
        this._alwaysHandler();
    };

var example3 = new ExampleH()
    .success(function () { })
    .always(function () { })
    .fail(function () { });

example3.go(true);
example3.go(false);
 
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.

  • Revision 1: published by Brandon Griffin on