在有人说:
之前document.querySelector('.myElem').getAttribute('data-*')
不,不是我想要的。 jQuery' s data()
具有双重功能。 1)它查询HTML5 data attribute,可以在HTML代码中看到,如下所示:
<div data-role="page" data-last-value="43" data-hidden="true" data-options='{"name":"John"}'></div>
$( "div" ).data( "role" ) === "page";
$( "div" ).data( "lastValue" ) === 43;
$( "div" ).data( "hidden" ) === true;
$( "div" ).data( "options" ).name === "John";
和2)由.data(name, value)
设置的隐藏在jQuery内部对象中的对象,文档仅说明&#34;以名称&#39;事件&#39;来保存信息。并且&#39;处理&#39;&#34;但我还没有找到一种方法来访问它们或实际创建它们的方式。
所以,我的问题是,如何从纯JavaScript中访问jQuery数据值?
就这样,它非常清楚......让我更加强调:我不想要data-
HTML属性,而是jQuery对象数据。
答案 0 :(得分:11)
jQuery使用名为$.cache
的内部对象来存储事件处理程序和数据值。 $.cache
是一个简单的字典,可以看起来像这样:
{ 1: { data: { role: "page"}, events: { click: ...} }, 2: { ... }}
密钥都是与某些DOM节点对应的唯一索引。如果您的DOM元素之前被jQuery(附加事件或某些数据)触及,您将看到它具有类似于下面的奇怪属性:
jQuery17108624803440179676: 2
此处jQuery17108624803440179676
是jQuery在页面上加载时生成的唯一字符串。此唯一标识符称为“expando”,存储为
$.expando
现在您已经知道如何通过绕过jQuery的数据API来访问单个元素的内部数据......
$.cache[element[$.expando]]
...您可能会问为什么jQuery使用中间对象来存储所有DOM数据和事件。原因是它是一种避免内存泄漏的方法,如果data
和事件处理程序直接存储在DOM元素属性中(由于循环引用),就会出现这种情况。
说了这么多,我想强调你应该不通过jQuery Data API处理除此之外的节点数据对象,原因很简单,因为它处理幕后所有复杂的东西
答案 1 :(得分:6)
根据评论,您绕过$(...).data
的动机似乎是基于它导致性能问题的事实。
我完全同意@meagar的观点,$(...).data
不应该足够昂贵而导致瓶颈。但是,如果您不断重新查询并重新包装DOM元素作为jQuery元素(例如$('#someEl').data(...)
多次而不是缓存$('#someEl')
并执行$someEl.data(...)
,那么它可能是一个问题。< / p>
请注意,如果您发现自己将大量数据附加到DOM元素,那么您的设计可能会出错。您的数据不应该存在于表示层中,您不必查询DOM或获取对DOM元素的引用来访问您的数据。显然,你可能在某些情况下,但这些不应该是常态。
如果您仍想构建自己的data
功能,那么这是一个示例。它没有优化,但你应该明白这个想法:
请注意,WeakMap仅在现代浏览器中可用,但如果没有它,我们就会泄漏内存,除非您提供一种机制来在关联的DOM元素被销毁时销毁缓存属性expenseo对象。 < / p>
JSPERF (测试可能不公平,因为我不确定我的实施是否完成$(...).data
var data = (function () {
var attributes = new WeakMap();
return function (el, attr, val) {
var elAttrs = attributes.get(el),
isSetOperation = arguments.length > 2;
if (isSetOperation) {
if (!elAttrs) attributes.set(el, elAttrs = {});
elAttrs[attr] = val;
} else {
return datasetOrCachedAttrsValue();
}
function datasetOrCachedAttrsValue() {
var attrVal = el.dataset[attr];
return typeof attrVal !== 'undefined'?
attrVal:
elAttrs && elAttrs[attr];
}
};
})();
var div = document.querySelector('div');
console.log(data(div, 'test')); //test
console.log(data(div, 'notexisting')); //undefined
data(div, 'exists', true);
console.log(data(div, 'exists')); //true
&#34;会泄漏内存,除非你提供一种破坏机制的机制 缓存&#34; - plalx 。即使使用WeakMap,它仍然会因为同样的原因而泄漏 jQuery可能会导致泄漏。见demo。 - dfsq
这是@dfsq的一个很好的关注点,但是 here's a demo 实际上显示了WeakMap如何在密钥无法访问时允许垃圾收集,而不是jQuery的实现。保持数据(除非使用$().remove
我相信)。
随着时间的推移使用探查器和记录堆分配并比较结果。这是我从每个按钮点击6次后得到的结果(每个快照有一种按钮)。我们可以清楚地看到$().data
在使用data
的自定义WeakMap
实施不会泄露时出现泄漏。
尝试与$().data
泄漏。
尝试泄漏数据