我应该在变量中缓存document.getElementById()还是每次都调用它?

时间:2010-01-30 22:42:44

标签: javascript memory caching performance

我有很多次生成和引用的元素(鼠标悬停,点击,位置变化)。

我手头有这些元素的ID。将document.getElementById(ID)调用存储在变量中是否明智,或者每次调用document.getElementById()更快/更快/更慢?

var app = [];
var app.elements = []; 
//i can store ['id1', 'id2', 'id3']
//OR ['id1' => document.getElementById('id1'), 'id2' => document.getElementById('id2'), 'id3' => document.getElementById('id3')]

5 个答案:

答案 0 :(得分:8)

您当然应该尽可能重用引用,但您可能需要在每个函数体中获得一个新引用。

示例:

var e1 = document.getElementById('id1');
e1.innerHTML = 'test';
e1.className = 'info';

如果您延长参考时间,您可能会发现它们不再有效。例如,如果您为页面的一部分获取innerHTML并将其存储回来,那么该部分中的所有元素都将被删除并重新创建。如果您对该部分中的某个元素有引用,则该元素不再存在。

// This will recreate all elements inside the 'parent' element:
document.getElementById('parent').innerHTML += 'test';

答案 1 :(得分:3)

getElementById返回一个元素节点,它本质上只是一个JavaScript对象。您可以将此对象分配给变量,这意味着只要您在稍后阶段键入该变量,该变量就会指向此对象。所以,

var id1 = document.getElementById('id1');

id1现在指的是id id1的DOM元素。如果未找到id的元素,则document.getElementById将返回null。

如果元素保留在DOM中并且没有被替换,则将它们存储在数组中是有意义的,这样您就可以根据需要多次引用它们,而不会产生任何性能成本。

如果有帮助,您可以创建一个简单的功能来为您完成:

function getElementsByIds( /* id1, id2 ... */ ) {

    var elems = [];

    for (var i = 0, l = arguments.length; i < l; i++) {
        elems[i] = document.getElementById(arguments[i]);
    }

    return elems;

}

app.elements = getElementsByIds('id1', 'id2', 'id3');

答案 2 :(得分:3)

这个问题没有一个正确的答案。这一切都取决于你必须与之合作。如果您正在使用DOM树中包含大量元素的页面,则最好缓存引用并重用它们,以加快查找时间。如果您正在处理小页面,最好动态查找元素,并最大限度地减少浏览器的内存消耗。

它还取决于您定位的浏览器。例如,较新版本的Firefox第一次需要一段时间才能对元素进行细化,但是它们会在内部缓存引用,所以下次你要查找它时,它几乎是即时的。另一方面,IE不会缓存查找值,但在第一次尝试时,它的搜索时间比Firefox要快得多。

许多现代框架将缓存您找到的元素。但是,我个人仍然更喜欢在大多数时候使用document.getElementById。当我需要缓存查找值时,我的工作如下:

 function registerElement(id)
 {
     if (!this["get_" + id])
        this["get_" + id] = function() {
            var element = document.getElementById(id);
            this["get_" + id] = function() {return element;};
            return element;
        }
 }

您可以通过调用registerElement并向其传递元素的ID来使用它。当你需要检索值时,你调用你传递的get_element id,在第一次运行时它会查找元素并缓存它,在每次连续调用时它都会返回缓存值。

答案 3 :(得分:2)

将元素存储在变量中肯定会更快,但不是很大。这种情况因个案而异,应根据每个情况进行调整。

也许最重要的因素是易读性,我相信直接访问元素更具可读性。

theMainButton.style.color = "red";
// vs.
document.getElementById("theMainButton").style.color = "red";

答案 4 :(得分:0)

我编写了一个JS例程,通过以下三个测试对此进行了一些基准测试:-

  1. 将元素中的值转换为简单变量,然后重复分配
  2. 反复使用getElementById从元素获取值,并且
  3. 使用getElementById将元素放入变量中,然后反复从该变量中获取。

该测试是在一千万次迭代循环中进行的,显然有很多因素可能会影响结果(连续运行的数字甚至不完全相同,方差约为10%),但它们提供了“合理的指示”。

测试1到11毫秒

测试2-3983毫秒

测试3-3594毫秒

一毫秒对于您来说似乎并不长,但是对于您的计算机来说,这几乎是永恒的。

function RunSillySpeedTest(){
var t1,t2,t3,test1,test2,test3
var d,e,f,Msg;

d=new Date();
var t=d.getTime();

//Test 1 - Simple variable assignment
e=document.getElementById('divelement').innerText;
for(var i=0; i<10000000; i++){
    f=e;
}
d=new Date();
t1=d.getTime();
test1=t1-t;

//Test 2 - Repeated getElementById
for(var i=0; i<10000000; i++){
    f=document.getElementById('divelement').innerText;
}
d=new Date();
t2=d.getTime();
test2=t2-t1;

//Test 3 - Stored getElementById
e=document.getElementById('divelement');
for(var i=0; i<10000000; i++){
    f=e.innerText;
}
d=new Date();
t3=d.getTime();
test3=t3-t2;

Msg='<b>Test 1 took '+test1+'ms.<br>Test 2 took '+test2+'ms.<br>Test 3 took '+test3+'ms.<br></b>';
return Msg;

}