JSでプロトタイプを理解するには、まず次の概念を理解する必要があります
1。JSのすべてはオブジェクトです
2。JSのすべてはオブジェクトから派生しています。つまり、すべてのもののプロトタイプチェーンのエンドポイントはObject.prototypeにポイントを指します
// ["constructor"、 "tostring"、 "tolocalestring"、 "value of"、 "hasownproperty"、 "isprototypeof"、// "apportiseNumerable"、 "__definegetter__"、 "__lookupgetter__"、 "__defineetter__ console.log(object.getownPropertynames(object.prototype));
3. JSのコンストラクターとインスタンス(オブジェクト)の間の微妙な関係
コンストラクターは、インスタンスの仕様に同意するプロトタイプを定義し、新しいものを通じてインスタンスを構築します。それらの機能は、オブジェクトを生成することです。
コンストラクター(メソッド)自体はメソッド(関数)のインスタンスであるため、__proto __(Protochain)のためにも見つけることができます。
オブジェクト /関数f(){}これはコンストラクターであり、1つはJSネイティブAPIによって提供され、もう1つはカスタマイズされています
新しいオブジェクト() /新しいf()はインスタンスです
例は、「に基づいて作成されているプロトタイプ」を見つけるために、「のみ」のみ表示できます。
「できない」プロトタイプは、インスタンスを再定義し、インスタンスのインスタンスを作成するためにそれ自体を欺く。
真の知識を生み出すために練習し、自分自身を観察/考えることによってのみ、あなたは本当に理解できます:
//最初にコンストラクターが何であるかを見てみましょう// object {} function empty(){} console.log(object.prototype、object .__ proto__);関数f(){} // f {} function empty(){} console.log(f.prototype、f .__ proto__);あなたはめまいかもしれません、それを分解しましょう。
プロトタイプ
プロトタイプ出力の形式は次のとおりです。コンストラクター名プロトタイプ
まず、どのobject.prototype出力を見てみましょう。
オブジェクト{} - >前のオブジェクトはコンストラクターの名前で、次のオブジェクトはプロトタイプを表します。これは{}、つまりオブジェクトオブジェクト(空のオブジェクト)のインスタンスです
次に、f {}それが何を意味するかを理解します。 fはコンストラクターの名前であり、プロトタイプも空のオブジェクトです
//コンストラクターvar o = new object()によって作成された例を見てみましょう。 // var o = {}; //未定義のオブジェクト{} console.log(o.prototype、o .__ proto__);関数f(){} var i = new f(); //非定義f {} console.log(i.prototype、i .__ proto__);もう少し深く行き、Fのプロトタイプを定義して、何が起こるかを確認しましょう。
function f(){} f.prototype.a = function(){}; var i = new f(); //非定義f {a:function} console.log(i.prototype、i .__ proto__);このようにして、IがFから構築されていることが明確にわかります。プロトタイプは{a:function}です。これは、メソッドAが元の空のオブジェクトプロトタイプに追加されたことを意味します。
状況を変えましょう。Fを完全にカバーするプロトタイプがどうなりますか?
function f(){} f.prototype = {a:function(){}}; var i = new f(); //未定義のオブジェクト{a:function} console.log(i.prototype、i .__ proto__);ねえ〜なぜ私がオブジェクトから構築されていることをここに示しているのですか?いいえ!
Fのプロトタイプを完全に上書きするため、実際、プロトタイプをオブジェクト{a:function}として指定しますが、これにより、元のコンストラクター情報が失われ、オブジェクト{a:function}で指定されたコンストラクターになります。
では、オブジェクトのコンストラクター{a:function}は何ですか?
オブジェクト{a:function}は実際には関連しているためです
var o = {a:function(){}} //新しいオブジェクトその後、Oのコンストラクターはもちろんオブジェクトです
このエラーを修正しましょう
function f(){} f.prototype = {a:function(){}} //正しいコンストラクターf.prototype.constructor = f;を再指定するvar i = new f(); //非定義f {a:function、constructor:function} console.log(i.prototype、i .__ proto__);これで、正しいプロトタイプ情報をもう一度入手できます〜
プロトタイプチェーン
それでは、プロトタイプチェーンとは何かを見てみましょう。
簡単に言えば、OOPの相続関係(チェーン)と同じです。最終object.prototypeまでレイヤーごとにレイヤーを検索します
最も重要なことは、JSの(インスタンス)オブジェクトであるものを把握することです。これは簡単です、JSのすべてはオブジェクトです!
次に、すべてのオブジェクトにプロトタイプがあることを把握する必要があります!
それからそれを証明しましょう:
オブジェクト//これは関数であり、関数は関数のインスタンスオブジェクトであるため、オブジェクトです。__proto__ == function.prototype //オブジェクトのプロトタイプ、true //これは通常のオブジェクトです。 object.prototype .__ proto__ == null // true function //これも関数です、はい! function .__ proto__ == function.prototype // true function a(){} //これはカスタム関数であり、結局のところ機能です、そうです! a .__ proto__ == function.prototype //関数は関数のインスタンスです。 var a = new a()a .__ proto__ == A.prototype //インスタンスAはAコンストラクターによって構築されるため、AのプロトタイプはA.Prototypeのプロトタイプ属性によって定義されます。__Proto__ == object.prototype //通常のオブジェクトの例はオブジェクトですプロトタイプと__proto__
各オブジェクトには、オブジェクトの「プロトタイプ」を指す__Proto__が含まれています。
同様のことは、各関数にプロトタイプが含まれていることです。このプロトタイプオブジェクトは何のためですか?
コンストラクターを使用してオブジェクトを作成して、次のコードを見てみましょう(上記は、文字通りの形式のオブジェクトを作成することです)。
function foo(){}; var foo = new foo(); console.log(foo .__ proto__);想像してみてください、このfooオブジェクトの__proto__は何を指しているのでしょうか?
コンストラクター属性を含むオブジェクト?あまり理解していないかどうかは関係ありません。関数fooのプロトタイプ属性を印刷し、それをあなたと比較して知ってください。
function foo(){}; var foo = new foo(); console.log(foo .__ proto __); console.log(foo.prototype); console.log(foo .__ proto__ === foo.prototype);新しいものから出てくるオブジェクトfooの__proto__は、関数fooのプロトタイプを指し示していることがわかります。
foo .__ proto__-> foo.prototype
このようなJSを設計するポイントは何ですか?上記のことを思い出して、JSの世界では、オブジェクトはクラス(金型)に基づいて作成されるのではなく、プロトタイプ(別のオブジェクト)から派生しています。
新しいオブジェクトを作成するために新しい操作を実行すると、新しい操作の特定の実装について深く入り込むことはありませんが、1つのことを確信しています。つまり、新しいオブジェクトのプロトタイプオブジェクトを指します__Proto__。
ただこのコード
function foo(){}; var foo = new foo();foo .__ proto__を指しているのは誰ですか?なぜあなたは機能自体を指すことができないのですか?関数はオブジェクトでもありますが、チャンスがあれば詳細に説明します。しかし、fooは多くの論理コードを持つ関数であるため、foo .__ proto__fooを指すことは確かに適切ではありません。オブジェクトとして、論理処理を継承する意味はありません。継承したいのは、「プロトタイプオブジェクト」の属性です。
したがって、各関数はプロトタイプオブジェクトを自動的に生成し、この関数から新しいオブジェクトの__Proto__はこの関数のプロトタイプを指します。
foo .__ proto__-> foo.prototype
要約します
多くのことを言った後、私はまだそれを完全に説明していないので、前の写真にいる方が良いです。私は他のネチズンからの写真を参照しましたが、私はいつもはっきりと説明していないと感じているので、自分で写真を描きました。私が良いと思うなら、それを気に入ってください! (私はそれを描くために最善を尽くしました)。
この写真を撮って、次の事実を覚えておいてください。
1.各オブジェクトに_Proto_属性があります。
JSの世界には、クラス(金型)の概念はありません。オブジェクトは別のオブジェクト(proto)から派生しているため、各オブジェクトにプロトタイプオブジェクトを指す_Proto_属性があります。 (左上隅のリテラル形式で定義されたオブジェクトを参照してください。オブジェクトのプロパティをメモリに保存するスペースを開き、_Proto_を生成します。
2。各関数にはプロトタイププロパティがあります。
「コンストラクター」がコンストラクターと呼ばれるのはなぜですか?オブジェクトを構築したいからです。上記の最初の事実によると、構築された新しいオブジェクトポイントの_Proto_属性は誰ですか?コンストラクター自体を指すことはできません。オブジェクトでもありますが、新しいオブジェクトが関数のプロパティとメソッドを継承したくありません。したがって、各コンストラクターにはプロトタイプ属性があり、このコンストラクターによって構築された新しいオブジェクトのプロトタイプとしてオブジェクトを指します。
3。関数もオブジェクトです。
各関数には、apply()/call()など、いくつかの共通のプロパティとメソッドがあります。しかし、これらの一般的な方法はどのように継承されますか?関数はどのように作成されますか?想像してください、すべてが関数を含むオブジェクトであり、コンストラクターを介して構築されたオブジェクトです。次に、上記の2番目の事実によれば、各関数にはそのコンストラクターを指すプロトタイプもあります。このコンストラクターの関数は関数であり、JSのすべての関数は関数から構築されます。関数の一般的な特性と方法は、プロトタイプオブジェクトfunction.prototypeに保存されます。