Amir-is-very-wrong

JavaScript performance comparison

Revision 2 of this test case created by bobywow

Preparation code

<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

<div id="top">
  <div class="bottom hairy-head-red dead-head-red"></div>
</div>
<script>
Benchmark.prototype.setup = function() {
    //Needs tested on IE's
   
    var classy = {
        trimA : /^\s\s*/,
        trimB : /\s/,
        trim : function(str) {
            var str = str.replace(this.trimA, ''),
                    i = str.length;
            while (this.trimB.test(str.charAt(--i)));
            return str.slice(0, i + 1);
        },
        select: function(selector, forceAll) {
          if (typeof selector == 'string') {
                return ( forceAll ? document.querySelectorAll(selector) : document.querySelector(selector) );
              } else if ( selector.nodeType ) {
                return selector;
              } else if ( selector[0] && selector[0].nodeType ) {
                return ( forceAll ? selector : selector[0] );
              } else {
                return null;
              }
        },
        has : function(selector, cls, forceAll) {
          var nodes;
          if (!selector || !cls) return false;
          cls = " " + this.trim(cls) + " ";
         
          nodes = classy.select(selector, forceAll);
          if (!nodes) return null;
   
          if ( nodes[0] ) {
            for (var i = 0, len = nodes.length; i < len; i++) {
              if ( (" " + nodes[i].className + " ").indexOf( cls ) == -1 ) return false;
            }
            return true;
          }
   
          cn = " " + nodes.className + " ";
          return ( ( cn ).indexOf( cls ) > -1  );
      },
      add: function(selector, cls, forceAll) {
        var node, nodes, cn;
   
        if (!selector || !cls) return false;
        cls = " " + this.trim(cls) + " ";
     
        nodes = classy.select(selector, forceAll);
        if (!nodes) return null;
   
        if ( nodes[0] ) {
          for (var i = 0, len = nodes.length; i < len; i++) {
            node = nodes[i];
            cn = " " + node.className + " ";
            if ( ( cn ).indexOf( cls ) === -1  ) {
              node.className = this.trim( cn + cls.slice(1) );
            }
          }
          return nodes;
        }
   
        cn = " " + nodes.className + " ";
        if ( ( cn ).indexOf( cls ) === -1  ) {
          nodes.className = this.trim( cn + cls.slice(1) );
        }
        return nodes;
      },
      remove: function(selector, cls, forceAll){
        var nodes, node, cn;
   
        if (!selector || !cls) return false;
        cls = " " + this.trim(cls) + " ";
        nodes = classy.select(selector, forceAll);
        if (!nodes) return null;
   
        if (nodes[0]) {
          for (var i = 0, len = nodes.length; i < len; i++) {
            node = nodes[i];
            cn = " " + node.className + " ";
            if ( ( cn ).indexOf( cls ) > -1  ) {
              node.className = this.trim( cn.replace(cls.slice(1), ' ') );
            }
          }
          return nodes;
        }
        cn = " " + nodes.className + " ";
        if ( ( cn ).indexOf( cls ) > -1  ) {
          nodes.className = this.trim( cn.replace(cls.slice(1), ' ') );
        }
        return nodes;
      },
      toggle: function(selector, cls, state ) {
        if ( !selector || !cls ) return false;
       
        if (state === true || state === 'on' || state === 'add' ) {
          return this.add(selector, cls);
        }
        if (state === false || state === 'off' || state === 'remove' ) {
          return this.remove(selector, cls);
        }
        return this.toggle( selector, cls, !this.has(selector, cls) );
      },
      flip: function(selector, cls1, cls2 ) {
        if ( !selector || !cls1 || !cls2 ) return false;
   
        if ( this.has(selector, cls2) ) {
          this.remove(selector, cls2);
          return this.add(selector, cls1);
        } else {
          this.remove(selector, cls1);
          return this.add(selector, cls2);
        }
      }
    }
   
    var $bottom = $('.bottom','#top'), bottom = $bottom[0];
};
</script>

Preparation code output

Test runner

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

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
classy
classy.remove('#top .bottom', 'hairy-head-red');
pending…
jq
$('.bottom','#top').removeClass('hairy-head-red').addClass('knuckle-head-red');
pending…
classy cached
classy.add(classy.remove(bottom, 'hairy-head-red'), 'knuckle-head-red');
pending…
jquery
$bottom.removeClass('hairy-head').addClass('knuckle-head-red');
pending…
classy many
classy.add( classy.remove( classy.remove(bottom, 'hairy-head-red' ), 'dead-head-red'), 'knuckle-head-red');
pending…
jq many
$bottom.removeClass('hairy-head-red dead-head-red').addClass('knuckle-head-red')
pending…
js raw many
bottom.className = bottom.className.replace(/\b[a-zA-Z]*-head-red\b/g, ' ').replace(/$/, ' knuckle-head-red');
pending…
js raw many 2
bottom.className = bottom.className.replace(/\b[a-z]*-head-red\b/i, ' ') + ' knuckle-head-red';
pending…
js + jq combo
bottom.className = bottom.className.replace(/\b[a-z]*-head-red\b/i, ' ');
$bottom.addClass('knuckle-head-red')
pending…
other many
var newClass = 'hairy-head-red', cn = " " + bottom.className + " ", 
    removeList = ('hairy-head-red dead-head-red').split(' ');

removeList.forEach(function(cls){
  if ( ( cn ).indexOf( cls ) > -1  ) {
    cn = cn.replace(cls.slice, ' ')
  }
})
if ( (cn).indexOf(newClass) == -1 )
  bottom.className = classy.trim(cn + ' hairy-head-red');
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