如何向HTMLElement添加自定义属性,该属性默认为元素的每个新实例上的空对象?

时间:2014-12-05 18:49:14

标签: javascript defineproperty

如果我将新属性添加到HTMLElement的原型中,并将其默认值设置为“{}”(空对象):

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

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

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

我将属性分配给customObject的{​​{1}}:

e

如果我发出警告,我会看到所需的值:

e.customObject.prop = "bla";

现在我创建一个新的,不同的alert(e.customObject.prop); // Displays 'bla'. 元素:

div

var d = document.createElement('div'); 现在应该有一个空的d属性,对吗?

但是,如果我提醒它:

customObject

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

alert (d.customObject.prop);

为什么?当我创建一个新元素时,它不应该有一个HTMLElement.prototype的“空白”实例吗?

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

修改 我正在寻找使用深度克隆(cloneNode(true))的解决方案。 含义 - 如果自定义对象在元素 或其任何子元素 上具有属性,则该元素或子元素将在克隆实例中保留其值(这是正常行为“native”HTMLElement属性)。

2 个答案:

答案 0 :(得分:3)

我可能会使用一个原型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模式非常接近how actual per-element DOM properties are implemented in the Web IDL specification。这里唯一的区别是每个元素的值存储在一个属性中,而不是隐藏的映射。

答案 1 :(得分:1)

您可以覆盖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);