Javascript jQuery与DOM性能

Javascript jQuery与DOM性能,javascript,jquery,dom,Javascript,Jquery,Dom,我编写了这段代码来测试jQuery与DOM的性能。每个浏览器的性能都不同,表现最差的Firefox X25运行jQuery的速度较慢。 这是预期的行为吗?我没想到jQuery会产生如此大的影响 <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Untitled Document&

我编写了这段代码来测试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>

无标题文件
$(函数(){
var i=0;
var dtb=新日期();
而(i<1000000)
{
var指数=数学地板(数学随机()*30);
i++;
var elem=document.getElementById('d'+索引);
}
var dte=新日期();
警报(dte dtb);
i=0;
var dtb2=新日期();
var body=document.getElementById('cog');
而(i<1000000)
{
var指数=数学地板(数学随机()*30);
i++;
var elem=body.childNodes[索引];
}
var dte2=新日期();
警报(dte2-dtb2);
i=0;
var dtb3=新日期();
而(i<1000000)
{
var指数=数学地板(数学随机()*30);
i++;
变量$elem=$(“#d”+指数);
}
var dte3=新日期();
警报(dte3-dtb3);
/////编辑//////
/////按照Erik Reppen的建议实现了一个数组////////
i=0;
var idNames=新数组(30);

而(ijQuery是一个包装器,它以一种在每个主要浏览器中都能一致工作的方式规范DOM操作。它的执行速度比直接DOM操作慢25倍是完全合理的。性能损失是一个折衷方案,即使用简洁的代码

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

如果某个脚本的性能受到严重影响,请使用工具分析代码占用时间最多的地方


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

你像大锤一样使用jQuery杀死蚊子。每次你做
$(“#d”+索引)
,你都会告诉jQuery解析你的选择器,将选择器应用到DOM,然后将结果包装到一个占用内存的对象中。这真的很耗时

士气:在需要时使用jQuery,性能不是函数的核心。

这是因为
$(“#d”+索引);
document.getElementById('d'+索引);
做的事情不同。后者得到一个DOM对象。这是一种内置在浏览器中的本机对象类型

然而,
$
构建了一个jQuery对象。首先,它必须解析选择器,因为jQuery可以按类、属性、祖先等查找对象,而
document.getElementById
只能按ID查找元素。jQuery对象不是一个本机对象,因此创建速度较慢,而且它还有更大的潜力。例如,jQuery对象(实际上是原生DOM对象的包装器)提供了
next
val
bind
on
方法使用jQuery比使用本机DOM对象速度慢,但使用它编程更容易,而且通常执行速度更快,因为jQuery的作者可能比您更擅长Javascript。

这:

$('#someId');
最终归结为JQuery函数

document.getElementId('someId'); // and then wrap it in a JQuery object and return it
但是首先,它必须做一系列的逻辑来根据你发送的arg来确定你的意图

它是字符串吗?是的。有空格吗?没有。它是以“#”或“.”开头还是以某个有效的标记名开头?它以“#”开头。太好了,只需按ID抓取,打包并返回它

现在,请尝试对此进行测试:

$('#someId.active > .someClass:visible')
不管你在IE7中为DOM写了什么乱七八糟的东西,你都会明白JQuery的全部意义

一般来说,无论您使用的是核心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
==不相关但有助于原始测试===

下面是每个评论的一些例子,并在循环之前尽可能地支持您的问题

//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);
}
注意:数组的索引为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];

仅供参考:jQuery本身正在进行DOM操作。当有人希望只进行DOM操作时,jQuery所做的远远超过DOM操作。这可能会影响性能。作者:检查您的基准测试与其他一些常见测试工具相比是否有价值,就像我会做更多的缓存操作一样,因为这些都是非常巨大的循环。在第一个循环之前将所有ID缓存到一个数组中,以便循环只命中数组,而不是在访问getElementById之前连接字符串。然后在下一个循环之前将body.childNodes缓存到var中。IE尤其在DOM访问时非常慢,这涉及到一个构建/拆卸过程。对于JQ,我将对childN执行类似的循环ODE但缓存$('body').children(),然后在循环中只缓存children[index](除非您希望每个子对象都有JQuery实例,而不是常规dom对象)呃,去他妈的,我在我的回答中添加了一些对上述内容的讽刺。我认为这是对过早优化的热爱,这是万恶之源……我正在研究DOM,我得到了一个建议