我能否向DOM对象添加任意属性?

65

我可以给JavaScript DOM对象添加任意属性吗?例如,<INPUT><SELECT>元素?如果不能添加属性,那么是否有一种方式可以通过引用属性将我的对象与网页元素关联起来?

7个回答

47

ECMAScript 6引入了WeakMap,它允许您将私有数据与DOM元素(或任何其他对象)相关联,只要该对象存在。

const wm = new WeakMap();
el = document.getElementById("myelement");
wm.set(el, "my value");
console.log(wm.get(el)); // "my value"
与其他答案不同,这种方法保证永远不会与任何属性或数据的名称冲突。

与其他答案不同,这种方法保证永远不会与任何属性或数据的名称冲突。


1
但这是否意味着您必须始终保持wm引用?似乎有点限制。 - Julian Knight
你不想维护那个wm引用吗?如果你更喜欢使用像setArbitraryValueTo(el,value)或getArbitraryValueFrom(el)这样的实用函数,就没有必要暴露它。 - Salketer

32

是的,您可以将自己的属性添加到DOM对象中,但请注意避免命名冲突和循环引用。

document.getElementById("myElement").myProperty = "my value";

HTML5 引入了一种通过标记附加数据到元素的有效方式 - 使用 data- 属性前缀。你也可以在 HTML 4 文档中使用此方法,但它们将无法通过验证。

<div id="myElement" data-myproperty="my value"></div>

你可以使用JavaScript通过getAttribute()访问它:

document.getElementById("myElement").getAttribute("data-myproperty");

1
那最后一行应该是 setAttribute() 吗? - alex
1
@alex:不,还是犯了一个错误 :-) - Andy E
18
data-属性只能存储字符串(或可序列化/反序列化为字符串的对象),而不能存储一般运行时对象,而在DOM对象上设置新属性则可以。 - Triynko
1
循环引用的问题到底是什么?一个对象A引用了一个对象B,而对象B又引用了A本身,在一般情况下并不是问题,那么在DOM元素附加任意属性的情况下必须避免的情况是什么? - matteo
@matteo 循环引用可能导致内存泄漏。 https://dev59.com/kWs05IYBdhLWcg3wQvuq - Yay295
2
@matteo - 回到2010年,当Andy写下这个答案时,Internet Explorer存在一个问题,即DOM元素在任意属性上引用JavaScript对象。但是这个问题已经在IE的后续版本中得到了解决,因此循环引用的问题不再是一个问题。 - T.J. Crowder

27

当然,人们已经做了很多年了。不建议这样做,因为它会很混乱,而且您可能会干扰现有的属性。

如果您使用 for..in 循环代码,则可能会导致代码中断,因为您现在将枚举这些新附加的属性。

我建议使用类似于jQuery的 .data 的内容,将元数据附加到对象上。如果您不想使用库,请重新实现 jQuery.data


酷啊... data 是被 jQuery 自身使用的,还是我可以自由地给它分配任何值? - Tony the Pony
1
$.data 是由 jQuery 定义的。您可以像这样使用它 $('#el').data('key', 'value') - meder omuraliev
1
设置值使用 $(element).data('name', value),读取值使用 $(element).data('name') - gen_Eric
1
我假设你知道如何使用手动DOM的方式完成它,el['data-foo'] = 'value'; - meder omuraliev
1
如果您决定不使用$.data,在IE中使用getAttributesetAttribute存在错误/不一致性,请在属性前加上data-前缀。 - meder omuraliev
2
如果有一个额外的属性,for...in循环会如何中断? - Hugh Guiney

7
你想给对象添加属性,还是给元素添加属性?
你可以使用setAttribute来添加属性。
var el = document.getElementById('myelement');
el.setAttribute('custom', 'value');

或者您可以直接向JavaScript对象添加属性:
var el = document.getElementById('myelement');
el.myProperty = 'myValue';

如果有人忘记了属性和特性之间的区别 -> 快速链接 https://dev59.com/32025IYBdhLWcg3wcli-#6004028 - wlf

6

如果有人在2015年想知道,是的,你可以这样做 - 并且 jQuery正在data中采取这种做法。只需要选择符合未来标准的名称,例如供应商前缀或基于时间的随机后缀(jQuery)即可。


1
但是jQuery使用了一个内部缓存来保存数据,数据并没有保存在DOM元素本身中。请参见:https://dev59.com/D2w05IYBdhLWcg3wfyA0 - RiZKiT
1
你链接到了 jQuery 的主分支。由于主分支会发生变化,请考虑链接到特定的版本。 - Michael Franzl

2

2
我正在探索答案,没有一个提到在现代JavaScript中我们可以使用dataset属性在domElements上设置属性,它可以在HTMLOrForeignElement上使用(这是几个特性的混合体,常见于HTMLElementSVGElementMathMLElement接口)
根据MDN

HTMLOrForeignElement接口上的dataset属性提供对元素上设置的所有自定义数据属性(data-*)的读/写访问。此访问在HTML和DOM内部都可用。它是一个DOMStrings映射,每个自定义数据属性都有一个条目。

let element = document.getElementById("test");
let footer = document.querySelector("#output");

/* get element values using camelCase names through .dataset */
let sample = element.dataset.sample;
let sampleNumber = element.dataset.sampleNumber;

let dataFromElement = sample + " :: " + sampleNumber;

footer.innerHTML = element.innerHTML  + dataFromElement;
<input type="hidden" id="test" data-sample="Sample" data-sample-number=34 />
<div id="output"> </div>

虽然有人对Internet Explorer的支持和性能表示担忧,但您可以在这里检查:此处


1
问题在于数据集属性只是属性,因此传递对象会导致其被压缩为[object Object] - Julian Knight

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