2016-10-31 16 views
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方法は<span id="test"></span>に新しいdiv子要素を追加することで正常に動作しますが、barないということです。

私は私のブラウザで開発ツールを開いて、その上で呼び出さappendChildを持っている2つのオブジェクトのプロトタイプチェーンを追跡しようとすると、彼らはほとんど同じに見える:

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はより正しいアプローチですか?もしそうなら、どのように正しく動作するようにセットアップする必要がありますか?

ご協力いただきありがとうございます!

+1

プロトタイプチェーンに 'HTMLSpanElement'がありますが、' fooRenderer'オブジェクトは単なるオブジェクトであり、実際のDOMノードではありません。 – Bergi

+0

@Bergiありがとうございますが、私はあなたが何を言っているのか分かりません。あなたはjavascriptが実際にプロトタイプチェーンをたどって 'appendChild'メソッドを見つけるのですが、その時点でDOMノードではなくオブジェクト上で実行されているので、実行できません。 – peinearydevelopment

+1

はい、まさにそのようなことを述べているエラーが発生しているはずです。ノードメソッドを継承するが、ノードとして初期化されていない(ネイティブ* DOMノードオブジェクトでもない)オブジェクトで呼び出されるように試みられます。 – Bergi

答えて

0

どちらの例も「正しい」ものではありません。プロトタイプのメソッドでは、すでに接続しているオブジェクトの新しいコピーをインスタンス化しようとしてはいけません。

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

foo.parentElementはないカスタム作成されたオブジェクトは、有効な、ネイティブのHTMLElementになりますので、最初の例にのみ動作します:あなたがする必要があるのはこれです。

カスタムオブジェクトでappendChildのような "ネイティブ"ブラウザメソッドを呼び出せない理由については、this answerを参照してください。

+0

私の質問は、私が何を得ようとしているかを完全には問いませんでした。私はあなたが言っていることを理解しています。私は将来のDOM操作のための参照を維持できるオブジェクトを作成しようとしています。あなたの例では、最後に「返す」か、DOMノードへの参照を保持して返すプロパティを持つ関数でオブジェクトを作成して返しますか? ありがとう! – peinearydevelopment

関連する問題