【问题标题】:Can I add arbitrary properties to DOM objects?我可以向 DOM 对象添加任意属性吗?
【发布时间】:2011-05-14 14:16:24
【问题描述】:

我可以向 JavaScript DOM 对象添加任意属性,例如 <INPUT><SELECT> 元素吗?或者,如果我不能这样做,有没有办法通过引用属性将我自己的对象与页面元素相关联?

【问题讨论】:

    标签: javascript dom


    【解决方案1】:

    ECMAScript 6 具有 WeakMap,只要该对象存在,您就可以将私有数据与 DOM 元素(或任何其他对象)相关联。

    const wm = new WeakMap();
    el = document.getElementById("myelement");
    wm.set(el, "my value");
    console.log(wm.get(el)); // "my value"
    

    与其他答案不同,此方法保证不会与任何属性或数据的名称发生冲突。

    【讨论】:

      【解决方案2】:

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

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

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

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

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

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

      【讨论】:

      • 最后一行应该是setAttribute()吗?
      • @alex: 不,还是犯了一个错误:-)
      • 数据属性只能存储字符串(或可序列化/可反序列化到/从字符串的对象),不能存储一般的运行时对象,而在 dom 对象上设置新属性可以。
      • 循环引用到底有什么问题?对象 A 对对象 B 的引用,对象 B 对 A 的引用通常不是问题,那么在 DOM 元素附加任意属性的情况下必须避免的情况是什么?
      • @matteo - 早在 2010 年,当 Andy 写这个答案时,Internet Explorer 中存在一个问题,即 DOM 元素在任意属性上引用了 JavaScript 对象。但这在 IE 的更高版本中已修复,因此循环引用不再是问题。
      【解决方案3】:

      当然,人们已经这样做了很久了。不建议这样做,因为它很乱,您可能会弄乱现有属性。

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

      我建议使用像 jQuery 的 .data 这样的东西,它可以将元数据附加到对象上。如果不想使用库,重新实现jQuery.data

      【讨论】:

      • $.data 由 jQuery 定义。您可以像 $('#el').data('key', 'value') 一样使用它。
      • 设置值是$(element).data('name', value),读取是$(element).data('name')
      • 我假设你知道如何使用手动 DOM 方式,el['data-foo'] = 'value';
      • 如果您不决定使用$.data,则IE 中的getAttributesetAttribute 存在错误/不一致,请在属性前加上data-
      • for...in 循环如何仅因拥有额外的属性而中断?
      【解决方案4】:

      您想为对象添加属性,还是为元素添加属性?

      您可以使用setAttribute添加属性

      var el = document.getElementById('myelement');
      el.setAttribute('custom', 'value');
      

      或者您可以只向 javascript 对象添加属性:

      var el = document.getElementById('myelement');
      el.myProperty = 'myValue';
      

      【讨论】:

      • 如果有人忘记了属性和属性的区别->快速链接*.com/a/6004028
      【解决方案5】:

      如果有人在 2015 年想知道,是的,你可以 - 并且 jQuery 在 data 中就是这样做的。只需选择面向未来的名称,例如供应商前缀或基于时间的随机后缀 (jQuery)。

      【讨论】:

      • 但是 jQuery 使用内部缓存来保存数据,数据不会保存在 DOM 元素本身中。另见:*.com/questions/7200722/jquery-expando-properties
      • 你链接到了 jQuery 的 master 分支。由于主分支发生变化,请考虑链接到特定版本。
      【解决方案6】:

      如果必须,不要使用标准的 HTML 属性。下面是使用自定义属性的教程:

      http://www.javascriptkit.com/dhtmltutors/customattributes.shtml

      它是 HTML5,但它是向后兼容的。

      【讨论】:

        【解决方案7】:

        我正在探索答案,没有人提到在现代 JavaScript 中,我们可以使用 dataset 属性在 domElements 上设置属性,它可以在 HTMLOrForeignElement 上使用 (这是@ 987654326@、SVGElementMathMLElement 接口)

        根据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 的支持和性能存在疑虑,但您可以查看here

        【讨论】: