【问题标题】:speed up DOM access while using $element.each()使用 $element.each() 时加快 DOM 访问
【发布时间】:2013-02-16 12:46:39
【问题描述】:

我正在尝试在我庞大的 javascript UI 应用程序中进行一些严重的延迟削减。 我一直在阅读优化代码的方法,从我学到的一些东西中,我了解到:

  1. $(element).each() 让事情变慢
  2. 应缓存变量(和 HTML 对象)

这是我在应用程序中经常运行的函数中现有代码的一部分:

if($('.textbox').length > 0)
{   $(".textbox").each(function(){
             var parts = $(this).attr('id').split('_');
             // do some linear-time operations here with $this
            });
     });

到目前为止,我知道我应该将$this = $(this) 放在.each() 的开头并且只使用$(this)。但我还能做什么?有没有更快的替代方式来使用 .each()?我确实需要检查 每个 div.textbox 类。

【问题讨论】:

    标签: javascript jquery dom performance


    【解决方案1】:

    但是我还能做什么呢?

    几件事:

    1. 你的if 语句绝对没有意义(除非它有一个你没有显示的else 子句),因为在一个空的jQuery 对象上调用.each 是一个空操作。删除它。

    2. 如果你不想删除它,至少缓存 DOM 查找的结果,因为每次调用$('.textbox') jQuery 都要去查询 DOM。

      李>
    3. id 是 DOM 元素实例的反射属性,因此 $(this).attr("id").split('_') 涉及多个函数调用和内存分配,您可以使用 this.id.split('_') 避免。

    这给了我们:

    $('.textbox').each(function() {
        var parts = this.id.split('_');
        // Do something with `parts`
    });
    

    或者如果您没有显示else

    var boxes = $('.textbox');
    if (boxes.length) {
        boxes.each(function() {
            var part s= this.id.split('_');
            // ...
        });
    }
    else {
        // ...
    }
    

    【讨论】:

    • 谢谢!我对您直接使用this 的方式有点困惑。这比使用$this 更有效吗?我们可以直接使用this 甚至是$this.css('left') 之类的东西吗?
    • @user961627:在each(和jQuery事件处理程序)内,this指的是原始DOM元素,这意味着您可以使用DOM元素具有的任何属性或方法(参见the various DOM specs )。当您执行$(this) 时,您正在调用 jQuery 并传入 DOM 元素,并取回围绕它的 jQuery 包装器。该包装器提供了 jQuery 函数,如 css 等。
    • 谢谢 - 我一直对包装部分感到困惑 - 你说得很清楚。
    • 那么在效率方面有什么区别,获取 jQuery 包装器和使用 $(this).css,或者直接从 this 访问 CSS 属性?我假设不调用包装器会更好?还是再次几乎可以忽略不计?
    • @user961627:可以忽略不计,但同样,如果您经常很多,有时(有时)可以忽略不计。但请注意,jQuery(以及类似的库)在幕后做了很多 很多 来为您简化事情并消除浏览器差异。
    【解决方案2】:

    您正在使用 jQuery,它在后面执行大量代码。最快的方法是原生 Javascript。

    真正的小优化是从this 获取id。你也可以使用这个(Native JS)jQuery 来执行很多函数):

    var parts = this.id.split('_'); 
    

    例如
    尽可能快地获取所有元素。您可以使用此函数按类名获取元素:

    if (document.getElementsByClassName == undefined) {
        document.getElementsByClassName = function(className)
        {
            var hasClassName = new RegExp("(?:^|\\s)" + className + "(?:$|\\s)");
            var allElements = document.getElementsByTagName("*");
            var results = [];
    
            var element;
            for (var i = 0; (element = allElements[i]) != null; i++) {
                var elementClass = element.className;
                if (elementClass && elementClass.indexOf(className) != -1 && hasClassName.test(elementClass))
                    results.push(element);
            }
    
            return results;
        }
    }
    

    以及要循环的代码:

    var elements = getElementsByClassName(".textbox");
    for(var i=0;i<elements.length;i++)
    {
        var splitid = elements[i].id.split("_");
    }
    

    【讨论】:

    • 如果我使用纯javascript,我还需要使用getElementsByClassName(".textbox");,还是我们会去掉类名前的点.?另外,只是想知道 - 大多数浏览器不是已经定义了document.getElementsByClassName 吗?
    • @user961627:你会摆脱点(但你也会遇到并非所有浏览器都有getElementsByClassName的问题,尽管所有现代浏览器都有)。但是说使用“纯 JavaScript”比使用库“更快”是一种大量的过度概括。在绝大多数情况下,只要您正确使用该库(例如,不连续两次查询 DOM 以获取相同的信息,这自然会比只查询一次慢,而不管你是怎么做的)。
    • 谢谢@T.J.Crowder 这正是我的意思,jQuery 真的很适合做简单的事情。但是如果你想要性能,你可能不想要所有的库开销。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-18
    • 1970-01-01
    • 2016-09-05
    • 2019-05-28
    • 1970-01-01
    • 2014-07-18
    • 1970-01-01
    相关资源
    最近更新 更多