JavaScript コンストラクタとプロトタイプの関係

JavaScript コンストラクタとプロトタイプの関係

1. コンストラクタとプロトタイプ

1. コンストラクター

コンストラクターは、主にオブジェクトを初期化する、つまりオブジェクトのメンバー変数に初期値を割り当てるために使用される特別な関数です。常にnewと一緒に使用されます。オブジェクトからいくつかの共通プロパティとメソッドを抽出し、この関数にカプセル化することができます。
JSでは、

コンストラクターを使用する場合は、次の 2 つの点に注意してください。

  • コンストラクターは特定のタイプのオブジェクトを作成するために使用され、その最初の文字は大文字にする必要があります。
  • コンストラクターはnewと一緒に使用する場合にのみ意味を持ちます。

new は実行されると次の 4 つの処理を実行します。

  • メモリ内に新しい空のオブジェクトを作成します。
  • この点を新しいオブジェクトに向けます。
  • コンストラクター内のコードを実行して、新しいオブジェクトにプロパティとメソッドを追加します。
  • この新しいオブジェクトを返します (したがって、コンストラクターではreturnは必要ありません)。

一部のメンバーは、コンストラクター自体またはコンストラクター内の this のいずれかで、 JavaScriptコンストラクターに追加できます。これら 2 つの方法で追加されたメンバーは、それぞれ静的メンバーとインスタンス メンバーと呼ばれます。
インスタンス メンバー:コンストラクター内で作成されたオブジェクト メンバーはインスタンス メンバーと呼ばれ、インスタンス化されたオブジェクトからのみアクセスできます。
静的メンバー:コンストラクターに追加されたメンバーは静的メンバーと呼ばれ、コンストラクター自体からのみアクセスできます。

例えば:

 関数A(名前,年齢){
            uname は uname です。
            this.age = 年齢;
            this.say = 関数() {
                console.log(this.uname+'hello');
            }
        }
        var wh = new A('王欢',18);
        var xl = new A('リトルベア',18);

上記のコードでは、コンストラクターで this を通じて追加されたnameagesayメソッドはすべてインスタンス メンバーです。インスタンス化されたオブジェクトからのみアクセスできます。コンストラクター自体に追加されるメンバーは、静的メンバーと呼ばれます。

たとえば、静的メンバーを作成します。

A.sex='女性';

2. コンストラクタ問題

コンストラクタメソッドは非常に便利ですが、メモリを無駄にしてしまうという問題があります

以下のように表示されます。

関数 学生(年齢,名前){
            this.age = 年齢;
            this.name = 名前;
            this.score = 関数(){
            console.log('子どもたちはみんな成績が良いです!');
        }
        }
        console.dir(学生);
        var xl = new Student(18,'リトルベア');
        var wh = new Student(17,'王欢');
        xl.スコア();
        wh.score();
       

次のコードを使用して、呼び出された 2 つのメソッドのアドレスが同じかどうかを判断します。

 console.log(xl.score === wh.score);


印刷結果は次のとおりです。

A の say 関数が 2 回呼び出されると、そのアドレスは同じではないことがわかります。これは、2 つのメモリ空間が開かれ、メモリが無駄になるためです。

3. コンストラクターのプロトタイプ

プロトタイプを通じてコン​​ストラクターによって割り当てられた関数は、すべてのオブジェクトで共有されます。 JavaScript では、すべてのコンストラクターに別のオブジェクトを指すprototypeプロパティがあることが規定されています。このprototypeはオブジェクトであり、このオブジェクトのすべてのプロパティとメソッドはコンストラクターによって所有されることに注意してください。

次のようにコンストラクターを作成します。

関数 学生(年齢,名前){
            this.age = 年齢;
            this.name = 名前;
            this.score = 関数(){
                console.log('子どもたちはみんな成績が良いです!');
            }
        }
        console.dir(学生);

コンストラクター内のすべてのメソッドを印刷すると、次のようになります。

prototypeオブジェクトが見つかります。
これらの不変のメソッドをprototypeオブジェクトに直接定義して、オブジェクトのすべてのインスタンスがこれらのメソッドを共有できるようにすることができます。

関数 学生(年齢,名前){
            this.age = 年齢;
            this.name = 名前;
        }
        Student.prototype.score = function(){
            console.log('子どもたちはみんな成績が良いです!');
        }
        console.dir(学生);
        var xl = new Student(18,'リトルベア');
        var wh = new Student(17,'王欢');
        xl.スコア();
        wh.score();
        console.log(xl.score === wh.score);

印刷結果は次のとおりです。

また、関数を 2 回呼び出すと、メモリ領域が 1 つだけ開かれるため、メモリの無駄も削減されます。

注:一般に、パブリック プロパティはコンストラクターで定義され、パブリック メソッドはプロトタイプ オブジェクトで定義されます。

4. オブジェクトプロトタイプ __proto__

すべてのオブジェクトには、コンストラクター関数のprototypeオブジェクトを指すプロパティ__proto__があります。オブジェクトがコンストラクター関数プロトタイプ オブジェクトのプロパティとメソッドを使用できるのは、オブジェクトが__proto__プロトタイプを持っているためです。

以下のように表示されます。

関数 学生(年齢,名前){
            this.age = 年齢;
            this.name = 名前;
           
        }
 Student.prototype.score = function(){
     console.log('子どもたちはみんな成績が良いです!');
 }
// console.dir(学生);
 var xl = new Student(18,'リトルベア');
 var wh = new Student(17,'王欢');
 コンソールログ(xl);

次のコード名で__proto__オブジェクトのプロトタイプがあるかどうかを確認します

console.log(xl); //システムは、コンストラクタのプロトタイプオブジェクトを指すために、オブジェクトに__proto__プロパティを追加します。

出力は次のようになります。

認識可能な存在。
上記の例では、次のコードを入力して、 __proto__オブジェクト プロトタイプと prototype オブジェクトprototypeが同等かどうかを判断します。

 console.log(xl.__proto__ === Student.prototype);

印刷結果は次のとおりです: true
したがって、 __proto__オブジェクトプロトタイプとプロトタイプprototypeは同等です。

次のようにインスタンス オブジェクトを通じてスコア関数を呼び出します。

xl.スコア();

出力は次のようになります。

これは呼び出すことができ、そのメソッド検索ルールは次のようになります。まず、 xl オブジェクトにscoreメソッドがあるかどうかを確認します。ある場合は、このオブジェクトでscoreを実行します。そのようなメソッドがない場合、 __prooto__属性があるため、コンストラクター関数プロトタイプprototypeで検索します。

次の図を使用して説明できます。

__proto__オブジェクト プロトタイプの重要性は、オブジェクトの検索メカニズムに方向、つまりルートを提供することですが、これは非標準の属性であるため、実際の開発では使用できません。内部的にプロトタイプprototypeを指すだけです。

5. コンストラクター

前の例に従って、インスタンス オブジェクト ( Student ) のオブジェクト プロトタイプ (__proto__) とコンストラクター (xl) ( prototype ) プロトタイプ オブジェクトをそれぞれ出力します。

console.log(Student.prototype);
コンソールにログ出力します。

印刷結果は次のとおりです。

オブジェクト プロトタイプ (__proto__) とコンストラクター関数 (prototype) の両方に、プロトタイプ オブジェクト内にコンストラクターと呼ばれるプロパティがあることがわかります。コンストラクター関数はコンストラクター関数自体を指しているため、 constructorター関数を呼び出します。

次に、オブジェクト プロトタイプとコンストラクター プロトタイプのconstroctorプロパティをそれぞれ出力します。戻り値を観察します。

 console.log(Student.prototype.constructor);
 console.log(xl.__proto__.constructor);

印刷結果は次のとおりです。

それらはすべてStudentコンストラクターを指していることがわかります。
つまり、 constructor主に、オブジェクトがどのコンストラクターを参照するかを記録するために使用され、プロトタイプ オブジェクトが元のコンストラクターを参照できるようになります。

通常、オブジェクトのメソッドはコンストラクターのプロトタイプ オブジェクトに設定されます。コンストラクターに複数のメソッドを追加する場合は、オブジェクト メソッドを使用できます。

以下のように表示されます。

 学生.プロトタイプ = {
            スコア: 関数(){
            console.log('子どもたちはみんな成績が良いです!')},
            研究: 関数(){
            console.log('一生懸命勉強してください!');  
        }

変更されたプロトタイプ オブジェクトのコンストラクター属性を印刷する場合:

プロトタイプ オブジェクトのポインタが変更されていることがわかります。これは、プロトタイプ オブジェクトがオブジェクトの形式で割り当てられ、コンストラクター プロトタイプ オブジェクトの元のコンテンツが上書きされるためです。このように、変更されたプロトタイプ オブジェクトconstructor 、現在のコンストラクターを指していなくなります。
この時点で、変更されたプロトタイプ オブジェクトにconstructorを追加して、元のコンストラクターを指すことができます。

次のように:

学生.プロトタイプ = {
            コンストラクター:学生、
            スコア: 関数(){
            console.log('子どもたちはみんな成績が良いです!')},
            研究: 関数(){
            console.log('一生懸命勉強してください!');  
        }

最終的に印刷された結果は次のようになります

成功は元のコンストラクターに戻ります。

6. コンストラクタ、インスタンス、プロトタイプオブジェクトの関係

上記の例によると、コンストラクター、インスタンス、プロトタイプ オブジェクトの関係は次の図で表すことができます。

7. JavaScriptメンバー検索メカニズム(ルール)

  • オブジェクトのプロパティ (メソッドを含む) にアクセスするときは、まずオブジェクト自体にプロパティがあるかどうかを確認します。
  • そうでない場合は、そのプロトタイプ (つまり、__proto__ によって指されるprototype prototype オブジェクト) を探します。
  • そうでない場合は、プロトタイプ オブジェクトのプロトタイプ (オブジェクトのプロトタイプ オブジェクト) を探します。

Objectが見つかるまで(null)、これを繰り返します。
__proto__ オブジェクト プロトタイプの重要性は、オブジェクト メンバーの検索メカニズムに方向、つまりルートを提供することです。

8. 組み込みオブジェクトの拡張

プロトタイプ オブジェクトを使用して、元の組み込みオブジェクトを拡張およびカスタマイズできます。
まず、配列のプロトタイプ オブジェクトを出力して、使用可能な組み込みオブジェクトを確認します。

 console.log(配列.プロトタイプ);

印刷結果は次のとおりです。

たとえば、配列内の偶数の合計を求めるカスタム関数を追加します。

 Array.prototype.sum = 関数(){
            var 合計 = 0;
            for(var i=0;i<this.length;i++){
                合計 += this[i];
            }
            合計を返します。
        }

組み込みオブジェクトが正常に展開されたかどうかを確認するには、もう一度入力します。

console.log(配列.プロトタイプ);

構築は成功しました。特定のインスタンス オブジェクトを指定して、正常に使用できるかどうかを判断します。

var arr = [1,2,3];
        コンソールにログ出力します。

印刷結果は次のとおりです。

2. 階級の本質

  • classの本質はやはりfunctionです。
  • クラスのすべてのメソッドは、クラスのprototypeプロパティで定義されます。
  • クラスによって作成されたインスタンスには、クラスのプロトタイプオブジェクトを指す__proto__も含まれています。
  • ES6 クラスのほとんどの機能は ES5 でも実現できます。新しいclass記述方法により、オブジェクト プロトタイプの記述がより明確になり、オブジェクト指向プログラミングの構文に近くなります。

JavaScript コンストラクターとプロトタイプに関するこの記事はこれで終わりです。より関連性の高い JavaScript コンストラクターとプロトタイプについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • JavaScript のコンストラクタ関数とプロトタイプチェーンの関係の詳細な説明
  • js コンストラクターとプロトタイプの原則と使用例の分析
  • JavaScript オブジェクト指向プログラミングの詳細な説明 [クラス作成、インスタンスオブジェクト、コンストラクタ、プロトタイプなど]
  • JavaScript のコンストラクタ、インスタンス、プロトタイプ オブジェクト、プロトタイプ チェーンを 1 つの記事で学習します。
  • JSコンストラクタとインスタンス化およびプロトタイプ導入の関係

<<:  H5でクリックされたときにaタグの背景色をキャンセルする方法

>>:  CSSを使用してTDのINPUTの幅を設定する

推薦する

Spring Boot のパッケージ化と Docker リポジトリへのアップロードの詳細な手順

重要な注意: この記事を読む前に、Docker コンテナに関する知識と、一般的な Docker 操作...

MySQL インデックスの左端原則のサンプルコード

序文最近、MySQL のインデックスについて読んでいました。結合されたインデックスを見ると、左端の原...

UTF-8 および GB2312 ウェブエンコーディング

最近、多くの学生から Web ページのエンコーディングについて質問を受けています。gb2312 と ...

Vue-routerルーティングの使い方

目次1. 説明2. インストール3. テスト1. 説明Vue Router は、Vue.js の公式...

ReactJs 基礎チュートリアル - 基本編

目次1. ReactJS の紹介2. ReactJSの理解とReactJSの利点1. ReactJS...

LinuxサーバーにGRUBをインストールする手順

Linux サーバーに GRUB をインストールする方法クラウド移行ツールを使用して、CentOS ...

面接官がmysqlのcharとvarcharの違いを尋ねたとき

目次charとvarcharの違いcharとvarcharの違い上記は、MySQL における cha...

MySQL での coalesce() の使用に関するヒントのまとめ

序文最近、偶然 MySQL の coalesce を発見しました。ちょうど時間があったので、MySQ...

JavaScriptプロトタイプチェーンの詳細な説明

目次1. コンストラクタとインスタンス2. プロパティプロトタイプ3. プロパティ __proto_...

Linux の Docker コンテナで bash を終了する 2 つの方法

bash を終了する場合は、次の 2 つのオプションがあります。最初のもの: Ctrl + d を押...

HTML で中国語を UTF-8 に変換する方法

HTMLでは、中国語のフレーズ「學好好學」は「學好好學」と表現できます。プロジェクトでは、SMSアラ...

Ubuntuのインストール Matlab2020b の詳細なチュートリアルとリソース

目次1. リソースファイル2. インストール2.1 詳細な手順2.1.1 ディスクイメージのマウント...

XHTML 特殊文字コレクション

注意&#160;ノーブレークスペース = ノーブレークスペース、 iexcl ¡ &...

重複したMySQLレコードを現場でチェックし、処理する実践的な記録

目次序文分析するデータ合計繰り返し率どこにあるかと持っているかの違い要約する序文私はソフトウェアの導...

React+TS を使用したシンプルな Jira プロジェクトを実装するためのベスト プラクティス

トレーニングのための一連のプロジェクト反応+ts内容は少ないですが、フックのカプセル化、ts ジェネ...