Почему этот Javascript намного * медленнее *, чем его эквивалент jQuery? - PullRequest
13 голосов
/ 23 октября 2011

У меня есть список HTML около 500 элементов и поле «фильтр» над ним. Я начал с использования jQuery для фильтрации списка, когда набирал букву (код синхронизации добавлен позже):

$('#filter').keyup( function() {
    var jqStart = (new Date).getTime();

    var search = $(this).val().toLowerCase();
    var $list = $('ul.ablist > li');

    $list.each( function() {
        if ( $(this).text().toLowerCase().indexOf(search) === -1 )
            $(this).hide();
        else
            $(this).show();
    } );

    console.log('Time: ' + ((new Date).getTime() - jqStart));
} );

Однако после ввода каждой буквы произошла задержка в пару секунд (особенно первая буква). Поэтому я подумал, что это может быть немного быстрее, если я использую простой Javascript (я недавно прочитал, что функция jQuery each особенно медленная). Вот мой эквивалент JS:

document.getElementById('filter').addEventListener( 'keyup', function () {
    var jsStart = (new Date).getTime();

    var search = this.value.toLowerCase();
    var list = document.querySelectorAll('ul.ablist > li');
    for ( var i = 0; i < list.length; i++ )
    {
        if ( list[i].innerText.toLowerCase().indexOf(search) === -1 )
            list[i].style.display = 'none';
        else
            list[i].style.display = 'block';
    }

    console.log('Time: ' + ((new Date).getTime() - jsStart));
}, false );

Однако, к моему удивлению, простой Javascript в 10 раз медленнее , чем эквивалент jQuery. Версия jQuery фильтруется по каждой букве за 2-3 секунды, а версия Javascript - более 17 секунд! Я использую Google Chrome в Ubuntu Linux.

Это не для чего-то действительно важного, поэтому оно не должно быть супер эффективным. Но я делаю что-то действительно глупое с моим Javascript здесь?

Ответы [ 4 ]

28 голосов
/ 24 октября 2011

Вы можете попробовать использовать textContent вместо innerText, я думаю, что это должно быть быстрее.Кроме того, синхронизация генерации списка и цикла по отдельности будет указывать на наличие проблемы в генерации списка.

4 голосов
/ 24 октября 2011

Еще одна лучшая практика для скорости javascript - это кэширование list.length в переменной и вызов переменной:*

2 голосов
/ 24 октября 2011

Здесь я немного реорганизовал ваш код:

var filter = document.getElementById( 'filter' ),
    ablist = document.querySelector( '.ablist' );

filter.addEventListener( 'keyup', function () {
    var re, elems, i, len, elem;

    re = RegExp( this.value, 'i' );
    elems = ablist.children;

    for ( i = 0, len = elems.length; i < len; i += 1 ) {
        elem = elems[i];       
        elem.style.display = 
                elem.textContent.search( re ) > -1 ? 'list-item' : 'none';
    }
}, false );

Живая демоверсия: http://jsfiddle.net/MVFxn/

Изменения:

  • с регулярным выражением и флагом i, в toLowerCase,
  • если на странице есть только один элемент '.ablist', querySelector должен быть самым быстрым способом получить его (поскольку он прерывает запрос, как только находит первый такой элемент),
  • нет запроса для элементов LI, поскольку свойство children уже ссылается на них удобно.

Мне бы очень хотелось узнать, как этот код работает на вашей странице ...

0 голосов
/ 24 октября 2011

Я использовал while вместо for и сделал несколько небольших улучшений. Здесь - окончательный код.

var list = list = document.querySelectorAll('ul.ablist > li');
document.getElementById('javascriptFilter').addEventListener( 'keyup', function () {
    var jsStart = (new Date).getTime(),
        search = this.value.toLowerCase(),
        i = list.length - 1,
        listItem,
        result;
    while( i >= 0 )
    {
        listItem = list[i];
        if ( listItem.textContent.toLowerCase().indexOf(search) === -1 )
            listItem.style.display = 'none';
        else
            listItem.style.display = 'block';
        i--;
    }

    result = ((new Date).getTime() - jsStart);
    console.log(['Time: ', result, '<br />'].join(''));
}, false );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...