Javascript 将HTML元素放入原型链中?

Javascript 将HTML元素放入原型链中?,javascript,prototype,Javascript,Prototype,我想创建一个对象,通过将元素放入对象的原型链来扩展HTML元素的功能 我想我可以用以下方法来实现这一点: var el = document.createElement( "div" ); el.innerHTML = "foo"; var wrapper = Object.create( el ); alert( wrapper.innerHTML ); 上述方法不起作用,而以下方法起作用: var el = document.createElement( "div" ); el.inne

我想创建一个对象,通过将元素放入对象的原型链来扩展HTML元素的功能

我想我可以用以下方法来实现这一点:

var el = document.createElement( "div" );
el.innerHTML = "foo";

var wrapper = Object.create( el );
alert( wrapper.innerHTML );
上述方法不起作用,而以下方法起作用:

var el = document.createElement( "div" );
el.innerHTML = "foo";

var wrapper = Object.create( el );
alert( wrapper.__proto__.innerHTML );

似乎奇怪的是,为了找到给定的属性,必须显式地查看原型内部。

对象。create
使用指定的原型对象和属性创建一个新对象
el
没有任何自己的可枚举属性
,您可以检查

Object.keys( el ) ; //[]

因此,您需要将属性及其描述符一起传递给

var wrapper = Object.create( el, { "innerHTML" : { value: el.innerHTML } } );
演示

var el=document.createElement(“div”);
el.innerHTML=“foo”;
var wrapper=Object.create(el{
“innerHTML”:{
值:el.innerHTML
}
});

log(wrapper.innerHTML)它不起作用,因为您在一个非本机DOM元素且没有内部插槽的对象上使用了
.innerHTML
getter

我想创建一个对象,通过将元素放入对象的原型链来扩展HTML元素的功能

那是错误的方向。要扩展元素的功能,需要将自定义函数放在其原型链中,以便仍然对元素本身调用方法。您可以使用
Object.setPrototypeOf
,或者创建自己的ES6子
class
(可能的话)


但最好的解决方案是简单地在元素周围放置一个包装器对象。另请查看。

请不要弄乱主机对象,请参阅。此外,主机不需要实现主机对象的原型继承,因此您不能期望它们都会实现(即很长一段时间都没有实现)。在
元素
HTMLLevel
上创建包装器的目的是什么?你想通过这样做来实现什么?包装器的想法是可以的,但是将元素放在包装器的原型链上可能不是最好的方法。只需将其作为包装器的属性。@RobG谢谢您的评论。我从来没有遇到过“主机对象”这个术语,或者“主机不需要为主机对象实现原型继承”的想法。@RobG yeah注意到了这一点,并定义了一个getter而不是普通值。谢谢你指出。我的理解是,如果一个给定的属性不属于某个对象,它的原型链将被搜索。我不明白为什么在这里不会发生这种情况。@DavidNewberry因为innerHTML很可能是作为一个getter实现的,当wrapper.innerHTML“调用”时,getter中的这个就是包装器,而不是属性所在的对象。原型上的所有方法都是这样工作的,例如,
someObj.toString()
在someObj上工作,而不是Object.prototype(可以在那里找到toString方法)。是调用设置了这个值,它不是词法的。不过,我认为原型链是自动搜索的。所以在我的示例代码中,既然innerHTML不是wrapper的属性,为什么不自动搜索wrapper的原型对象(与普通JS对象通常发生的情况一样)?搜索原型链,找到
.innerHTML
getter就可以了。但是getter函数抱怨说
wrapper
不是DOM元素(就像
el
那样),它不知道如何从中获取html字符串。注意,它确实抛出了一个
非法调用
异常,而不是仅仅警告
未定义
@Bergi,但是getter函数会抱怨包装器不是DOM元素,但是
HTMLElement的包装器instanceof
返回true。@gurvinder372在原型链中可以找到
HTMLElement.prototype
(这就是
instanceof
检查的内容)。正如我在回答中所解释的,
包装器
没有使其成为dom元素的自定义内部插槽。@gurvinder372不,我不能。这种行为似乎在任何规范中都没有详细说明(不适用于标准中令人烦恼的缺失,但也适用于其他DOM属性)。但这只是EcmaScript中宿主对象通常的工作方式。
var wrapper = Object.create( el, { "innerHTML" : { value: el.innerHTML } } );