这个问题是关于jQuery函数如何保存
HTML元素,以及是否可能对垃圾收集产生影响.
考虑以下两个函数,它们显示或隐藏某个< div> HTML页面中的元素.
function showError() { $("div#error").show(); }
function hideError() { $("div#error").hide(); }
这两个函数总是调用jQuery来查找< div> DOM树中的元素;它们可以被重构以消除jQuery函数的开销一次,如下:
var divError = $("div#error");
function showError() { divError.show(); }
function hideError() { divError.hide(); }
但在这种情况下,divError变量在全局范围内被松开;我们可以通过一个函数来获取一些技巧:
var showError, hideError;
(function() {
var divError = $("div#error");
showError = function() { divError.show(); }
hideError = function() { divError.hide(); }
})();
在所有这些情况下,对垃圾收集的影响是什么?将调用jQuery函数的结果浮动在全局范围内是一个问题吗?
尝试最小化对jQuery函数的调用是一个很好的规则吗?是应该遵循还是避免这些例子?
如果我用document.getElementById()替换这些示例中的jQuery,要检索HTML元素,是否也适用相同的问题?
最佳答案 垃圾收集
如果您正在做其中的一些,那么不要担心它.如果单独使用,此处显示的任何一个用户案例都不会对内存使用产生负面影响.
内存占用
当在大循环中完成时,这些将开始具有潜在影响. Each time a function object is created, it can take up to 754 bytes of memory.如果您创建了许多这些内容,例如1000,则可能会短暂地占用1MB内存,具体取决于浏览器可忽略不计. 10,000变得更糟(~10MB),100,000(~100MB)变得麻烦,1,000,000(~1GB)可能会开始引起一些严重的问题,取决于客户端以一分钟的UI锁定形式.
范围
当对象未保留在当前执行上下文中时,垃圾收集器将成为先前情况中的一个因素.每个执行上下文都有一个词法和可变环境.一旦当前执行上下文失去范围,变量环境就有资格进行垃圾收集.但需要注意的是,符合条件的仅仅意味着它会在某个时间发生并且不会对何时做出承诺.
为了减少不断增长的内存占用,确保实现函数的执行上下文以尽快丢失范围将确保垃圾收集器尽可能快地收集选项.同样,收集的选项可能在一段时间内无法实现.
履行
所有这些都是关闭变量所以一旦它们的引用消失了,它们在将来的某个时候有资格收集,当它方便垃圾收集器时.
性能
除此之外,如果单独使用,调用jQuery函数的问题应该不重要.唯一一次重复查询成为一个问题是当你有超过大约10,000个DOM元素时,你可能已经有其他问题;当你要重复数千次并想避免毫秒堆积时.优化总共不到10毫秒的任何事情都可能是微优化. 10-100是自由裁量的,超过100是绝对保证.
此外,只要id访问元素,就可以通过字典(哈希表)查找直接访问它,该查找是O(1).这意味着您的DOM不需要完全解析.然而,情况可能并非总是如此,所以我认为我们不能简单地停在那里.
所以,如果这只使用一次,那么你的第一个场景就没有错了(这里不需要使用div,id是O(1)查找).
function showError() { $("#error").show(); }
function hideError() { $("#error").hide(); }
但是,如果由于某种原因,id的字符串是一个类选择器,并且这些在循环中以某种方式大量完成,您将需要确保函数定义作用于循环,并且元素选择器是缓存(缓存本身引入了一个有趣的侧面案例,其中缓存的元素集可能实际上不匹配动态页面中类选择器之类的页面集 – 但这是一个边缘情况).
范围
父作用域很重要,因为您从未真正想要在全局作用域中执行代码.所以虽然这两个完成同样的事情
var divError = $("div#error");
function showError() { divError.show(); }
function hideError() { divError.hide(); }
和
var showError, hideError;
(function() {
var divError = $("div#error");
showError = function() { divError.show(); }
hideError = function() { divError.hide(); }
})();
(请注意,因为IIFE中的匿名函数具有由其词汇环境引用的变量环境,因此在该词汇环境符合条件之前,将无法进行垃圾收集)
他们都对范围略有不同.第一个将公开变量divError,而第二个不公开.在狭窄的环境中,这并不重要,因为词汇和变量环境中的冲突不太可能,但在全局命名空间中,这可能会有问题,因为在卸载整个页面之前不会收集词汇环境.这被称为polluting the global namespace.
备择方案
最后,整个分析归结为应该是相当微不足道的事情.如果要对此元素具有全局访问权限,请将其存储在已安全使用的全局变量中.由于您使用的是jQuery,因此您只需使用$即可.
$.errorDiv = $("#error");
当你想要切换它时,只需使用切换:)或隐藏/显示你是否不确定状态或以某种方式调用它显示两次.
$.errorDiv.toggle();
$.errorDiv.show();
$.errorDiv.hide();
我理解,最后一节可能不适用于直接,因为这可能是类似行为的简单再现.