16

I measured the execution times of those two functions:

  • jQuery grep function
  • Native JavaScript filter function

The execution of following methods have been measured using Chrome Profiles tool:

// jQuery GREP function
function alternative1(words, wordToTest) {
  return $.grep(words, function(word) {
    return wordToTest.indexOf(word) != -1;                    
  });
}

// Native javascript FILTER function        
function alternative2(words, wordToTest) {
  return words.filter(function(word) {
    return wordToTest.indexOf(word) != -1;                    
  });
}

Array of words was constructed of 1 million randomly generated strings. Each method was run 20 times. On my surprise jQuery grep function was faster.

Execution times (20 executions):

  • jQuery grep function 26,31s
  • Native JavaScript filter function 34,66s

You can repeate measurings on this jsFidle - it will take some time to execute so be patient.

Is there any explanation why jQuery grep function is faster then native JavaScript filter function?

PS: This questions was inspired by this answer.

Community
  • 1
  • 1
PrimosK
  • 13,848
  • 10
  • 60
  • 78
  • 6
    Looking for the explanation? Try taking a look at [**the implementation of grep**](https://github.com/jquery/jquery/blob/master/src/core.js#L712). As for testing performance, use [**JSPerf**](http://jsperf.com/) instead of making a script that can freeze the browser. – Joseph Dec 30 '12 at 13:28
  • I put it into [**a test suite in jsPerf**](http://jsperf.com/filterings). I reduced it to `100 000` elements though, even `1 000` is fine – Alexander Dec 30 '12 at 13:44
  • @Alexander thanks for porting JSFiddle code to JSPerf. – PrimosK Dec 30 '12 at 16:11

1 Answers1

12

By comparing the actual jQuery function $.grep uses on the page

function (a, b, c) {
    var d = [],
        e;
    c = !! c;
    for (var f = 0, g = a.length; f < g; f++) e = !! b(a[f], f), c !== e && d.push(a[f]);
    return d
}

(check here for non-minified, thanks Alexander) against the algorithm specified for

Array.prototype.filter.

It looks to me like .filter forces its this to Object, checks the callback IsCallable and sets this in it as well as checking for existence of property in each iteration, whereas .grep assumes and skips these steps, meaning there is slightly less going on.

Combine this with how good the JavaScript compiler in Chrome is and you might find the speed difference.

Adding some of these into $.grep would make it look like

function (elems, callback, inv, thisArg) {
    var ret = [],
        retVal;
    inv = !!inv;
    for (var i = 0, length = elems.length; i < length; i++) {
        if (i in elems) { // check existance
            retVal = !!callback.call(thisArg, elems[i], i); // set callback this
            if (inv !== retVal) {
                ret.push(elems[i]);
            }
        }
    }
    return ret;
}

and take about the same time as .filter (modified Alexander's jsperf).

Jason Sears
  • 429
  • 1
  • 7
  • 18
Paul S.
  • 64,864
  • 9
  • 122
  • 138
  • 2
    You may want to look at [a non-minified version of `$.grep`](http://james.padolsey.com/jquery/#v=1.7.2&fn=jQuery.grep) though – Alexander Dec 30 '12 at 13:54
  • 1
    @Alexander thanks, I've linked that in and credited you (twice because I made use of your jsperf too) – Paul S. Dec 30 '12 at 14:25