Delegated Click Handler - Unified vs Ad Hoc

JavaScript performance comparison

Revision 3 of this test case created

Info

THE TRUE VARIATION

Initial version didn't take the click handler off of <body> in the teardown, and became the killer of browsers.

version 2 shows only ad hoc

Preparation code

<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js">
</script>
<div>
  <div class="someDiv">
    <div id="el1" class="someNestedDiv el1">
    </div>
    <div id="el2" class="someNestedDiv el2">
    </div>
    <div id="el3" class="someNestedDiv el3">
    </div>
    <div id="el4" class="someNestedDiv el4">
    </div>
    <div id="el5" class="someNestedDiv el5">
    </div>
  </div>
</div>
<script>
Benchmark.prototype.setup = function() {
    var clickTester = {
      clickEvents: [],
      setupClickHandler: function() {
        var self = this;
        $("body").on("click", function(e) {
          var $curTar = $(e.target);
          for (var i = 0; i < self.clickEvents.length; i++) {
            var curSel = self.clickEvents[i].selector
            console.log("loop for ", curSel);
            if ($curTar.is(curSel)) {
              self.clickEvents[i].callback(e);
            }
          }
        });
      }
    }
   
    function addClickEvents(clicks) {
      for (var i = 0; i < clicks.length; i++) {
        clickTester.clickEvents[clickTester.clickEvents.length] = clicks[i];
      }
    }
   
    function testFunction(e) {
      console.log("Test Function activated");
      console.log("target: " + e.currentTarget);
    }
   
    function triggerClick(sel) {
      var $body = $('body'),
          ev = jQuery.Event('click');
      ev.target = $body.find(sel)[0];
   
      $body.trigger(ev);
    }
};

Benchmark.prototype.teardown = function() {
    clickTester = null;
    $('body').off('click');
};
</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
Ad Hoc - ID
$('body').on('click', '#el1', function(e) {
  testFunction(e)
});

$('body').on('click', '#el2', function(e) {
  testFunction(e)
});

$('body').on('click', '#el3', function(e) {
  testFunction(e)
});

$('body').on('click', '#el4', function(e) {
  testFunction(e)
});

$('body').on('click', '#el5', function(e) {
  testFunction(e)
});

for (var i = 0; i < 20; i++) {
  triggerClick("#el1");
  triggerClick("#el2");
  triggerClick("#el3");
  triggerClick("#el4");
  triggerClick("#el5");
}
pending…
Unified - ID
var clicks = [{
  selector: "#el1",
  callback: function(e) {
    testFunction(e);
  }
}, {
  selector: "#el2",
  callback: function(e) {
    testFunction(e);
  }
}, {
  selector: "#el3",
  callback: function(e) {
    testFunction(e);
  }
}, {
  selector: "#el4",
  callback: function(e) {
    testFunction(e);
  }
}, {
  selector: "#el5",
  callback: function(e) {
    testFunction(e);
  }
}];

addClickEvents(clicks);

for (var i = 0; i < 20; i++) {
  triggerClick("#el1");
  triggerClick("#el2");
  triggerClick("#el3");
  triggerClick("#el4");
  triggerClick("#el5");
}
pending…
Ad Hoc - Single Class
$('body').on('click', '.el1', function(e) {
  testFunction(e)
});

$('body').on('click', '.el2', function(e) {
  testFunction(e)
});

$('body').on('click', '.el3', function(e) {
  testFunction(e)
});

$('body').on('click', '.el4', function(e) {
  testFunction(e)
});

$('body').on('click', '.el5', function(e) {
  testFunction(e)
});

for (var i = 0; i < 20; i++) {
  triggerClick("#el1");
  triggerClick("#el2");
  triggerClick("#el3");
  triggerClick("#el4");
  triggerClick("#el5");
}
pending…
Unified - Single Class
var clicks = [{
  selector: ".el1",
  callback: function(e) {
    testFunction(e);
  }
}, {
  selector: ".el2",
  callback: function(e) {
    testFunction(e);
  }
}, {
  selector: ".el3",
  callback: function(e) {
    testFunction(e);
  }
}, {
  selector: ".el4",
  callback: function(e) {
    testFunction(e);
  }
}, {
  selector: ".el5",
  callback: function(e) {
    testFunction(e);
  }
}];

addClickEvents(clicks);

for (var i = 0; i < 20; i++) {
  triggerClick("#el1");
  triggerClick("#el2");
  triggerClick("#el3");
  triggerClick("#el4");
  triggerClick("#el5");
}
pending…
Ad Hoc - Single Class
$('body').on('click', '.el1', function(e) {
  testFunction(e)
});

$('body').on('click', '.el2', function(e) {
  testFunction(e)
});

$('body').on('click', '.el3', function(e) {
  testFunction(e)
});

$('body').on('click', '.el4', function(e) {
  testFunction(e)
});

$('body').on('click', '.el5', function(e) {
  testFunction(e)
});

for (var i = 0; i < 20; i++) {
  triggerClick("#el1");
  triggerClick("#el2");
  triggerClick("#el3");
  triggerClick("#el4");
  triggerClick("#el5");
}
pending…
Unified - Multiple Classes
var clicks = [{
  selector: ".someNestedDiv.el1",
  callback: function(e) {
    testFunction(e);
  }
}, {
  selector: ".someNestedDiv.el2",
  callback: function(e) {
    testFunction(e);
  }
}, {
  selector: ".someNestedDiv.el3",
  callback: function(e) {
    testFunction(e);
  }
}, {
  selector: ".someNestedDiv.el4",
  callback: function(e) {
    testFunction(e);
  }
}, {
  selector: ".someNestedDiv.el5",
  callback: function(e) {
    testFunction(e);
  }
}];

addClickEvents(clicks);

for (var i = 0; i < 20; i++) {
  triggerClick("#el1");
  triggerClick("#el2");
  triggerClick("#el3");
  triggerClick("#el4");
  triggerClick("#el5");
}
pending…
Ad Hoc - Multiple Classes
$('body').on('click', '.someNestedDiv.el1', function(e) {
  testFunction(e)
});

$('body').on('click', '.someNestedDiv.el2', function(e) {
  testFunction(e)
});

$('body').on('click', '.someNestedDiv.el3', function(e) {
  testFunction(e)
});

$('body').on('click', '.someNestedDiv.el4', function(e) {
  testFunction(e)
});

$('body').on('click', '.someNestedDiv.el5', function(e) {
  testFunction(e)
});

for (var i = 0; i < 20; i++) {
  triggerClick("#el1");
  triggerClick("#el2");
  triggerClick("#el3");
  triggerClick("#el4");
  triggerClick("#el5");
}
pending…
Unified - ID - AGAIN!
var clicks = [{
  selector: "#el1",
  callback: function(e) {
    testFunction(e);
  }
}, {
  selector: "#el2",
  callback: function(e) {
    testFunction(e);
  }
}, {
  selector: "#el3",
  callback: function(e) {
    testFunction(e);
  }
}, {
  selector: "#el4",
  callback: function(e) {
    testFunction(e);
  }
}, {
  selector: "#el5",
  callback: function(e) {
    testFunction(e);
  }
}];

addClickEvents(clicks);

for (var i = 0; i < 20; i++) {
  triggerClick("#el1");
  triggerClick("#el2");
  triggerClick("#el3");
  triggerClick("#el4");
  triggerClick("#el5");
}
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