[js]プロトタイプ

6426 ワード

グループ学習🦆 アヒルと一緒に!
<ディレクトリ>
1.オブジェクトジェネレータ関数の問題点
2.プロトタイプとは?
3.原型製品
4.proto property
5.プロトタイプチェーン
6.整理

1.オブジェクトジェネレータ関数の問題点


コンストラクション関数を使用すると、数十個の同じ形状のオブジェクトを簡単に作成できます.
メソッドがコンストラクション関数にある場合、
メソッドはhipメモリに割り当てられますが、数十個のPersonインスタンスを作成するたびに、PersonのsayHiメソッドがhipメモリに割り当てられ、効率が低下し、メモリが消費されます.だからプロトタイプを使います.
プロトタイプを使用する前に)
function Person(name){
  this.name=name;
  this.sayHi= function(){
      console.log(`Hi ${this.name}`);
 }
 const mike= new Person('mike');
 const sally = new Person('sally');

2.プロトタイプとは?


jsでは、関数はオブジェクトであるため、関数にもpropertyがあります.
関数はpropertyであり,パラメータ,呼び出し者,プロトタイプ,[prototype]などを持つ.

原型は継承の概念である.
JAvaまたは他の言語はクラスを継承し、jsはオブジェクトを継承します.
継承とは、子供が親の役割を継承することを意味します.つまり、jsでは、あるオブジェクトが他のオブジェクトの機能を継承します.
生成者の関数問題はjs式の継承であり,プロトタイプを用いてメモリ浪費問題を解決できる.
佟prototype適用前)
インスタンスを作成するたびに同じ方法を作成します->メモリの無駄+効率👎
改善後)sayHiメソッドは、コンストラクション関数内で直接定義するのではなく、プロトタイプとして定義される.
function Person(name){
  this.name=name;
 👉  Person.prototype.sayHi= function(){
       console.log(`Hi ${this.name}`);
    }
 }
 const sally = new Person('sally');
 const mike = new Person('mike');
sayHiメソッドは、コンストラクション関数で定義されるのではなく、コンストラクション関数のPrototype Propertyが指すPrototypeオブジェクトに登録されます.
では、新しく作成された各インスタンスにはsayHiメソッドはありませんが、プロトタイプオブジェクトのsayHiメソッドを使用することができます.
(インスタンス内の[Prototype]はプロトタイプオブジェクトを継承します.図全体を表示するだけで、後でこのオブジェクトについて説明します.)
sally.sayHi();//Hi sally;

インスタンスはメモリにsayHiメソッドはありませんが、[[Prototype]]によってコンストラクション関数のプロトタイプオブジェクトを参照できます.
すなわち、インスタンスは、プロトタイプオブジェクト内のすべてのメソッドとプログラムを継承します.
したがって、sayHiの方法を使用してもよい.
プロトタイプをコンストラクション関数に適用し、再度表示します.

図に示すように、prototypeオブジェクトには、既存のコンストラクション関数に加えてsayHiが追加されている.(コンストラクション関数、prototype、および[prototype]については、これから説明します)

3.原型製品


先ほど見たように、コンストラクション関数にはprototypeパーセントが表示されます.
各関数には、prototypeのパーセントが含まれています.prototypeパーセントとは、プロトタイプオブジェクトを指します.
プロトタイプオブジェクトは、実質的にconstructorおよび[[Prototype]]を有する.
constructor propertyとは、独自のコンストラクション関数を参照することです.
すなわち,コンストラクション関数のプロトタイプベースとプロトタイプオブジェクトのコンストラクション関数は互いに参照される.

次に、インスタンスはプロトタイプオブジェクトを継承します.

ただし、すべての関数オブジェクトにPrototype Propertyがあるわけではありません.non-constructor(矢印関数、メソッド)関数にはプロトタイプpropertyはありません.
プロトタイププログラムは、constructorを有する関数のみが有する.

4. __proto__

__proto__は実は[[Prototype]]の訪問者プログラムに近づくためです.
アクセス者プログラムは、getter、setterによって値を安全に読み取り、書き込む方法であり、外部でデータを勝手に操作することを防止する.
すべてのオブジェクトには[[Prototype]]の内部プログラムがあります.[[Prototype]]は、内部スロット(javascriptエンジンの内部ロジック)であり、その継承者である親オブジェクトのプロトタイプオブジェクトを指す.
したがって、オブジェクトは、[[Prototype]]に示されるプロトタイプオブジェクトのすべてのプロパティおよびメソッドを使用することができる.
内部スロットのため、EC 5には[PRODotype]にアクセスできません.
EC 6からは、__proto__パーセントで間接的に[prototype]に近づくことができる.
したがって、[[Prototype]]__proto__と表す.
function Person(name){
       this.name=name;
       Person.prototype.sayHi= function(){
           console.log(`Hi ${this.name}`);
       }
  }   
const sally= new Person('mike');

インスタンスの[prototype]または__proto__は、Personコンストラクション関数のプロトタイプオブジェクトを指します.
プロトタイプオブジェクトのすべてのプロパティとメソッドを継承します.
コンストラクション関数が継承されているため、インスタンスはPersonジェネレータのすべてのPropertyとメソッドを参照できます.
console.log(Person.prototype=== sally. __proto__ );//true
console.log(Person === sally.constructor);//true

インスタンスが__proto__([prototype])を介してジェネレータプロトタイプオブジェクトを直接継承していることが写真からわかります.
インスタンスは単純なオブジェクトであり、コンストラクション関数は存在しませんが、継承によって継承されていることがわかります.
コンストラクション関数が持つprototypeが持たないことも決定できます.
そしてここでは、Prototypeで議論される[[Prototype]]:Objectが[prototype]に含まれていることがわかります.
以上のように、prototypeの割合は、コンストラクション関数を有する関数のみにおいて、通常のオブジェクト文字であってもよいし、({...})であってもよい.non-constructor関数にはプロトタイププログラムがありません.
逆に、[[Prototype]]プロトコルは、すべてのオブジェクトが持つ内部スロットであり、直接アクセスすることはできません.__proto__ビジタープロトコルを使用して間接アクセスできます.また、__proto__([prototype])は、自分に引き継がれたプロトタイプオブジェクトを指すため、__proto__で指すプロトタイプオブジェクトのprototypeを使用することができる.
これにより、オブジェクトはこれらのオブジェクトにアクセスして使用できます.これらのオブジェクトは、それらが持たないPropertyまたはメソッドを継承できます.

5.プロトタイプチェーン

[[Prototype]]先ほどお話ししたように、オブジェクトごとにあるので、オブジェクトごとに[[Prototye]]があります.__proto__が指すオブジェクトのうち、__proto__が指すオブジェクトのうち、__proto__が指すオブジェクト…
このように__proto__で親として上昇し続ける連結リングをプロトタイプチェーンと呼ぶ.このように上昇し続け、最終目的地はnullをモデルとしたオブジェクト上で終了する.
プロトタイプpropertyを紹介する際に現れますが、プロトタイプpropertyには構造関数propertyと[prototype]があります.
図に示す場合、[PRODUCType]は省略され、識別子のみを表しますが、実際には[PRODUCType]はオブジェクトのプロトタイプオブジェクトを指します.
Object.プロトタイプはすべてのオブジェクトのプロトタイプです.

最終boss Objectの__proto__はnull終了を指す.

6.整理


原型は本当に複雑で難しい...深く入り込むと本当に複雑で複雑です.恐らくここまで読める人はいないだろう.もしあったら、間違った情報があったので、何を言っている人…?まず、jsはjava言語のようにclass概念を持っていないことをまとめます.JAvaはclassを継承して上書きし、jsはプロトコルタイプチェーンを使用してオブジェクトの情報を他のオブジェクトに渡します.すなわち,プロトタイプを継承するオブジェクト向け言語をプロトタイプベースのオブジェクト向け言語と呼ぶ.
前述したように、プロトコルタイプとして定義すると、メモリを無駄にすることなく、各インスタンスを効率的にプログラミングできます.
しかし、ここでは言及していないが、プロトタイプを修正、変更することができる.開発者は、直接継承するオブジェクトを特定できます.すなわち,継承関係を任意に変更できることは,安全ではなく,面倒で非効率であることを意味する.
したがって,プロトタイプではなくES 6からサポートされるクラスを選択することが望ましい.(ここでjsのclassはjavaのclassとは異なり、jsではclassも関数であり、プロトタイプの使用をより簡単にするためである.)