Mixin

JavaScript performance comparison

Test case created

Preparation code

 
<script>
Benchmark.prototype.setup = function() {
    /**
     * Require the given path.
     *
     * @param {String} path
     * @return {Object} exports
     * @api public
     */

   
    function require(p, parent, orig){
      var path = require.resolve(p)
        , mod = require.modules[path];
   
      // lookup failed
      if (null == path) {
        orig = orig || p;
        parent = parent || 'root';
        throw new Error('failed to require "' + orig + '" from "' + parent + '"');
      }
   
      // perform real require()
      // by invoking the module's
      // registered function
      if (!mod.exports) {
        mod.exports = {};
        mod.client = mod.component = true;
        mod.call(this, mod, mod.exports, require.relative(path));
      }
   
      return mod.exports;
    }
   
    /**
     * Registered modules.
     */

   
    require.modules = {};
   
    /**
     * Registered aliases.
     */

   
    require.aliases = {};
   
    /**
     * Resolve `path`.
     *
     * Lookup:
     *
     *   - PATH/index.js
     *   - PATH.js
     *   - PATH
     *
     * @param {String} path
     * @return {String} path or null
     * @api private
     */

   
    require.resolve = function(path){
      var orig = path
        , reg = path + '.js'
        , regJSON = path + '.json'
        , index = path + '/index.js'
        , indexJSON = path + '/index.json';
   
      return require.modules[reg] && reg
        || require.modules[regJSON] && regJSON
        || require.modules[index] && index
        || require.modules[indexJSON] && indexJSON
        || require.modules[orig] && orig
        || require.aliases[index];
    };
   
    /**
     * Normalize `path` relative to the current path.
     *
     * @param {String} curr
     * @param {String} path
     * @return {String}
     * @api private
     */

   
    require.normalize = function(curr, path) {
      var segs = [];
   
      if ('.' != path.charAt(0)) return path;
   
      curr = curr.split('/');
      path = path.split('/');
   
      for (var i = 0; i < path.length; ++i) {
        if ('..' == path[i]) {
          curr.pop();
        } else if ('.' != path[i] && '' != path[i]) {
          segs.push(path[i]);
        }
      }
   
      return curr.concat(segs).join('/');
    };
   
    /**
     * Register module at `path` with callback `fn`.
     *
     * @param {String} path
     * @param {Function} fn
     * @api private
     */

   
    require.register = function(path, fn){
      require.modules[path] = fn;
    };
   
    /**
     * Alias a module definition.
     *
     * @param {String} from
     * @param {String} to
     * @api private
     */

   
    require.alias = function(from, to){
      var fn = require.modules[from];
      if (!fn) throw new Error('failed to alias "' + from + '", it does not exist');
      require.aliases[to] = from;
    };
   
    /**
     * Return a require function relative to the `parent` path.
     *
     * @param {String} parent
     * @return {Function}
     * @api private
     */

   
    require.relative = function(parent) {
      var p = require.normalize(parent, '..');
   
      /**
       * lastIndexOf helper.
       */

   
      function lastIndexOf(arr, obj){
        var i = arr.length;
        while (i--) {
          if (arr[i] === obj) return i;
        }
        return -1;
      }
   
      /**
       * The relative require() itself.
       */

   
      function fn(path){
        var orig = path;
        path = fn.resolve(path);
        return require(path, parent, orig);
      }
   
      /**
       * Resolve relative to the parent.
       */

   
      fn.resolve = function(path){
        // resolve deps by returning
        // the dep in the nearest "deps"
        // directory
        if ('.' != path.charAt(0)) {
          var segs = parent.split('/');
          var i = lastIndexOf(segs, 'deps') + 1;
          if (!i) i = 0;
          path = segs.slice(0, i + 1).join('/') + '/deps/' + path;
          return path;
        }
        return require.normalize(p, path);
      };
   
      /**
       * Check if module is defined at `path`.
       */

   
      fn.exists = function(path){
        return !! require.modules[fn.resolve(path)];
      };
   
      return fn;
    };require.register("component-emitter/index.js", function(module, exports, require){
   
    /**
     * Expose `Emitter`.
     */

   
    module.exports = Emitter;
   
    /**
     * Initialize a new `Emitter`.
     *
     * @api public
     */

   
    function Emitter(obj) {
      if (obj) return mixin(obj);
    };
   
    /**
     * Mixin the emitter properties.
     *
     * @param {Object} obj
     * @return {Object}
     * @api private
     */

   
    function mixin(obj) {
      for (var key in Emitter.prototype) {
        obj[key] = Emitter.prototype[key];
      }
      return obj;
    }
   
    /**
     * Listen on the given `event` with `fn`.
     *
     * @param {String} event
     * @param {Function} fn
     * @return {Emitter}
     * @api public
     */

   
    Emitter.prototype.on = function(event, fn){
      this._callbacks = this._callbacks || {};
      (this._callbacks[event] = this._callbacks[event] || [])
        .push(fn);
      return this;
    };
   
    /**
     * Adds an `event` listener that will be invoked a single
     * time then automatically removed.
     *
     * @param {String} event
     * @param {Function} fn
     * @return {Emitter}
     * @api public
     */

   
    Emitter.prototype.once = function(event, fn){
      var self = this;
      this._callbacks = this._callbacks || {};
   
      function on() {
        self.off(event, on);
        fn.apply(this, arguments);
      }
   
      fn._off = on;
      this.on(event, on);
      return this;
    };
   
    /**
     * Remove the given callback for `event` or all
     * registered callbacks.
     *
     * @param {String} event
     * @param {Function} fn
     * @return {Emitter}
     * @api public
     */

   
    Emitter.prototype.off = function(event, fn){
      this._callbacks = this._callbacks || {};
      var callbacks = this._callbacks[event];
      if (!callbacks) return this;
   
      // remove all handlers
      if (1 == arguments.length) {
        delete this._callbacks[event];
        return this;
      }
   
      // remove specific handler
      var i = callbacks.indexOf(fn._off || fn);
      if (~i) callbacks.splice(i, 1);
      return this;
    };
   
    /**
     * Emit `event` with the given args.
     *
     * @param {String} event
     * @param {Mixed} ...
     * @return {Emitter}
     */

   
    Emitter.prototype.emit = function(event){
      this._callbacks = this._callbacks || {};
      var args = [].slice.call(arguments, 1)
        , callbacks = this._callbacks[event];
   
      if (callbacks) {
        callbacks = callbacks.slice(0);
        for (var i = 0, len = callbacks.length; i < len; ++i) {
          callbacks[i].apply(this, args);
        }
      }
   
      return this;
    };
   
    /**
     * Return array of callbacks for `event`.
     *
     * @param {String} event
     * @return {Array}
     * @api public
     */

   
    Emitter.prototype.listeners = function(event){
      this._callbacks = this._callbacks || {};
      return this._callbacks[event] || [];
    };
   
    /**
     * Check if this emitter has `event` handlers.
     *
     * @param {String} event
     * @return {Boolean}
     * @api public
     */

   
    Emitter.prototype.hasListeners = function(event){
      return !! this.listeners(event).length;
    };
   
   
    });
    require.register("array/array.js", function(module, exports, require){
    /**
     * Module dependencies
     */

   
    var Emitter = require('emitter');
   
    /**
     * Expose `array`
     */

   
    module.exports = array;
   
    /**
     * Array prototype
     */

   
    var proto = Array.prototype;
   
    /**
     * Initalize `array`
     *
     * @param {Array} arr
     * @return {array}
     */

   
    function array(arr) {
      if(!(this instanceof array)) return new array(arr);
      return mixin(arr);
    }
   
    /**
     * Inherit from `Emitter`
     */

   
    Emitter(array.prototype);
   
    /**
     * Removes the last element from an array and returns that element
     *
     * @return {Mixed} removed element
     */

   
    array.prototype.pop = function() {
      var ret = proto.pop.apply(this, arguments);
      this.emit('pop', ret);
      this.emit('remove', ret);
      return ret;
    };
   
    /**
     * Push a value onto the end of the array,
     * returning the length of the array
     *
     * @param {Mixed, ...} elements
     * @return {Number}
     */

   
    array.prototype.push = function() {
      var ret = proto.push.apply(this, arguments),
          args = [].slice.call(arguments);
      this.emit('push', ret);
      for(var i = 0, len = args.length; i < len; i++) this.emit('add', args[i]);
      return ret;
    };
   
    /**
     * Reverses an array in place.
     *
     * @return {Array}
     */

   
    array.prototype.reverse = function() {
      var ret = proto.reverse.apply(this, arguments);
      this.emit('reverse', ret);
      return ret;
    };
   
    /**
     * Removes the first element from an array and returns that element.
     *
     * @return {Mixed}
     */

   
    array.prototype.shift = function() {
      var ret = proto.shift.apply(this, arguments);
      this.emit('shift', ret);
      this.emit('remove', ret);
      return ret;
    };
   
    /**
     * Sorts the elements of an array.
     *
     * @return {Array}
     */

   
    array.prototype.sort = function() {
      var ret = proto.sort.apply(this, arguments);
      this.emit('sort', ret);
      return ret;
    };
   
    /**
     * Adds and/or removes elements from an array.
     *
     * @param {Number} index
     * @param {Number} howMany
     * @param {Mixed, ...} elements
     * @return {Array} removed elements
     */

   
    array.prototype.splice = function() {
      var ret = proto.splice.apply(this, arguments),
          added = [].slice.call(arguments, 2);
      this.emit('splice', ret);
      for(var i = 0, len = ret.length; i < len; i++) this.emit('remove', ret[i]);
      for(    i = 0, len = added.length; i < len; i++) this.emit('add', added[i]);
      return ret;
    };
   
    /**
     * Adds one or more elements to the front of an array
     * and returns the new length of the array.
     *
     * @param {Mixed, ...} elements
     * @return {Number} length
     */

   
    array.prototype.unshift = function() {
      var ret = proto.unshift.apply(this, arguments),
          args = [].slice.call(arguments);
      this.emit('unshift', ret);
      for(var i = 0, len = args.length; i < len; i++) this.emit('add', args[i]);
      return ret;
    };
   
    /**
     * Mixin to `arr`.
     *
     *    var array = require('array');
     *    array(Something.prototype);
     *
     * @param {Object} arr
     * @return {Object} arr
     */

   
    function mixin(arr){
      for (var key in array.prototype)
        arr[key] = array.prototype[key];
      return arr;
    }
   
    });
    require.alias("component-emitter/index.js", "array/deps/emitter/index.js");
   
    require.alias("array/array.js", "array/index.js");
    var array = require('array');
    var arrr = array([]);
};
</script>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
Normal Array
var arr = [];

arr.push('1', '2');
pending…
Emitting Array
arrr.push('1', '2');
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

0 comments

Add a comment