JQuery grep (...) Встроенный JavaScript-фильтр VS (...)

Я измерил время выполнения этих двух функций:

  • jQuery grep функция
  • Нативный JavaScript filter функция

Выполнение следующих методов было измерено с помощью инструмента Chrome Profiles:

// 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;                    
  });
}

Массив words был построен из 1 миллиона случайно сгенерированных строк. Каждый метод выполнялся 20 раз. С моей неожиданностью jQuery функция grep была быстрее.

Время выполнения (20 исполнений):

  • jQuery grep функция 26,31s
  • Нативный JavaScript filter функция 34,66s

Вы можете повторить измерения на этом jsFidle - это займет некоторое время, чтобы выполнить терпение.

Есть ли объяснение, почему jQuery grep функция быстрее, чем native JavaScript filter функция?

PS: Эти вопросы были вдохновлены этим ответом .

Ответ 1

Сравнивая фактическую функцию jQuery $.grep, используйте на странице

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
}

(отметьте здесь для неограниченного, спасибо Alexander) против алгоритм, указанный для

Array.prototype.filter.

Мне кажется, что .filter заставляет свой this Object, проверяет обратный вызов IsCallable и устанавливает в нем this, а также проверяет наличие свойства на каждой итерации, тогда как .grep принимает и пропустит эти шаги, что означает, что происходит немного меньше.

Объедините это с тем, насколько хорош компилятор JavaScript в Chrome, и вы можете найти разницу в скорости.

Добавление некоторых из них в $.grep сделает его похожим на

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;
}

и займет примерно то же время, что и .filter (изменено Alexander jsperf).