序文
SegmentFaultでこのような質問を見ました:
var f = function(){}; object.prototype.a = function(){}; function.prototype.b = function(){}; var f = new f();Q:fはaとbを取得できますか?原則は何ですか?
一見、私は本当に混乱していました。慎重な研究の後、私はまだプロトタイプを完全に理解していないことがわかったので、それを要約して穴に埋めました〜
関数とオブジェクト
問題を解決する前に、プロトタイプ、プロトタイプチェーン、機能とオブジェクトの関係について話しましょう。これもこの記事の焦点です。
プロトタイプ
関数を作成すると、プロトタイプオブジェクトが自動的に作成され、関数のプロトタイププロパティを介してアクセスできます。
コンストラクターのインスタンスオブジェクトを作成します。コンストラクタ内にポインター(内部プロパティ)が含まれ、コンストラクターのプロトタイプオブジェクトを指します。 ECMA-262このポインターの第5版は[[プロトタイプ]]と呼ばれます。スクリプトに[[プロトタイプ]]にアクセスする標準的な方法はありませんが、Firefox、Safari、およびChromeは、各オブジェクトのプロパティ__Proto__をサポートして、コンストラクターのプロトタイプオブジェクトにアクセスします。
もう一度重要なことを言わせてください:
コンストラクターは、プロトタイププロパティを介してプロトタイプオブジェクトにアクセスします。
インスタンスオブジェクトは、[[[プロトタイプ]]内部属性を介してプロトタイプオブジェクトにアクセスし、ブラウザはインスタンスオブジェクトの_Proto_属性を実装してプロトタイプオブジェクトにアクセスします。
var f = function(){}; var f = new f(); // fのプロトタイプオブジェクトはp、// f.prototype === p; // f .__ proto__ === p;もう一度繰り返します。 。プロトタイプとは、コンストラクターとプロトタイプオブジェクトの関係を指し、__Proto__はインスタンスオブジェクトとプロトタイプオブジェクトの関係を指します。
プロトタイプチェーン
クラスAはB、B、BはCを継承します...実際、AのプロトタイプオブジェクトにBを指すポインターを持つプロトタイプオブジェクトと、プロトタイプオブジェクトにCを指すポインターを持つプロトタイプオブジェクトがあります...それはプロトタイプオブジェクト間の接続であることに注意してください。 ABCの3つのコンストラクター間に関係はないため、「プロトタイプチェーン」と呼ばれます〜
AがAのインスタンスオブジェクトであると仮定すると、Aのプロトタイプチェーンが下の図の紫色の線に示されており、オレンジ線はコンストラクターとそのプロトタイプオブジェクトを接続します。
図からわかるように、プロトタイプチェーンの終わりはobject.prototype .__ proto__、つまりnullです。 Aのプロパティまたは方法を探しているときは、最初にそれ自体が持っているかどうかを探します。そうでない場合は、プロトタイプチェーンが見つかるまで検索するか、最終的にNULL後に定義されていないように戻します。
関数とオブジェクト
関数とオブジェクトの関係は少しもつれです:
オブジェクトはコンストラクターです。関数であるため、関数のインスタンスオブジェクトです。関数はコンストラクターですが、function.prototypeはオブジェクトです。オブジェクトであるため、オブジェクトのインスタンスオブジェクトです。
すべてのオブジェクトはオブジェクトのインスタンスであり、すべての関数は関数のインスタンスです。
オブジェクトは機能のインスタンスであり、function.prototypeはオブジェクトのインスタンスです。
2つの間の関係を下の図に示します。
コンストラクターとしてのオブジェクトが見られるように、Object.prototypeを指すプロトタイプ属性があり、インスタンスオブジェクトとして、function.prototypeを指すObject .__ proto__があります。関数はコンストラクターであり、function.prototypeと関数は関数であり、関数のインスタンスでもあるため、プロトタイプ属性を備えているため、function.__ proto__ function.prototypeを指すため、機能.__ proto__ === function.prototypeは真です。
図に示すように、Chromeコンソールの下で検証できます。
元の質問の分析
プロトタイプチェーンの問題を解決する最良の方法は、絵を描くことです。以前の分析の後、この写真は次のように問題ではないはずです〜
Fのプロトタイプチェーンは青い線で描画されるため、FはAにアクセスできますが、Bはアクセスできません。
一見絵を描かない場合、Fはbにアクセスできると思われるかもしれません。 f.prototypeがfunction.prototypeを指していることは私のようなものかもしれませんが、実際、f。プロトタイプは関数ではなくオブジェクトであるため、そのプロトタイプオブジェクトはfunction.prototypeではありません。
したがって、プロトタイプチェーンの問題がいつでも絵を描く必要があります〜
拡張トピック
上記の質問では、fはaにのみアクセスできますが、b。ただし、fはaとbの両方にアクセスできます。質問を以下に変更すると、FB()の結果は何ですか?なぜ?あなたはそれについて考えることができます〜
var f = function(){}; object.prototype.a = function(){}; function.prototype.b = function(){console.log( 'f .__ proto__')}; f.prototype.b = function(){console.log( 'f.prototype');};};要約します
これを読んだ後、関数の特別な機能を見つけましたか?
一般的なオブジェクトの場合、コンストラクターのプロトタイプオブジェクトにアクセスするために使用される__Proto__属性は1つだけで、関数の場合、それは関数とオブジェクトの両方です。
関数として、それはそのプロトタイプオブジェクト関数name.prototypeを指すプロトタイプ属性で生まれます。
functionのインスタンスオブジェクトとして、function.prototypeを指す__proto__属性があります
通常、これらの2つのプロパティは2つのオブジェクトを指しますが、関数の両方のプロパティが同じものを指し、両方ともfunction.prototypeを指します。
関数a()の場合、A.prototypeのメソッドはインスタンスオブジェクトへの呼び出し用であり、単独では使用されません。 aがインスタンスとして実行されると、.__ proto__のメソッドが呼び出されます。言い換えれば、コンストラクターとして使用すると、A.Prototypeチェーンが採取され、方法と属性が例に割り当てられます。オブジェクトとして使用すると、a .__ proto__チェーンが使用されます。さまざまなシナリオでは、そのアイデンティティを区別することは間違っていません。
記事全体の後、私が言ったことは非常にしつこいと感じています...欠点があれば私を修正してください〜質問に関しては、私はそれを何と呼ぶべきか本当にわかりません。 。
この記事が読んだ後にいくつかの利益をもたらしますように〜 ^_ ^
このウェブサイトへのご支援ありがとうございます。私たちは、あなたが知識のこの部分を学び、理解するのを助けるために、将来の関連情報を引き続き更新します!