我正在尝试更多地了解Javascript并深入了解原型链。当我遇到这个问题时,我想为HTMLElement创建一个小扩展。
我理解Object.create
的方式是传递给它的对象用于为新对象创建上下文,并且新创建的对象的原型链中的第一个链接将指向该对象传递给Object.create
方法。既然如此,下面的bar
方法中使用的扩展方法对我来说似乎是正确的方法,因为这个新创建的对象将被赋予其HTMLElement作为其上下文。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<span id="test"></span>
<script>
HTMLElement.prototype.foo = function() {
let foo = Object.create(null);
foo.parentElement = this;
foo.parentElement.appendChild(document.createElement('div'));
}
HTMLElement.prototype.bar = function() {
let fooRenderer = Object.create(this);
fooRenderer.appendChild(document.createElement('div'));
}
document.getElementById('test').foo();
document.getElementById('test').bar();
</script>
</body>
</html>
但是,foo
方法可以通过将新的div
子元素附加到<span id="test"></span>
来正常工作,但bar
却没有。
当我在浏览器中打开开发人员工具并尝试跟踪调用appendChild
的两个对象的原型链时,它们看起来几乎相同:
foo Object
.parentElement <span#test2>
.__proto__ HTMLSpanElementPrototype
.__proto__ HTMLElementPrototype
.__proto__ ElementPrototype
.__proto__ NodePrototype
.appendChild
.__proto__ EventTargetPrototype
.__proto__ Object
.__proto__
get
set
fooRenderer Object
.__proto__ <span#test2>
.__proto__ HTMLSpanElementPrototype
.__proto__ HTMLElementPrototype
.__proto__ ElementPrototype
.__proto__ NodePrototype
.appendChild
.__proto__ EventTargetPrototype
.__proto__ Object
.__proto__
get
set
我已使用此示例创建了jsFiddle。
有人可以向我解释为什么bar
无效吗? bar
实际上是更正确的方法吗?如果是这样,应如何设置才能正常工作?
提前感谢您的帮助!!!
答案 0 :(得分:0)
这两个例子都不“正确”。在原型方法中,您不应该尝试实例化已经附加到的对象的新副本。您需要做的就是:
HTMLElement.prototype.bar = function() {
let div = document.createElement('div');
div.innerHTML = 'fooRenderer';
this.appendChild(div);
}
第一个示例仅起作用,因为foo.parentElement
将是有效的本机HTMLElement,而不是自定义创建的对象。
请参阅this answer,了解为何无法在自定义对象上调用appendChild
等“原生”浏览器方法。