为什么HTMLElement原型与所有实例共享属性,而不是为每个元素创建副本?

时间:2019-06-08 14:26:12

标签: javascript dom

我正在使用HTMLElement.prototype,因为我想将自定义属性添加到要使用的元素中。例如,我正在建立一个存储,该存储将保存properties:与THIS元素相关的值键。

问题在于,在HTMLElement.prototype上设置属性会与所有实例共享这些属性,这是非常错误的。

HTMLElement.prototype.storage = {};
HTMLElement.prototype.store = function(prop, val) {
  this.storage[prop] = val;
}
HTMLElement.prototype.retrieve = function(prop) {
  return this.storage[prop];
}

window.onload = function() {
  var box = document.getElementById("box");
  var box2 = document.getElementById("box2");

  box.store("a", "a value");
  console.log(
    box2.retrieve("a")
  );
}

我希望box2元素在他的存储中不具有“ a”属性,因为我没有为THIS元素设置它。我将其设置为box元素。

1 个答案:

答案 0 :(得分:2)

存储属性是在HTMLElement的原型上定义的,其定义为«seen by all objects through prototype chaining»

您可以在HTMLElement原型上定义一个store(prop, val): void方法,通常每个实例的属性都在 constructor 函数中定义。

在这种情况下,您正在处理内置的 constructor 函数,因此无法在其中添加属性。一种简单的替代方法是在store方法中定义storage属性(如果尚不存在),该属性将为调用方法 store 的元素添加

HTMLElement.prototype.store = function (key, val) {
 if (!this.storage) {
   this.storage = {};
 }
 this.storage[key] = val;
}

HTMLElement.prototype.getFromStore = function (key) {
 return this.storage ? this.storage[key] : undefined;
}

document.getElementById('one').store('test', 1);
document.getElementById('two').store('test', 2);

// Display stored values for each div element
document.body.innerHTML = Array.prototype.slice.call(document.querySelectorAll('div'), 0).map((el) => `${el.id}: ${el.getFromStore('test')}`).join(',');
<div id="one"></div>
<div id="two"></div>

HTMLElement.prototype.store = function(prop, val) {
    if (!this._storage) {
        this._storage = {};
    }
    this.storage[prop] = val;
}