寻求更快的$。(':data(key)')

时间:2011-01-05 01:38:01

标签: javascript jquery performance jquery-selectors

我正在编写jQuery扩展,使用

将数据添加到DOM元素
el.data('lalala', my_data);

然后使用该数据动态上传元素。

每次从服务器获取新数据时,我都需要更新所有具有

的元素
el.data('lalala') != null;

为了获得所有需要的元素,我使用了James Padolsey的扩展名:

$(':data(lalala)').each(...);

一切都很好,直到我遇到需要运行该代码50次的情况 - 它非常慢!使用3640个DOM元素在我的页面上执行大约需要8秒

var x, t = (new Date).getTime();
for (n=0; n < 50; n++) {
  jQuery(':data(lalala)').each(function() {
    x++;
  });
};
console.log(((new Date).getTime()-t)/1000);

由于我不需要RegExp作为:data选择器的参数,我试图通过

替换它
var x, t = (new Date).getTime();
for (n=0; n < 50; n++) {
  jQuery('*').each(function() {
    if ($(this).data('lalala'))
      x++;
  });
};
console.log(((new Date).getTime()-t)/1000);

此代码更快(5秒),但我想要更多。

有没有更快的方法来获取具有此数据密钥的所有元素?

事实上,我可以保留一个包含我需要的所有元素的数组,因为我在模块中执行.data('key')。检查具有所需.data('lalala')的100个元素比检查3640更好:)

所以解决方案就像

for (i in elements) {
  el = elements[i];
  ....

但有时会从页面中删除元素(使用jQuery .remove())。上面描述的两个解决方案[$(':data(lalala)')解决方案和if ($(this).data('lalala'))]将跳过已删除的项目(我需要),而带数组的解决方案仍将指向已删除的元素(事实上,该元素不会被真正删除 - 它只会从DOM树中删除 - 因为我的数组仍然有引用。

我发现.remove()也会从节点中删除数据,因此我的解决方案将变为

var toRemove = [];

for (vari in elements) {
  var el = elements[i];
  if ($(el).data('lalala'))
    ....
  else
    toRemove.push(i);
};

for (var ii in toRemove)
  elements.splice(toRemove[ii], 1); // remove element from array

此解决方案快100倍!

Q 从该数组中删除时,垃圾收集器会释放DOM元素占用的内存吗?

请记住,元素已被DOM树引用,我们在数组中创建了一个新引用,然后使用.remove()删除,然后从数组中删除。

有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

  

有没有更快的方法来获取具有此数据密钥的所有元素?

当然!,直接遍历数据存储而不是通过元素,例如,如果你想要计数:

var x=0;
for(var key in $.cache) { 
  if(typeof $.cache[key]["lalala"] != "undefined") x++; 
}

这几乎是即时的,因为元素只有$.cache的条目,如果它们有数据和/或事件,并且没有 DOM遍历发生。

对于另一篇文章,是的,这将跳过已删除的元素,因为它们的缓存也会被清除,前提是您不直接通过.innerHTML删除它们。

答案 1 :(得分:0)

自V1.4.3起,jQuery支持HTML5-data-attribute 这意味着:如果您设置了HTML属性data-lalala,则还可以使用element.data('lalala')访问这些属性。这应该快得多,因为你使用了 原生属性选择器$('*[data-lalala]')而不是一些解决方法。

所以你必须使用:

el.attr('data-lalala', my_data);

而不是

el.data('lalala', my_data);

注意:由于那些data-attributes只允许使用字符串,因此如果需要使用对象,则需要将对象存储为字符串化的JSON。