3

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

4 回答 4

11

这个:

$('#someId');

最终归结为 JQuery 函数说

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

但首先,它必须根据您发送的 arg 执行一系列逻辑来弄清楚您的意图是什么。类似的东西(我知道还有更多):

它是一个字符串吗?是的。有空格吗?不,它是以“#”、“.”还是一些有效的标记名开头的?它以“#”开头。太好了,只需凭身份证抓取,打包并退回。

现在尝试对此进行测试:

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

比。无论您必须为 IE7 中的 DOM 编写什么糟糕的东西,您都会看到 JQuery 的全部意义。

一般来说,一遍又一遍地重复 DOM 选择是一件愚蠢的事情,无论您使用的是核心 DOM 方法还是特别是 JQuery。这就像在循环内没有使用任何函数时抱怨函数调用开销。尝试在缓存初始元素抓取之后比较一些 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];
于 2012-05-23T00:52:39.467 回答
4

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

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

于 2012-05-23T00:21:42.390 回答
3

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

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

如果您某个脚本的性能受到严重影响,请使用工具分析代码在哪里花费的时间最多。

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

于 2012-05-23T00:21:12.003 回答
1

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

士气:在需要时使用 jQuery,而性能不是你的功能的主要主题。

于 2012-05-23T00:21:27.370 回答