0

我正在尝试更多地了解 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实际上是更正确的方法吗?如果是这样,它应该如何设置才能正常工作?

提前感谢您的帮助!!!

4

1 回答 1

0

这些例子都不是“正确的”。在原型方法中,您不应该尝试实例化您已经附加到的对象的新副本。您需要做的就是:

HTMLElement.prototype.bar = function() {
    let div = document.createElement('div');
    div.innerHTML = 'fooRenderer';
    this.appendChild(div);
}

第一个示例之所以有效,是因为foo.parentElement它将是一个有效的原生 HTMLElement,而不是自定义创建的对象。

请参阅此答案,了解为什么您不能像appendChild在自定义对象上调用“本机”浏览器方法。

于 2016-10-31T18:47:10.143 回答