如何将自定义属性添加到 HTML 环境,该属性将默认为元素的每个新实例上的空对象

How can I add a custom attribute to an HTMLElement, that will default to an empty object on each new instance of the element?

本文关键字:新实例 实例 对象 元素 添加 自定义属性 HTML 环境 默认 属性      更新时间:2023-09-26

如果我在HTMLElement的原型中添加一个新属性,并将其默认值设置为' {} '(一个空对象(:

Object.defineProperty(HTMLElement.prototype, 'customObject', 
{ configurable: true, enumerable: true, writeable: true, value: {} });

现在我创建一个新div(这也是一个HTMLElement(:

var e = document.createElement('div');

我将一个属性分配给ecustomObject

e.customObject.prop = "bla";

如果我提醒它,我会看到所需的值:

alert(e.customObject.prop); // Displays 'bla'.

现在我创建一个新的、不同的div元素:

var d = document.createElement('div');

这个d现在应该有一个空的customObject属性,对吧?

但是,如果我提醒它:

alert (d.customObject.prop);

我得到这个意想不到的结果:

bla

怎么来了?当我创建一个新元素时,它不应该有一个HTMLElement.prototype的"空白"实例吗?

( JSFIDDLE: http://jsfiddle.net/5pgr38mb/(

编辑:我正在寻找一种适用于深度克隆的解决方案(克隆节点(true((。含义 - 如果自定义对象在元素或其任何子元素上具有属性,则该元素或子元素将在克隆实例中保留其值(这是"本机"HTMLElement 属性的正常行为(。

我可能会使用原型 getter,它在调用时在实例上创建新的对象属性:

Object.defineProperty(HTMLElement.prototype, 'customObject', {
    enumerable: true,
    get: function() {
        if(this.__thisCustomObject === undefined) {
            this.__thisCustomObject = {};
            // or non-enumerable with:
            //    Object.defineProperty(this, '__thisCustomObject', {
            //        enumerable: false,
            //        value: {}
            //    };
        }
        return this.__thisCustomObject;
    },
    set: function(val) {
        this.__thisCustomObject = val;
    }
});

这样,每次您第一次请求对对象进行customObject时,它都会创建一个新对象并将其存储在该对象的 __thisCustomObject 属性中。然后,所有将来的customObject请求都使用该元素的__thisCustomObject属性。

请注意,这是 getter-setter 模式,非常接近 Web IDL 规范中实际每个元素 DOM 属性的实现方式。这里唯一的区别是每个元素的值存储在属性中,而不是隐藏映射中。

您可以覆盖document.createElement函数。只需打开控制台(大多数浏览器中为 F12(,然后单击"运行"即可查看此代码的结果。

document.createElement = (function () {
    var reference = document.createElement;
    return function (name) {
        var e = reference.call(document, name);
        e.customObject = {
            configurable: true,
            enumerable: true,
            writeable: true,
            value: {}
        };
        return e;
    };
}());
var e = document.createElement('div');
e.customObject.prop = "bla";
console.log(e.customObject.prop);
var d = document.createElement('div');
console.log(d.customObject.prop);