jQuery的$.data()与DOM对象属性之间的区别

9

我最近需要将一些数据添加到动态创建的LI元素中。在我的第一个尝试中,我使用了类似于.data()的方法:

var _newli = $('<li>foobar</li>');
_newli.data('base', 'ball');
// append _newli to an `ul`

那个...非常缓慢。这个逻辑在一个循环中发生,可以轻松增加到500多个项目,需要很长时间!有时甚至会破坏JavaScript执行时间框架。

所以我改用$.data()。不知何故,使用这种方法将数据附加到对象上比通过.data()方法调用快8倍。所以现在它看起来像这样:

var _newli = $('<li>foobar</li>');
$.data(_newli[0], 'base', 'ball');
// append _newli to an `ul`

确实,这样做速度更快,但仍然需要大约3-4秒钟才能构建出所有元素(在我的实际代码中,每个元素都有6次对$.data的调用)。

因此,我真的被困在那里,我问自己为什么要使用.data()$.data()?我可以将我的数据直接附加到DOM对象上。于是我这样做了。

var _newli = $('<li>foobar</li>');
_newli[0].base = 'ball';
// append _newli to an `ul`

看哪,wow我很震惊,这太快了!我简直不敢相信这个技术如此出色而没有任何缺点。所以这就是我的问题所在。实际上,我在网上还没有发现这种技术的任何缺点。有一些关于使用这种方式创建循环引用的文章,但据我所知,“只有”在IE上,并且只有在引用对象时才会出现。

专家们有什么想法吗?

更新

感谢大家的好评论和帖子。@patrick dw的简短更新:

你是对的,当使用$.data()时,我传递了底层的DOM元素。它甚至不能与jQuery对象一起使用,至少不符合预期。 我自己也有过使用一个对象并通过$.date()传递它的想法,但是由于性能差异太大,我决定永远忽略.data()方法。


如果每个元素有“6次对$.data的调用”,那么为什么您不只进行一次调用,并传递一个包含您想要的所有属性的值的对象呢?$.data(_newli,'myvalues',{'base':'ball','basket':'ball','foot':'ball'}); - user113716
2
在一次演讲中,约翰表示这种方法很慢,并建议使用 var data = $('selector').data(); data['foo'] = 'bar'; data['bar'] = 'foo'; 等方式,这样你只需要一次访问它。仅供参考。 - Felix Kling
@patrick dw:已更新帖子!@Felix Kling:听起来相当合理,你知道我在哪里可以找到那个Resig的演讲/论文吗?无论如何,我会尝试一下,大问题是,它是否接近“DOM属性存储”?否则它就没什么用了。 - jAndy
1
jAndy - 我使用Webkit的配置文件工具做了几个配置文件,使用@Felix的解决方案而不是写入DOM元素,分配一个属性。 如果我在测试中不包括初始变量分配数据:0.025毫秒,DOM:0.040毫秒。 如果我为data()包括变量分配,var data = $.data(_newli[0]),它会变化数据:0.040毫秒至0.225毫秒。 但这仅适用于分配一个属性。 分配多个属性将关闭其中一些差距(当存在时)。 在500个元素上使用$.data(),最慢的速度约为22ms。非常快。 再次强调,这仅适用于Webkit。 - user113716
@jAndy 看看这些 jsperf 统计数据:http://jsperf.com/jquery-data-vs-getattribute/13。 最快的选项是 el["searchable"] = true; - hitautodestruct
显示剩余2条评论
3个回答

3
您对“循环引用”是正确的,在IE之外这不是一个问题,在IE中只有当JavaScript引用了DOM对象并且JS对象被分配给DOM对象的属性时才会成为问题。我认为,通过将JS中的任何引用设置为DOM对象的null值即可解决此问题。
"$().data()"方法是"$.data()"的过度复杂的包装器(参见"jQuery.fn.data":http://github.com/jquery/jquery/blob/master/src/data.js#L126,它调用"jQuery.data":http://github.com/jquery/jquery/blob/master/src/data.js#L20),因此削减中间人将节省大量时间,特别是如果要执行500次。
在这种情况下,"$().data('foo', 'bar')"方法与"el.foo = 'bar'"方法没有太大区别。使用最快的方法。

2

0

这些可能会有所帮助:

并阅读有关使用自定义DTD的以下内容:

简而言之,我认为使用自定义属性大多数情况下不会遇到任何问题。大多数合理/当前的浏览器都可以很好地处理它。但是我必须说,我曾经在为MobileSafari开发的Web应用程序中遇到了问题,这迫使我不得不使用$.data隐藏元素。幸运的是,我没有500多个元素,只有五六个。

1
我猜我们正在谈论两个不同的故事。如果您将一些数据附加到element.somedata = {foo: 5};,那么不会为其创建任何attribute。这有点像在某种程度上混淆了ECMAlandDOMland,因为在ECMAscript中,DOM元素被视为对象。 - jAndy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接