【问题标题】:Tips on optimizing javascript关于优化 javascript 的提示
【发布时间】:2009-05-26 01:22:38
【问题描述】:

我试图让我的网站做的事情变得相当复杂,一些需要完成的事情需要花费足够长的时间,从而导致明显的延迟。

主要是,向文档中添加内容会减慢我正在使用的 jquery 动画的速度。

我使用document.createElement("div")创建元素而不是仅仅做document.write("<div id='someId'></div>"),并且动画是使用.animation()的自定义动画;

我想知道如何才能继续按原样添加内容,但要防止浏览器在每次我想添加内容时冻结。

对于加快速度以减少延迟有什么建议吗? 关于在 javascript 编程中避免哪些会导致延迟增加的提示将非常有帮助。

【问题讨论】:

    标签: javascript performance optimization


    【解决方案1】:

    这听起来更像是您想提高 DOM 交互性能而不是 javascript,所以在这种情况下:

    • 是的,document.write 很糟糕,它会阻止额外的加载(在页面完成加载之前执行的任何 JS 基本上都需要停止所有其他处理 - 现代浏览器,如 Safari(以及代理 Chrome)和 Firefox 会在一定程度上内容预加载以防止加载阻塞,但随后的样式解析等在很大程度上被阻塞。
    • document.createElement 通常是最好的解决方案,尽管在某些情况下,仅在元素上操作 innerHTML 可能会更快——但这还不是跨浏览器兼容的(我认为 innerHTML 直到 Firefox 3.5 才存在)并且执行特性很棘手。
    • 减少最初加载的内容量 - 例如。如果您有大量内容(或需要大型脚本的内容),请尝试将加载延迟到初始页面加载完成之后。
    • 哦,对于动画,你应该看看 CSS 动画,它们的性能比任何 JS 实现都要好,但它们只存在于 Safari(和代理 Chrome)和 Firefox 3.5 中——绝对不存在于 IE 中:-(

    就 JavaScript 性能而言,请避免使用 with 和 getter/setter 之类的瘟疫,并且在大多数现代 JS 实现中应该没问题。

    【讨论】:

    • getter/setter 对性能的影响有多大?我被教导的编程方式不应该只是公开变量,但我想如果 getter 和 setter 需要大量的计算能力,那么牺牲可能是值得的......
    • innerHTML 肯定存在于 Firefox 3.0.4 及更高版本以及 Safari 3 中。我用过。尽管它可能不是最好的跨平台操作方法,但它并不像您想象的那么有限。
    • @A. Levy:也许我在想innerText? @Matt:使用函数而不是 ECMAScript 的 getter/setter 特性。 getter 和 setter 会破坏属性缓存并导致意外的函数调用,从而对性能产生灾难性影响——例如在 Safari4 中,我相信 getter/setter 比普通函数调用慢 10 倍左右。
    • 作为一个例子,我将这个简单的测试用例组合在一起——nerget.com/jstests/performance/getters-setters.html
    【解决方案2】:

    我知道这已经晚了几年,但总比不考虑这个问题出现在 google 的 javascript 动画优化列表顶部。

    如果您需要向 DOM 添加大量元素并且不想使用 innerHTML 这样做,您可以通过先将元素添加到 documentFragment 然后一次性注入 documentFragment 来加快速度进入 DOM。我记得读过 DOM 注入是使用标准 API 创建和添加元素的最慢部分。 documentFragment 允许您一次性将其所有内容注入到 DOM 中,从而消除了因多次调用 appendChild 或其他插入方法而导致的大量开销。 appendChild 和其他插入方法在插入到 documentFragment 时与插入到 DOM 中的成本不同。我希望我能找到我读到的这篇文章,因为它有一些非常好的基准测试和解释。我相信您可以通过搜索找到更多信息。

    与往常一样,应根据具体情况通过测试来确定使用哪种方法。最终,您可能会根据元素的结构、数量和用途来了解使用哪一种。

    PS。样式和 documentFragment 可能存在问题,但我不记得关于它们的内容,无论哪种方式都值得一试。

    【讨论】:

      【解决方案3】:

      JQuery 非常适合操作 DOM。我会看看他们的代码以获得一些想法。或者,看我有多懒,我就用他们的东西。

      在其中一个播客中,Jeff Atwood 提到你必须发疯才能编写自己的 javascript...在使用 JQuery 之后,我不得不同意他的看法。

      【讨论】:

        【解决方案4】:

        虽然我是 jQuery 的忠实粉丝,它使开发变得更加容易,但请注意,jQuery 语句(或任何 JavaScript 库中的)永远不会像其在纯 JavaScript 中的语义等价物一样快因为额外的开销。

        话虽如此,当我想加快 JavaScript 速度时,这些都是我的 goto 参考。

        http://home.earthlink.net/~kendrasg/info/js_opt/

        http://www.miislita.com/searchito/javascript-optimization.html

        【讨论】:

          【解决方案5】:

          有文档片段功能,可以让生活更轻松。这是使用示例。

          function appendDivs(element){
              var fragment = document.createDocumentFragment();
              for(var i=0;i<10;i++){
                  var div = document.createElement("div");
                  fragment.appendChild(div);           
              }
              element.appendChild(fragment);
          }
          

          如需完整参考,您可以在我的博客上查看post

          【讨论】:

            【解决方案6】:

            令大多数人惊讶的是,使用 innerHTML 实际上是操作 DOM 的最快方法。

            例如,您可以查看一个基准 here

            【讨论】:

            • 这完全取决于用例、使用的引擎(IE 的 DOM 实现速度非常慢)以及 html 中的代码长度——修改 innerHTML 需要重新解析整个字符串并要重建的dom。如果字符串中有很多元素,或者字符串很长,那么修改 innerhtml 会比较慢。此外,如果您持有对 innerHTML 块中元素的引用,这些元素将保留,但不会引用在其位置创建的新节点。
            • InnerHTML 中的更多元素意味着如果您想使用“首选”DOM 方法,也需要创建更多元素。不确定你在这一点上是否正确。至于其他问题......从来没有说它是完美的解决方案,只是最快的。我遇到过很多不使用 innerHTML 更方便的情况(你必须承认 innerHTML 是最直接的方法)。
            • 我想说的是,innerHTML 并不总是最快的——如果你有一段 html,&lt;li&gt;...&lt;/li&gt;&lt;li&gt;...&lt;/li&gt;... 如果你用 foo.innerHTML += 将 html 添加到列表的末尾
            • " +text+"
            • "。引擎必须重新解析整个字符串,并为所有字符串重建 DOM,因此解析不是免费的,创建元素也不是免费的,有一点是,添加一个新的 dom 创建的元素比添加到 innerHTML 更快, 如果你想引用列表中的元素,那么修改 innerHTML 将需要你重新获取这些元素。
          • 一个测试用例:nerget.com/jstests/performance/dom-manipulation.html DOM API 有(对所有意图)O(1) 插入,innerHTML 有 O(innerHTML 长度) 复杂度
          • 【解决方案7】:
            // Some functions for easier coding in DOM
            
            function createEl(el){
              return document.createElement(el);
            }
            function addElBody(el){
              return document.body.appendChild(el);
            }
            
            function addElChild(el, child){ //el- parent
              return el.appendChild(child);
            }
            // Example : 
            var container=createEl('div');
            container.setAttribute('id', 'container');
            addElBody(container);
            
            var item=createEl('ul');
            item.setAttribute('id', 'list');
            addElBody(item);
            addElChild(container, item);
            

            【讨论】:

              猜你喜欢
              相关资源
              最近更新 更多
              热门标签