( は から続きます) まず、ベテランにとっては目新しいものではありませんが、初心者にとっては非常に興味深い写真を見てみましょう:
それは一体何ですか?それはただのルンルンです。
新しい
上の図はさておき、前の記事で残った 2 番目の質問を見てみましょう。コンストラクターの関数本体に何かを追加して、何が起こるかを見てみましょう。
<div> <!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000"> A(){</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.p </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">}<br></span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> a </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> A()</span> </div>
次の結果が得られます:
new キーワードで構築された a が属性 p を取得するのはなぜですか?コードの新しい A() 行は何をするのでしょうか?前回の記事の関数作成プロセスのステップ 4 によると、オブジェクト A は Construct 属性を持ちます (コンストラクターではないことに注意してください。Consturct は ECMAScript 標準の属性であり、外部には見えないようです)。この属性の値が関数の場合、 new A( ) は A の Construct 関数を呼び出します。では、この Construct 関数は何をするのでしょうか?
1. x という名前のオブジェクトを作成します。
2. A.prototype がオブジェクトの場合 (通常はオブジェクトです)、A.prototype を x.__proto__ に割り当てます。それ以外の場合 (一般的ではありません)、ビッグボス オブジェクトにアクションを実行して Object.prototype を x.__proto__ に割り当てます。
3. A.call(x) を呼び出し、作成したばかりの x を最初のパラメーターとして渡します。以上です、A の関数本体の this.p = 1、これ this が x になります。したがって、x は属性 p を持ち、x.p = 1 になります。
4. 通常の状況では x が返されますが、このとき a は x です。ただし、特殊なケースがあります。A の関数本体が何かを返す場合、その型 (typeof) はオブジェクトです。この場合、a は x を指すのではなく、A 関数が返すものを指します。
疑似コードは次のとおりです:
<div> <!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> x </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Object(); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">事实上不一定用new来创建,我也不清楚。</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">x.__proto__ </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> A.prototype <br></span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> result </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> A.call(x)<br></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (</span><span style="COLOR: #0000ff">typeof</span><span style="COLOR: #000000">(result) </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">object</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">){<br> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> result;<br>}<br></span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> x;<br></span> </div>
この例では、A 関数は未定義を返します (戻り値がないため)。したがって、a は x です。ただし、上記のステップ 4 の特殊な状況を検証する例を見てみましょう:
確かにそうです。
オブジェクトのコンストラクタープロパティ
前の記事に残っている最初の質問を見てください
<div> <span>function</span><span> Base(){}<br>Base.prototype.a </span><span>=</span><span> </span><span>1</span><span><br></span><span>var</span><span> base </span><span>=</span><span> </span><span>new</span><span> Base();<br><br></span><span>function</span><span> Derived(){}<br>Derived.prototype </span><span>=</span><span> base;<br></span><span>var</span><span> d </span><span>=</span><span> </span><span>new</span><span> Derived()</span> </div>
上記のコードを実行すると、mybase.constructor が Base であることは容易に推測できますが、d.constructor はどうでしょうか?派生ですか?
いいえ、それもBaseです、何が起こっているのですか?前の記事の内容を確認すると、これは非常に簡単であることがわかります。 d 自体にはコンストラクター属性がないため、d.__proto__ にアクセスして、これを見つけます。これは Derived.prototype です。オブジェクトbase、baseにはコンストラクター属性がないので、base.__proto__、つまりBase.prototypeを探します。これには Base 自体であるコンストラクター属性があります。実際、私がこれまでに知っている限り、コンストラクターのプロトタイプ(関数型オブジェクト)だけが実際にコンストラクター属性を持つ独自のオブジェクトを持ち、「constructor.prototype.constructor === コンストラクター」となっています。
のインスタンス
それでは、instanceof はどうでしょうか?
図から分かるように、d は Base、Derived、Object のインスタンスです。非常に合理的ですが、これをどう判断すればよいでしょうか?これは次のようになります。 x インスタンスオブコンストラクターの式の場合、constructor.prototype が x のプロトタイプ (__proto__) チェーン内にある場合、true が返されます。明らかに、d の __proto__ チェーンは、 Derived.prototype、Base.prototype、Object.prototype となり、図の結果が得られることは間違いありません。したがって、instanceof はオブジェクトのコンストラクター プロパティとは何の関係もありません。
関数とオブジェクト
最後に、記事冒頭の写真について答えさせてください。
Function と Object 自体も関数型オブジェクトなので、両方とも Function() によって構築されると言えます (自分で構築します。これが事実かどうかはわかりませんが、考えるのはかなり合理的です)そう。)
言い換えると、次のコードを想像できます:
<div> <!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> Function </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Function()<br></span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000"> Object </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Function() </span> </div>
前の記事のルールによれば、Function.__proto__ === Function.prototype と Object.__proto__ === Function.prototype が存在します。それを確認してください:
オブジェクトの関数インスタンス、これは明らかに当てはまります。関数の __proto__ チェーンは Function.prototype、Object.prototype を指します。
Function のオブジェクト インスタンス。Function.prototype は Object の __proto__ チェーン内にあるため、これも当てはまります。