JavaScript performance comparison

Revision 3 of this test case created by tomByrer and last updated


Test each/forEach for performance of iterating arrays and objects in AngularJS, Underscore, & Lo-Dash.

v3: Updated v2 to latest Underscore, Lo-Dash & Underscore-clone build. Renamed tests.

Preparation code

<script src="https://cdn.jsdelivr.net/jquery/1.11/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<script src="https://cdn.jsdelivr.net/underscorejs/1.6/underscore-min.js"></script>
<script>var underscore = _.noConflict();</script>
<script src="https://cdn.jsdelivr.net/lodash/2.4.1/lodash.min.js"></script>
<script>var lodash = _.noConflict();</script>
<script src="https://cdn.jsdelivr.net/lodash/2.4.1/lodash.underscore.min.js"></script>
var toString = Object.prototype.toString;
var has = Object.prototype.hasOwnProperty;

function type(val) {
 switch (toString.call(val)) {
    case '[object Date]': return 'date';
    case '[object RegExp]': return 'regexp';
    case '[object Arguments]': return 'arguments';
    case '[object Array]': return 'array';
    case '[object Error]': return 'error';

  if (val === null) return 'null';
  if (val === undefined) return 'undefined';
  if (val !== val) return 'nan';
  if (val && val.nodeType === 1) return 'element';

  return typeof val.valueOf();

function each(obj, fn, ctx) {
  //fn = toFunction(fn);
  ctx = ctx || this;
  switch(type(obj)) {
    case 'array':
      return array(obj, fn, ctx);
    case 'object':
      if ('number' == typeof obj.length) return array(obj, fn, ctx);
      return object(obj, fn, ctx);
    case 'string':
      return string(obj, fn, ctx);

function string(obj, fn, ctx) {
  for (var i=0; i<obj.length; i++) {
    fn.call(ctx, obj.charAt(i), i);

function object(obj, fn, ctx) {
  for(var key in obj) {
    if (has.call(obj, key)) {
      fn.call(ctx, key, obj[key]);

function array(obj, fn, ctx) {
  for (var i=0;i<obj.length; i++) {
    if(fn.call(ctx, obj[i], i) === {}) return;
Benchmark.prototype.setup = function() {
    var _ = window._,
        angular = window.angular,
        each = window.each,
        lodash = window.lodash,
        underscore = window.underscore;
    var j = 300;
    var arr = _.shuffle(_.range(j));
    var obj = {};
    var noop = function() {};
    while(j--) {
      obj[j] = 'value' + arr[j];

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
angular array
angular.forEach(arr, noop);
angular object
angular.forEach(obj, noop);
lodash array
lodash.each(arr, noop);
lodash object
lodash.each(obj, noop);
lodash.underscore array
_.each(arr, noop);
lodash.underscore object
_.each(obj, noop);
underscore array
underscore.each(arr, noop);
underscore object
underscore.each(obj, noop);
js array
each(arr, noop);
js object
each(obj, noop);

Compare results of other browsers


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:


tomByrer (revision owner) commented :

Tests on same 1st gen i7 laptop; odd that Underscore usually beats out the Lo-Dash Underscore-build by a wide margin except in the Firefox alpha.

UserAgent , Angular , jQuery , JS , Lo-Dash , Underscore , # Tests

Chrome 33.0.1750, 10,608, 11,743, 10,307, 10,307, 30,067, 3

Firefox 30.0, 6,654, 6,454, 6,654, 13,038, 8,104, 4

IE 10.0, 8,305, 11,267, 6,003, 7,512, 13,782, 1

PaleMoon(Firefox) 24.4.1, 5,896, 5,360, 6,358, 6,016, 13,207, 6

tomByrer (revision owner) commented :

Note: The above recorded tests were before me adding the normal Lo-Dash test. The Lo-Dash Underscore-build is now labeled "Lo-Dash". Lo-Dash is still much slower than Underscore, though the regular Lo-Dash is usually close, if not a bit faster.

tomByrer (revision owner) commented :

Note 2: The 1st tests were actually with a "Backbone" build, which IIRC are another Lo-Dash-Underscore specialized build. Either way, same results.

Comment form temporarily disabled.

Add a comment