JavaScript:document.getElementById性能下降?

Ted*_*dyH 15 javascript optimization

document.getElementById常见的 CSS元素上重复使用了很多东西.

如果我创建一个global array存储我的所有document.getElementById元素而不是每次都重新获取元素,那么会有显着的性能提升吗?

示例,而不是:

document.getElementById("desc").setAttribute("href", "#");
document.getElementById("desc").onclick = function() {...};
document.getElementById("desc").style.textDecoration = "none"
document.getElementById("asc").setAttribute("href", "#");
document.getElementById("asc").onclick = function() {...};
document.getElementById("asc").style.textDecoration = "none"
...
Run Code Online (Sandbox Code Playgroud)

简单地说:

var GlobalElementId = [];
GlobalElementId ["desc"] = document.getElementById("desc");
GlobalElementId ["asc"] = document.getElementById("asc");
GlobalElementId [...] = document.getElementById(...);

GlobalElementId ["desc"].setAttribute("href", "#");
GlobalElementId ["desc"].onclick = function() {...};
GlobalElementId ["desc"].style.textDecoration = "none"
...
Run Code Online (Sandbox Code Playgroud)

Mik*_*ord 22

所以所有"是"的答案都在困扰我,所以我实际上是时候看看getElementById是否很慢!

以下是结果(对于包含10,000个元素的页面):

IE8 getElementById:0.4844 ms
IE8 id数组查找:0.0062 ms

Chrome getElementById:0.0039 ms
Chrome ID阵列查找:0.0006 ms

Firefox 3.5与chrome相当.

每个函数调用半毫秒不会让我使用数组;)但可能在IE6上更糟糕,我还没有安装.

这是我的脚本:

<html>
<head>
<script type="text/javascript">
    var numEles = 10000;
    var idx = {};

    function test(){
        generateElements();
        var t0 = (new Date()).getTime();
        var x = selectElementsById();
        var t1 = (new Date()).getTime();
        var time = t1 - t0;
        generateIndex();
        var t2 = (new Date()).getTime();
        var x = selectElementsWithIndex();
        var t3 = (new Date()).getTime();
        var idxTime = t3 - t2;

        var msg = "getElementById time = " + (time / numEles) + " ms (for one call)\n"
            + "Index Time = " + (idxTime/ numEles) + " ms (for one call)";
        alert(msg);
    }

    function generateElements(){
        var d = document.getElementById("mainDiv");
        var str = [];
       for(var i=0;i<numEles;i++){
           str.push("<div id='d_" + i + "' >" + i + "</div>");
        }
        d.innerHTML = str.join('');
    }

    function selectElementsById(){
        var eles = [];
        for(var i=0;i<numEles;i++){
            var id = ((i * 99) % numEles);
            eles.push(document.getElementById("d_" + id));
        }
        return eles;
    }

    function generateIndex(){
        for(var i=0;i<numEles;i++){
            var id = "d_" + i;
           idx[id] = document.getElementById(id);
        }
    }

    function selectElementsWithIndex(){
        var eles = [];
        for(var i=0;i<numEles;i++){
            var id = ((i * 99) % numEles);
            eles.push(idx["d_" + id]);
        }
        return eles;
    }   
</script>
</head>
<body onload="javascript:test();" >
<div id="mainDiv" />
</body>
</html>
Run Code Online (Sandbox Code Playgroud)


Pet*_*ley 7

既然你说"CSS元素"我怀疑你的很多性能不是因为重复使用document.getElementById()(你应该避免使用),而是你style为给定节点修改对象的次数.

每次更改属性时,style都会强制浏览器重新绘制该元素,可能还会重新绘制页面上的其他元素.

var elem = document.getElementById( 'desc' );
elem.style.textDecoration = "none"; // browser re-draw
elem.style.borderWidth    = "2px";  // browser re-draw
elem.style.paddingBottom  = "5px";  // browser re-draw
Run Code Online (Sandbox Code Playgroud)

在这里,更好的解决方案是使用CSS类并切换或添加/删除节点中的类名.这样,您只需一次重新绘制即可打包所需的样式更改.

var elem = document.getElementById( 'desc' );
elem.className = "whatever"; // Only one browser re-draw!
Run Code Online (Sandbox Code Playgroud)


Cha*_*ion 2

是的!

不久前有一种情况,我在修改元素时性能很差。解决方案是建立一个像你的例子一样的字典。我确实将性能提高了 1000 倍(至少在 IE6 中)。

var elementCache = {};
function buildElementCache() {
    elementCache[id] = {
        element1: document.getElementById(id + "1"),
        element2: document.getElementById(id + "2")
    } 
    // Etc...   
}
Run Code Online (Sandbox Code Playgroud)