为什么这个Javascript比它的jQuery相当慢* *?

时间:2011-10-23 19:52:26

标签: javascript jquery performance

我有一个大约500个项目的HTML列表,上面有一个“过滤器”框。当我输入一个字母时,我开始使用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版本需要大约2-3秒来过滤每个字母,而Javascript版本需要17秒以上!我在Ubuntu Linux上使用谷歌浏览器。

这不是真正重要的事情,因此不需要超级高效。但是我在这里使用Javascript做了一些非常愚蠢的事情吗?

4 个答案:

答案 0 :(得分:28)

您可以尝试使用textContent代替innerText,我认为它应该更快。同时对列表生成和循环进行单独计时也可以判断列表生成是否存在问题。

答案 1 :(得分:4)

javascript速度的另一个最佳实践是在变量中缓存list.length并调用变量,如:

l = list.length;
for (var i=0;i<l;i++):{ code here}

也许jsperf的时机会更好。

答案 2 :(得分:2)

在这里,我稍微重构了一下你的代码:

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属性已经方便地引用它们。

我想知道此代码在您的网页上的效果......

答案 3 :(得分:0)

我使用while代替for并进行了一些小改进。 Here是最终代码。

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