javascript jQuery 与 DOM 性能

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10711823/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 10:47:08  来源:igfitidea点击:

jQuery vs DOM performance

javascriptjquerydom

提问by Registered User

I have written this code to benchmark jQuery vs DOM performance. The performance is defferent in every browser with the worst performer Firefox X25 slower running jQuery. Is this expected behavior? I wasn't expecting to see such an impact with jQuery.

我编写了这段代码来对 jQuery 与 DOM 性能进行基准测试。每个浏览器的性能都不同,性能最差的 Firefox X25 运行 jQuery 速度较慢。这是预期的行为吗?我没想到 jQuery 会产生这样的影响。

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled Document</title>
<script  type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js"></script>
<script language="JavaScript" type="text/javascript">
$(function () {
    var i=0;
    var dtb = new Date();
    while(i < 1000000)
    {
        var index = Math.floor(Math.random()*30);
        i++;
        var elem = document.getElementById('d'+index);
    }
    var dte = new Date();
    alert(dte-dtb);

    i=0;
    var dtb2 = new Date();
    var body = document.getElementById('cog');
    while(i < 1000000)
    {
        var index = Math.floor(Math.random()*30);
        i++;
        var elem = body.childNodes[index];
    }
    var dte2 = new Date();
    alert(dte2-dtb2);

    i=0;
    var dtb3 = new Date();
    while(i < 1000000)
    {
        var index = Math.floor(Math.random()*30);
        i++;
        var $elem = $("#d"+index);
    }
    var dte3 = new Date();
    alert(dte3-dtb3);



    /////EDIT//////
    ///// Implemented an Array as suggested by Erik Reppen  ////////


    i = 0;
    var idNames=new Array(30);
    while(i<30){
        idNames[i] = $("#d"+i);
        i++;
    }


    i=0;
    var dtb4 = new Date();
    while(i < 1000000)
    {
        var index = Math.floor(Math.random()*30);
        i++;
        var $elem = idNames[index];
    }
    var dte4 = new Date();
    alert(dte4-dtb4);

    /////EDIT//////////////////////////////////////////////



});

</script>
</head>

<body id="cog">
<div id="d0">sdfkjjfgdfd@@@</div><div id="d1">sdffgdfd@@@</div><div id="d2">sddfgfd</div><div id="d3">sdasfd</div><div id="d4">swqedfd</div><div id="d5">sddfdsfd</div><div id="d6">sdfd</div><div id="d7">sdsdffd</div><div id="d8">sdfsdfd</div><div id="d9">sdfkjlkjd</div><div id="d10">sdm ,nfd</div><div id="d11">sdcxvfd</div><div id="d12">sdxzcmfd</div><div id="d13">shgjmdfd</div><div id="d14">sdfvcbd</div><div id="d15">sdf;k;d</div><div id="d16">sdjklfd</div><div id="d17">sd412fd</div><div id="d18">sdfkyhkd</div><div id="d19">sdasdfd</div><div id="d20">sdhdfgsfd</div><div id="d21">sdfdsad</div><div id="d22">sdasdfd</div><div id="d23">sddfgdffd</div><div id="d24">sdklugiffd</div><div id="d25">sddfsafd</div><div id="d26">sdfq21fd</div><div id="d27">42324sdfd</div><div id="d28">sdnhmjkgufksfd</div><div id="d29">sdqwefdLAST</div>
</body>
</html>

回答by Erik Reppen

This:

这:

$('#someId');

ultimately boils down to the JQuery function saying

最终归结为 JQuery 函数说

document.getElementId('someId'); // and then wrap it in a JQuery object and return it

But first, it has to do a bunch of logic to figure out what your intentions are based on the arg you sent. Something like (and I know there's much more than this):

但首先,它必须做一堆逻辑来根据您发送的 arg 确定您的意图。类似的东西(我知道还有很多):

Is it a string? Yes. Are there spaces? No. Does it start with '#', '.', or some valid tagName? It starts with '#'. Great, just grab by ID, package and return it.

是字符串吗?是的。有空格吗?不。它是否以“#”、“.”或一些有效的 tagName 开头?它以“#”开头。太好了,只需按 ID 抓取,打包并返回即可。

Now try doing a test on this:

现在尝试对此进行测试:

$('#someId.active > .someClass:visible')

Vs. whatever ungodly mess you have to write for the DOM in IE7 and you'll see the whole point of JQuery.

对比 无论您必须在 IE7 中为 DOM 编写什么不敬虔的混乱,您都会看到 JQuery 的全部意义。

Generally speaking, repeating DOM selections over and over again is kind of a silly thing to do regardless of whether you're using core DOM methods or especially JQuery. It's like griping about function call overhead when no functions are getting used inside loops. Try comparing some DOM methods and JQ equivalents after caching that initial element grab instead. JQ might still be slower but I doubt 25 times slower in anything.

一般来说,无论您使用的是核心 DOM 方法还是特别是 JQuery,一遍又一遍地重复 DOM 选择是一件很愚蠢的事情。这就像在循环内没有使用函数时抱怨函数调用开销一样。尝试在缓存初始元素抓取后比较一些 DOM 方法和 JQ 等效方法。JQ 可能仍然更慢,但我怀疑任何事情都会慢 25 倍。

var $_someId = $('#someId');
dom_someId = document.getElementById('someId');
//now try looping a JQuery method vs an equivalent set of DOM methods for each

===Unrelated but helping with original test===

===无关但有助于原始测试===

Here's some examples per comments below and back up at your question as far as stuff to do before the loop.

下面是每个评论的一些示例,并在循环之前备份您的问题。

//caching ID names before loop
var i = 30,
idNames = [];
while(i--){ //confusing but tests as i, then inside i is i-=1
idNames[i] = 'd'+(i+1);
}

Note: You index the array by 0-30 so kill the +1 after the random index building statement in the loop. In fact I'm not sure why that 1-31 doesn't blow up your childNodes loop since it never hits the first element and should be trying to access two that aren't there.Remove the +1 and it's picking 0-30. The above loop assumed you wanted 1-31 but I just saw that the HTML only goes up to the 30 and starts with 1.

注意:您将数组索引为 0-30,因此在循环中的随机索引构建语句之后终止 +1。事实上,我不确定为什么 1-31 不会炸毁您的 childNodes 循环,因为它从未命中第一个元素,并且应该尝试访问两个不存在的元素。删除 +1 并选择 0-30 . 上面的循环假设你想要 1-31 但我刚刚看到 HTML 只上升到 30 并从 1 开始。

//caching object/property lookup and DOM Access/HTMLCollection/obj instantiation
var bodyChildren = body.childNodes; //DOM object lookups cost performance

//caching JQ so you can use the exact same loop afterwards
var bodyChildren = $('body').children();

//inside loops
bodyChildren[index];

回答by lonesomeday

This is because $("#d"+index);does not do the same thing as document.getElementById('d'+index);. The latter gets a DOM object. This is a native type of object, built into the browser.

这是因为$("#d"+index);document.getElementById('d'+index);. 后者获取一个 DOM 对象。这是一种原生类型的对象,内置于浏览器中。

$, however, builds a jQuery object. First, it has to parse the selector, since jQuery can find things by class, attribute, ancestor, etc., whereas document.getElementByIdonly finds elements by their ID. The jQuery object is not a native object, so is slower to create, and it also has much more potential. For instance, the jQuery object (which actually is a wrapper around the native DOM objects) provides the next, val, bindand onmethods. Doing the selection (or at least, doing a selection this simple) is slower with jQuery than with native DOM objects, but makes programming with it easier and often makes the execution faster, since the authors of jQuery are probably better at Javascript than you.

$,但是,会构建一个 jQuery 对象。首先,它必须解析选择器,因为 jQuery 可以通过类、属性、祖先等来查找事物,而document.getElementById只能通过它们的 ID 查找元素。jQuery 对象不是本机对象,因此创建速度较慢,但​​它也具有更大的潜力。例如,jQuery对象(实际上是围绕本机DOM对象的包装器)提供nextvalbindon方法。使用 jQuery 进行选择(或至少,进行如此简单的选择)比使用本机 DOM 对象慢,但使用它进行编程更容易并且通常使执行更快,因为 jQuery 的作者可能比您更擅长 Javascript。

回答by zzzzBov

jQuery is a wrapper that normalizes DOM manipulation in a way that works consistently in every major browser. It's fully reasonable for it to perform 25x slower than direct DOM manipulation. The performance loss is a tradeoff to have concise code.

jQuery 是一个包装器,它以在每个主要浏览器中一致工作的方式规范化 DOM 操作。它的执行速度比直接 DOM 操作慢 25 倍是完全合理的。性能损失是对简洁代码的权衡。

JavaScript in general is a highly asynchronous language. Much of its usage involves waiting for a user-triggered callback, or timer. Because there's so much time, performance is hardly ever an issue. A user wont notice the difference between a process that runs in 1ms compared to a process that runs in 25ms.

JavaScript 通常是一种高度异步的语言。它的大部分用法涉及等待用户触发的回调或计时器。因为有这么多时间,性能几乎不是问题。用户不会注意到在 1 毫秒内运行的进程与在 25 毫秒内运行的进程之间的区别。

If there isa significant performance hit in one of your scripts, use tools to analyze where the code is taking the most time.

如果在脚本中的一个显著的性能损失,使用的工具来分析其中的代码是最耗时。

After all, premature optimization is the root of all evil.

毕竟,过早优化是万恶之源。

回答by MaxArt

You're using jQuery like a sledgehammer to kill a mosquito. Everytime you do $("#d"+index), you tell jQuery to parse your selector, apply the selector to the DOM, then wrap the result in a memory-consuming object. This is really time consuming.

您像使用大锤一样使用 jQuery 来杀死蚊子。每次这样做时$("#d"+index),您都会告诉 jQuery 解析您的选择器,将选择器应用到 DOM,然后将结果包装在一个消耗内存的对象中。这真的很费时间。

Morale: use jQuery when you need to, and performances aren't the leit motif of your function.

士气:在需要时使用 jQuery,性能不是您功能的主旨。