JS関数の継承について学ぶ記事

JS関数の継承について学ぶ記事

1. はじめに:

こんにちは、皆さん最近調子はどうですか?😃関数の継承は JS の基本かつ重要な部分であり、面接でもよく質問されます。以下では、JS でよく使用され、習得する必要がある継承メソッドを簡単に紹介します。以下の内容をマスターしておけば面接も問題なしですよ~

もちろん、これにはプロトタイプ チェーンの一定の基礎が必要です。プロトタイプ チェーンに詳しくない場合は、私の記事「js プロトタイプ チェーンの簡単な理解」をお読みください。

2. プロトタイプチェーン継承:

プロトタイプ チェーン継承の重要なポイントは、親クラスのインスタンスが子クラスのプロトタイプとして機能することです。次の例を見てください。

 // 親関数 Person
  関数 Person(名前, 年齢) {
    // いくつかのプロパティを定義します this.name = name;
    this.age = 年齢;
    this.nature = ["オーロラ", "風", "月"];
  }
 // Personプロトタイプにメソッドを定義する Person.prototype.sayLove = function () {
    console.log(this.name + " 好き " + this.nature[0]);
  };
  // サブ関数ジャック
  関数 Jack() {}
  // 親クラスのインスタンスはサブクラスのプロトタイプとして使用されます (------------------実装コア--------------------------)
  Jack.prototype = 新しい Person();

ここで、Jack のインスタンスを 2 つ作成し、Person の継承が実装されているかどうかをテストします。

      var jack1 = 新しい Jack();
      var jack2 = 新しい Jack();
      jack2.nature[0] = "海";
      jack1.sayLove();
      jack2.sayLove();   
      コンソールにログ出力します。
      コンソールにログ出力します。  

実行結果から、確かに継承されており、sayLove メソッドを実行できることがわかります。しかし、欠点もたくさんあります。Jack インスタンスを作成するときに、name と age パラメータを渡すことができず、異なるインスタンスの nature 参照型属性が互いに影響を及ぼします。1 つを変更すると、すべてが変更されます。

ここに画像の説明を挿入

3. コンストラクタ継承の借用(オブジェクトの偽装):

核心は「コンストラクタの盗用」にあります。サブクラスのコンストラクターから親クラスのコンストラクターを呼び出します。結局のところ、関数は特定のコンテキストでコードを実行する単なるオブジェクトなので、apply() メソッドと call() メソッドを使用して、新しく作成されたオブジェクトをコンテキストとしてコンストラクターを実行できます。プロトタイプ チェーン継承におけるパラメーターと参照型プロパティ間の競合を解決できます。または、直接例を見てみましょう:

 // 親関数 Person
  関数 Person(名前, 年齢) {
    // いくつかのプロパティを定義します this.name = name;
    this.age = 年齢;
    this.nature = ["オーロラ", "風", "月"];
  }
 // Personプロトタイプにメソッドを定義する Person.prototype.sayLove = function () {
    console.log(this.name + " 好き " + this.nature[0]);
  };
  // サブ関数 Lucy
  関数 Lucy(名前, 年齢) {
  // 呼び出しを通じてこれを Lucy にポイントすることは、親関数 Person のコンテンツをコピーすることと同じです (---------実装コア--------------)
        Person.call(this, 名前, 年齢);
      }
  // 子関数プロトタイプにメソッドを定義する Lucy.prototype.syaName = function () {
        console.log("私の名前は " + this.name です);
      };

ここで、Lucy のインスタンスを 2 つ作成し、Person の継承が実装されているかどうかをテストします。

      var lucy1 = new Lucy("lucy1", "20");
      var lucy2 = new Lucy("lucy2", "22");
      lucy2.nature[0] = "海";
      コンソールにログ出力します。
      コンソールにログ出力します。
      コンソールにログ出力します。
      lucy1.syaName();
      lucy2.syaName();
      lucy1.sayLove();

その結果、継承が可能になり、パラメータを渡すことができ、参照型のプロパティは互いに影響を及ぼしません。ただし、デメリットは明らかです。エラーが表示され、親クラスのプロトタイプで sayLove メソッドを使用できません。

ここに画像の説明を挿入

4. 組み合わせ継承:

複合継承は、プロトタイプチェーン継承と借用コンストラクタ継承のコア実装を組み合わせた継承方法です。パラメータを渡すことができ、参照型プロパティは互いに影響しません。同時に、サブクラスは親クラスのメソッドも取得できます。これは現在最も一般的に使用されている継承方法でもあります。直接例を見てみましょう:

 // 親関数 Person
  関数 Person(名前, 年齢) {
    // いくつかのプロパティを定義します this.name = name;
    this.age = 年齢;
    this.nature = ["オーロラ", "風", "月"];
  }
 // Personプロトタイプにメソッドを定義する Person.prototype.sayLove = function () {
    console.log(this.name + " 好き " + this.nature[0]);
  };
  // サブ関数 Lisa
      関数 Lisa(名前, 年齢) {
// 呼び出しを通じてこれを Lisa にポイントすることは、親関数 Person のコンテンツをコピーすることと同じです (------実装コア-----------)      
        Person.call(this, 名前, 年齢);
      }
// 親クラスのインスタンスはサブクラスのプロトタイプとして使用されます (---------------実装コア-------------------)      
      Lisa.prototype = 新しいPerson();
  //ちょっとした知識ポイントですが、ここでは Lisa のコンストラクタが再び Lisa を指すようにします。そうしないと、Lisa のプロトタイプが Person インスタンスであるため、コンストラクタは Person を指すことになります。
      Lisa のプロトタイプを作成します。

ここで、Lisa のインスタンスを 2 つ作成し、Person の継承が実装されているかどうかをテストします。

      var lisa1 = new Lisa("lisa1", "20");
      var lisa2 = new Lisa("lisa2", "21");
      lisa2.nature[0] = "海";
      コンソールログ(lisa1.name);
      コンソールにログ出力します。
      コンソールにログ出力します。
      lisa1.sayLove();
      lisa2.sayLove();

継承した機能が基本的に実現されていることがわかります。また、プロトタイプチェーンと借用コンストラクタ継承の欠点も修正します。ただし、まだ小さな欠点があります。コード コメントの実装コアでは、Person が 2 回呼び出されているため、Lisa プロトタイプとインスタンスに 2 つの同一のプロパティがあり、パフォーマンスがいくらか浪費されることがわかります。

ここに画像の説明を挿入

5. 寄生的組み合わせ遺伝:

実際、寄生的なコンポジション継承はコンポジション継承に似ていますが、コンポジション継承のプロトタイプとインスタンスが同じプロパティのコピーを 2 つ生成するという欠点に対する追加の解決策があります。ソリューションの核心は、サブクラスのプロトタイプを親クラスのプロトタイプに割り当てるだけなので、新しい親クラスのインスタンスを作成する必要がないことです。親クラスのプロトタイプを値とする新しいオブジェクトを作成し、それを子クラスのプロトタイプに割り当てるだけです。

Object.create(proto, [propertiesObject]) メソッドは、新しいオブジェクトを作成するために使用されます。新しいオブジェクトの __proto__ は、そのパラメータ proto と同等です。もちろん、Object.create は IE の下位バージョンでは使用できない可能性があるため、Object.create メソッドも以下のようにカスタム カプセル化されていますが、これは単純なカプセル化にすぎません。直接例を見てみましょう:

 // 親関数 Person
  関数 Person(名前, 年齢) {
    // いくつかのプロパティを定義します this.name = name;
    this.age = 年齢;
    this.nature = ["オーロラ", "風", "月"];
  }
 // Personプロトタイプにメソッドを定義する Person.prototype.sayLove = function () {
    console.log(this.name + " 好き " + this.nature[0]);
  };
  // サブ関数 Andy
 関数 Andy(名前, 年齢) {
        Person.call(this, 名前, 年齢);
      }
// Object.create() メソッドがない場合は、単に if (!Object.create) { をカプセル化します。
        Object.create = 関数 (proto) {
          関数 Temp() {}
          Temp.prototype = proto;
          新しい Temp() を返します。
        };
      }
// Object.create メソッドを呼び出して、__proto__ が Person.prototype である新しい画像のペアを作成し、それを Andy.prototype に割り当てます (-------実装コア----------)
      Andy.prototype = Object.create(Person.prototype);
  // Andy を指すようにコンストラクターを変更します。prototype.constructor = Andy;

ここで、Andy のインスタンスを 2 つ作成し、Person の継承が実装されているかどうかをテストします。

      console.log(Andy.prototype.__proto__ === Person.prototype);
      var andy1 = new Andy("andy1", "20");
      var andy2 = new Andy("andy2", "21");
      andy2.nature[0] = "海";
      コンソールにログ出力します。
      コンソールにログ出力します。
      コンソールにログ出力します。
      andy1.sayLove();
      andy2.sayLove();

完璧に動作します:

ここに画像の説明を挿入

6. クラスの継承:

ES6 でクラス構文シュガーがリリースされてからは、クラスを通じてクラスを定義し、クラスの継承を実装できるようになりました。直接例を見てみましょう:

//親クラス Animal を定義する
  クラス動物{
   //ここでコンストラクタはクラス自体を指しており、es5の動作と同じです。constructor(name) {
      this.name = 名前;
    }
    いいね食べる() {
      console.log(this.name + " like eat " + this.food);
    }
  }
//親クラスAnimalを継承してサブクラスDogを定義する
  クラスDogはAnimalを拡張します{   
    コンストラクタ(名前、食べ物) {
      //親クラスの属性 super(name) を super(attribute name) を通じて継承します。
     this.food = 食べ物;
    }
    いいね食べる() {
     // super を通じて親クラス メソッドを継承します。+親クラス メソッド super.likeEat();
    }
  }

新しい Dog インスタンスを作成し、Dog が Animal を継承するかどうかをテストします。

  var jinmao = new Dog("jinmao", "bone");
  console.log(jinmao.name);
  ジンマオ

完璧に実装されていることがわかります。

ここに画像の説明を挿入

7. 要約:

方法アドバンテージ欠点
プロトタイプチェーン継承親プロトタイプなどからプロパティやメソッドを継承できます。パラメータを渡すことができない、参照型属性が競合しているなど...
コンストラクタ継承の借用パラメータを渡すことができ、参照型属性が競合しないなど...親プロトタイプなどからメソッドを継承できません。
コンポジション継承上記2つの利点を持ち、欠点を解決します親インスタンスを 2 回呼び出すと、同じプロパティのコピーが 2 つ生成されます。
寄生的な構成継承上記3つの利点があり、欠点を解決しますあまり直感的ではないかもしれません...
クラスの継承es6 の新しい構文、簡潔で直感的など... IE の下位バージョンでは es6 などがサポートされません。

この記事はこれで終わりです。皆さんのお役に立てれば幸いです。また、123WORDPRESS.COM のその他のコンテンツにも注目していただければ幸いです。

以下もご興味があるかもしれません:
  • Js クラスの構築と継承のケースの詳細な説明
  • JavaScript の継承についてどれくらい知っていますか?
  • JS における ES6 継承と ES5 継承の違い
  • JavaScript の寄生的構成継承についての簡単な説明
  • JavaScript オブジェクト指向クラス継承ケースの説明
  • JavaScript継承のさまざまな方法とメリット・デメリットを詳しく解説

<<:  Linux で NFS のワンクリック展開を実装する方法

>>:  CentOS7 64でのMySQL5.6.40の詳細なインストール手順

推薦する

MySQLのサブクエリユニオンの効率性についての簡単な説明と

最近の製品テストでは、同時呼び出し数が 10 未満の場合に応答時間が 100 ミリ秒以内に維持できな...

Mongodb の GUID 表示の問題の詳細な分析

問題を見つける最近、プログラムのストレージを Mongodb に移行したところ、Guid 型が書き込...

要素テーブルの行と列のドラッグを実装する例

要素 ui テーブルにはドラッグ アンド ドロップによる並べ替え機能が組み込まれておらず、サードパー...

バックエンドから返される 100,000 個のデータをフロントエンドでより適切に表示するにはどうすればよいですか?

目次予備作業バックエンド構築フロントエンドページダイレクトレンダリングsetTimeout ページン...

Vue の自動書式設定の改行保存の詳細な説明

ネットで変更方法をいろいろ調べたのですが、うまくいきませんでした。後で大物から見て削除しました。フォ...

MySQL explain クエリ命令情報の取得原理と例

explain はクエリ実行プラン情報を取得するために使用されます。 1. 文法次のように、sele...

CSSボックスの表示/非表示とトップレイヤーの実装コード

.imgbox{ 幅: 1200ピクセル; 高さ: 612px; 右マージン: 自動; 左マージン...

JSはオンラインでのアナウンスのスクロール効果を実現します

この記事では、オンラインアナウンスのスクロール効果を実現するためのJSの具体的なコードを参考までに共...

MySQL の frm ファイルからテーブル構造を復元する 3 つの方法 [推奨]

mysql が正常に実行されている場合、テーブル構造を表示することは難しくありません。しかし、場合...

MySqlのインストールとログインの詳細な説明

LinuxにMySQLがすでにインストールされているかどうかを確認する sudo service m...

1つの記事でJSONPの原理と応用を理解する

目次JSONPとはJSONP 原則JSONP実装1. Ajaxでクロスドメインリクエストが行われると...

ウェブページ制作時のコードコメントの書き方

<br />私の仕事で使用しているアノテーションの書き方の基準をまとめました。技術的な内...

Squid を使用して http および https 用のプロキシ サーバーを構築する方法

nginx を導入した際に、フォワードプロキシの設定も nginx を使っていました。しかし、htt...

Vue がコンポーネント通信を実装する 8 つの例

目次1. Props 親コンポーネント ---> 子コンポーネント通信2. $emit 子コン...

Dockerコンテナ同士を接続する3つの方法の詳しい説明

Docker コンテナ間の相互接続と通信には 3 つの方法があります。 Docker 内部ネットワー...