JavaScript DOM:设置自定义DOM元素属性

28

在DOM元素上设置自定义属性,然后依赖于它们的持久性,这样做是否可以?

例如,给定:

 <html><body><div id="foo"></div></body></html>

document.getElementById('foo').bar = "baz";,并期望 document.getElementsByTagName('div')[0].bar 等于 "baz",这样做公平吗?请注意,我谈论的是一般JavaScript对象属性,而不是元素属性。我对它的跨浏览器兼容性和是否受任何规范支持感兴趣。DOM API是否保证每次都返回相同的JavaScript对象以表示相同的DOM元素?


1
你可以设置自定义属性,但不要依赖它们。它们可能会成为标准属性,并与你的代码冲突。最好使用jQuery/MooTools提供的元素存储系统(.data()等)。 - Marc B
1
“DOM API是否保证每次返回相同的JavaScript对象来表示相同的DOM元素?”我不理解这个问题。DOM元素是宿主对象,而不是“JavaScript对象”(正式称为本地对象)。 - Šime Vidas
1
@rampion 节点由其Node对象表示。只要您引用相同的节点,就会获得相同的对象。如果您成功在Node对象上定义了新属性,则应该能够稍后检索其值。 - Šime Vidas
1
这个问题非常技术性,因此在选择词汇时需要非常小心。什么是“DOM元素”?为什么(何时)会“返回”JavaScript对象?有什么区别?而且,“语义节点”到底是什么鬼? - user123444555621
1
可能是 Can I add arbitrary properties to DOM objects? 的重复问题。 - Lightness Races in Orbit
显示剩余5条评论
4个回答

7
作为一般规则,不要使用自定义属性。您不应以DOM对象未预期的方式进行修改,因为它们可能不会像您想象的那样运行。 在HTML5中,自定义属性的机制是使用data-前缀。 但是,HTML5不是标准,并且尚未得到广泛实施。但是,如果您对data-属性使用set/getAttribute,它应该可以在所有合理现代浏览器上使用,在未来也不会引入任何具有data-前缀的标准属性。 但是话虽如此,我仍然建议使用自定义对象存储值,并通过元素idclass或其他某些标准(如HTML 4.01)属性值进行引用。它避免了自定义属性和属性的问题,并被知晓可在任何地方使用。

有人能检查一下这个答案是否仍然准确吗?特别是这句话:“HTML5不是一个标准,而且还没有被广泛实现。” - Mountain Scott
@MountainScott - 根据 HTML Living Standard:'“HTML5”这个术语被广泛用作指代现代Web技术的流行词汇'. 在2011年,它并没有得到广泛应用。10年后,情况有所不同。 :-) - RobG
如果现在情况有所不同,你应该更新答案吗?使用data属性的建议仍然存在吗?我没有注意到在JavaScript教程中使用它会有任何犹豫,因此希望能够得到一些明确的解释。 - Mountain Scott
@MountainScott - 回答应该在它们编写时的上下文中考虑。不现实指望答案为每个与Web技术相关的更改进行更新。高度活跃的答案通常由社区更新,我认为这个答案不属于那个篮子。 :-) - RobG
不一定。在这个平台上,作者经常更新和编辑他们的回答。问题的背景是持久的,而回答并非如此。没有人强迫你改变,但这似乎是明智的选择。 - Mountain Scott
作者提到了HTMLElements的属性,而不是特性! - Velaro

6

我们能在IE中使用shim吗?有没有尝试过使用shim? - Raynos
我认为这是一个好的解决方案,如果数据集不存在,只需将其定义为自定义属性即可。 - Ibu
数据集只能包含字符串值,因为它是DOM和数据属性之间的桥梁。这很好,但不足以存储连接到DOM元素的任意数据。 - Strider
这个代码是可以运行的,但是奇怪的是,如果我设置例如myobj.dataset.changed=true或false,它似乎不像布尔值一样工作,!myobj.dataset.changed总是返回false而不是被反转!那么这是什么鬼? - McVitas

1

不行。

假设5年前,您认为属性.contains是用于判断元素是否包含某些特殊数据的好用例。

因此,您编写了document.getElementById("someId").contains = true

然后您进行了检查,例如if (document.getElementByID("someId").contains)

今天这个代码会出错,因为Node.prototype.contains是一个方法。

基本上,您的代码不具备未来安全性。


2
点已经被接受。我仍然很好奇它是否是现在安全的(即,如果浏览器不支持持久化自定义属性,它是否会违反与程序员的合同)。 - rampion
@rampion 我个人不知道任何会中断的实现。 - Raynos
1
虽然我猜他可以相当安全地使用 elem.data_containselem.dlkafh - oriadam
1
前缀可以解决这个问题(例如,即使DOM规范最终切换到snake_case的可能性非常小,但您的代码很可能会因为其他原因而出现错误)。如果前缀不好,符号完全解决了冲突问题。 - Strider

1

这是规范中关于内部属性访问器的说明:

主机对象可以以任何方式实现这些内部方法,除非另有规定;例如,特定主机对象的[[Get]]和[[Put]]确实获取和存储属性值,但[[HasProperty]]始终生成false是一种可能性。

主机对象可以对[[Put]]操作定义附加约束。如果可能,主机对象不应允许在[[CanPut]]返回false的情况下进行[[Put]]操作。

然而,我认为这只是理论上的,实际上扩展属性按预期工作。


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