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


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

我手头有这些元素的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')]

12353
2018-01-30 22:42


起源

两者都没有 - 你应该使用jQuery! - Aaronaught
我正在使用jQuery。性能提升:同样的问题:我应该缓存jQuery对象($('#id1'))还是应该每次需要时调用$('#id1')? - Ropstah


答案:


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

例:

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';

8
2018-01-30 22:49



这是一个很好的观点,我想补充一点,你永远不知道是谁或者什么,会改变你的DOM节点。我总是倾向于明确地获取引用以减少错误并提高可读性。如果要在高性能情况下处理许多节点,则可能需要将它们分配给内存。 - Kris Walker
它将是大约500项,但它们将被正确管理。我正在使用jQuery,大多数时候对象将是$(jqueryfied),所以我可以调用position()之类的函数。将$('#id1')对象存储在内存中是否同样如此? - Ropstah
哦,现在有道理了。我想知道为什么缓存会在函数调用之间中断。 (当然,我在那里创造新的元素)。 - Dallaylaen


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

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

id1 现在引用带有的DOM元素 id 的 id1。如果没有找到任何元素 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');

3
2018-01-30 22:52





这个问题没有一个正确的答案。这一切都取决于你必须与之合作。如果您正在使用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
2018-01-31 01:21





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

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

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

2
2018-01-30 22:47



我在这里寻求性能提升。代码放在函数中,不需要阅读:) - Ropstah
所有代码都需要阅读,除非它是第一次完美编写,永远不需要修改或扩展,永远不需要新功能,永远不需要被理解。 :) - Eddie
如果将它存储在稀疏数组/映射中,它会更快吗?我问,因为getElementById本质上已经有缓存的ID,所以我不确定是否有任何收益,因为拥有已经拥有id(最快查找)的元素的缓存可以保存您将要查找的项目时间,但在查找数据的过程中,你基本上和getElementById做同样的事情...... - Dmitry
@Dmitry:可能取决于一些事情:浏览器,你使用它的频率(JIT是否温暖),存储的对象在哪里。我无法想象这与性能有关。我有兴趣看到一个基准。 - Georg Schölly