JS 継承の詳細

JS 継承の詳細

序文

柔軟な js の場合、java などの言語と比較して、継承にはさまざまな実装方法があります。方法の多様性は、知識ポイントの多さを意味し、それは当然、面接中に避けることができないポイントです。 ES6 クラスは別として、従来の継承方法をいくつ知っていますか?それぞれの実装原則は何ですか? 利点と欠点についてお話しいただけますか?ここでは、具体的な例を用いて段階的なアプローチで継承の発展について見ていきます。

準備する

js の継承について説明する前に、js がオブジェクトをインスタンス化する方法を確認しましょう。

コンストラクターは、new を通じてオブジェクトをインスタンス化できる関数です。その目的は、それを再利用し、毎回手動でオブジェクト インスタンスを宣言する手間を省くことです。

新しいシンプルな実装は次のとおりです。

関数 my_new(func){
    var obj = {}
    obj._proto_ = func.protype // プロトタイプチェーンポイントを変更し、それを func プロトタイプチェーンに接合します func.call(obj) // インスタンス属性の割り当て return obj
}

上記からわかるように、インスタンス属性はコンストラクター呼び出しを通じてターゲット オブジェクトに割り当てることができます。

サブクラスで親クラスのコンストラクターを呼び出すことでも継承の目的を達成できると推測できます。

これにより、js を継承する方法、つまりコンストラクターを介して呼び出す方法が提供されます。

プロトタイプ属性に関しては、プロトタイプポインタを変更することでプロトタイプ属性の共有が実現されます。

継承にも同じ方法を使用できます。

要約する

コンストラクターとプロトタイプ チェーンの 2 つの機能に基づいており、js 言語の柔軟性と組み合わされています。

継承を実装する方法は多数ありますが、それらはすべて同じ原則に従います。

継承方法

プロトタイプ継承

定義: カスタム タイプを作成せずに、プロトタイプを使用して既存のオブジェクトに基づいて新しいオブジェクトを作成するこのタイプの継承は、プロトタイプ継承と呼ばれます。

コードを直接見たほうがわかりやすいです:

関数createObj(o) {
  関数 F() { }
  F.プロトタイプ = o;
  新しいF()を返します。
}
var 親 = {
  名前: 'trigkit4',
  arr: ['兄弟', '姉妹', 'ババ']
};
var child1 = createObj(親);

表面的には、このメソッドはオブジェクトの作成に基づいており、コンストラクターは必要ありません (もちろん、実際のコンストラクターはカプセル化されています)。プロトタイプオブジェクトのみが使用されるため、名前はプロトタイプ継承です。

欠点:

より明らかな優位性

この継承は再利用できず、各サブクラス インスタンスは完全な createObj プロセスを経る必要があります。

サブクラスオブジェクトの場合

コンストラクターは createObj にカプセル化されているため、そのためのコンストラクターはありません。この結果、初期化中にパラメータを渡すことができなくなります。
補足: createObj は ES6 でよく使用される Object.create() ですが、Object.create は追加のパラメータを許可するように改良されています。

解決:

この問題はコンストラクタの不足によって発生するため、コンストラクタのプロトタイプ チェーン継承が関係しているのではないかと大胆に推測します。

プロトタイプチェーン継承

定義: サブクラスが親クラスのプロパティ (メソッドを含む) を継承するには、まずコンストラクターを定義する必要があります。次に、スーパークラスの新しいインスタンスがコンストラクターのプロトタイプに割り当てられます。

関数親() {
  this.name = 'マイク';
}
関数Child() {
  年齢は12歳です。
}
Child.prototype = 新しい Parent();
child.prototype.constructor = child // prototype プロパティが上書きされるため、修正する必要があります。
var child1 = 新しい Child();

つまり、サブクラスのプロトタイプ オブジェクトを直接変更して親コンストラクターのインスタンスを指すようにし、親クラスのインスタンス属性とプロトタイプ属性が独自のプロトタイプ チェーンに掛けられるようにします。

欠点

Child.prototype = new Parent() の場合、子関数自体の prototype プロパティが上書きされ、必要に応じて後で補足する必要があります。

子オブジェクトがインスタンス化されると、親クラスのコンストラクターにパラメーターを渡すことはできません。
たとえば、new Child() が実行されたときに、名前を上書きしたい場合は、Child.prototype = new Parent() の場合にのみ上書きできます。 新しい Child() を作成するときに、パラメータを均一に渡して初期化することが、より一般的な要件です。

解決

サブクラスが初期化されるときに親クラスのコンストラクターを呼び出す方法。これまでの基盤と組み合わせると、答えは明らかです。

コンストラクタの借用(クラス継承)

クラス継承: サブタイプ コンストラクター内でスーパータイプ コンストラクターを呼び出します。

アイデアは比較的明確であり、問​​題によって推進されています。

プロトタイプチェーンのサブクラスは親クラスにパラメータを渡すことができないため、サブクラスが初期化されるときに親クラスを呼び出すだけで十分ではないでしょうか?

次に例を示します。

関数 Parent(年齢) {
  this.name = ['マイク'、'ジャック'、'スミス'];
  this.age = 年齢;
}
Parent.prototype.run = 関数(){
  this.name + ' は両方とも ' + this.age を返します。
};
関数 Child(年齢) {
  //親クラスを呼び出します Parent.call(this, age);
}
var child1 = 新しいChild(21);

これは初期化中のパラメータ転送のニーズを満たしますが、問題も明らかです。

child1.run //未定義

質問

親クラスのプロトタイプ属性が失われました

親クラスの初期化ではサンプルプロパティのみが継承され、プロトタイププロパティはサブクラスのプロトタイプチェーンで失われます。

解決

損失の理由は、プロトタイプ チェーンがポインターを変更しないためです。では、なぜポインターを変更しないのでしょうか?

コンポジション継承

定義: プロトタイプ チェーンを使用してプロトタイプ プロパティとメソッドの継承を実装し、コンストラクターを使用してインスタンス プロパティの継承を実装します。

例:

関数 Parent(年齢) {
  this.name = ['マイク'、'ジャック'、'スミス'];
  this.age = 年齢;
}
Parent.prototype.run = 関数(){
  this.name + ' は両方とも ' + this.age を返します。
};
関数 Child(年齢) {
  //親クラスのコンストラクターを呼び出します Parent.call(this, age);
}
Child.prototype = new Parent(); //プロトタイププロパティの継承 Child.prototype.constructor = Child
var child1 = 新しいChild(21);

この問題は次のように回避されます。

child1.run() // "マイク、ジャック、スミスは両方とも21です"

質問

機能が満たされたら、パフォーマンスに焦点を当てます。この継承方法の問題は、親クラスのコンストラクターが 2 回実行されることです。

彼らです:

関数 Child(年齢) {
  // 親クラスのコンストラクターを 2 回目に呼び出します。Parent.call(this, age);
}
Child.prototype = new Parent(); //最初に指しているプロトタイプチェーンを変更する

解決

自然な解決策は、1 つのコンストラクター呼び出しをキャンセルすることです。キャンセルするには、当然、2 つの実行を分析して、機能に重複があるかどうかを確認する必要があります。

1 回目はインスタンス プロパティとプロトタイプ プロパティも継承し、2 回目は親クラスのインスタンス プロパティも継承します。

したがって、2 回目は親クラスのパラメータが利用できないため、1 回目は親クラスのコンストラクターを呼び出さず、プロトタイプ プロパティのみを継承する方法についてのみ検討できます。

答えはもちろん「はい」です。以前のプロトタイプ継承はこの考えに基づいています。

寄生的組み合わせ継承

名前が示すように、寄生とはプロトタイプ プロパティを継承するメソッドを特定のメソッドにカプセル化することを指し、組み合わせとはコンストラクタ継承を組み合わせてプロトタイプ継承の欠点を補うことです。

許してください、ただ見てください:

関数createObj(o) {
  関数 F() { }
  F.プロトタイプ = o;
  新しいF()を返します。
}
//プロトタイププロパティの継承、つまりプロトタイプ継承関数 create(parent, child) { 
  var f = createObj(parent.prototype); //プロトタイプオブジェクトを取得する child.prototype = f
  child.prototype.constructor = child; //オブジェクトのプロトタイプを拡張します。つまり、元のコンストラクタが指し示すままにします}

関数 親(名前) {
  this.name = 名前;
  this.arr = ['兄弟', '姉妹', '両親'];
}
Parent.prototype.run = 関数(){
  this.name を返します。
};
関数 Child(名前, 年齢) {
  // 例のプロパティ Parent.call(this, name);
  this.age = 年齢;
}
// このメソッドではプロトタイプ プロパティの継承が寄生します create(Parent.prototype,Child);
var child1 = 新しい Child('trigkit4', 21);

このように、比較的完全な継承方法に到達するまで、問題を発見して解決するという考え方に従います。 ES メソッドについては、この記事では説明しません。

結論

たくさんの積み重ねがあってこそ、多くのことを達成できます。希望するオファーを受けたいなら、十分に準備し、しっかりとした基礎を築かなければなりません。あいまいにしないでください。原則は理解していますが、回答が不完全です。これは、まったく理解していないのとあまり変わりません。それほど新しくないこの時代に、毎週 3 つの知識ポイントを復習するという目標を設定してください。あなたが花を咲かせれば、蝶があなたのところにやって来ると信じてください。

以上が、JS継承の詳細な内容です。JS継承の詳細な内容については、123WORDPRESS.COMの他の関連記事にも注目してください。

以下もご興味があるかもしれません:
  • ネイティブ JavaScript 継承方法とその長所と短所の詳細な説明
  • JavaScript における継承の 3 つの方法
  • jsの継承の6つの方法を詳しく解説
  • JavaScriptで継承を実装するいくつかの方法
  • js で継承を実装する 5 つの方法
  • JavaScript におけるいくつかの継承方法の例
  • JavaScript継承の詳細な説明
  • JavaScript オブジェクト指向クラス継承ケースの説明

<<:  Linux での mysql および mysql.sock のインストールに関する問題

>>:  Linux システム ディレクトリ sys、tmp、usr、var の詳細な説明。

推薦する

Nginx でアンチホットリンクを設定するための手順を完了する

必要:通常、サイト側は、ウェブサイト上の動画や写真が盗まれるのを防ぎたいと考えています。結局のところ...

MySQL のレイテンシ問題とデータフラッシュ戦略プロセスの分析

目次1. MySQLレプリケーションプロセス2. MySQLの遅延問題の分析3. プロモーション期間...

MySQLデータのグループ化の詳細な説明

グループを作成グループ化は、SELECT ステートメントの GROUP BY 句で設定されます。例:...

Mybatisの特殊文字処理の詳細な説明

序文: Mybatis の特殊文字処理、Mybatis の xml ファイル内の特殊文字の処理、ここ...

ウェブサイトの画像にグレー効果を加える3つの方法

私はグレースケールの画像の方が芸術的に見えると思うので、いつもグレースケールの画像を好んで使っていま...

MySQL 5.6.23 のインストールと設定環境変数のチュートリアル

この記事では、MySQL 5.6.23のインストールと設定のチュートリアルを参考までに紹介します。具...

Dreamweaver で Zen コーディングを使用する方法

前回の記事「Zen Coding: HTML/CSS コードを素早く記述する方法」を公開した後、一部...

Html+CSS フローティング広告ストリップの実装

1.html部分コードをコピーコードは次のとおりです。 <!DOCTYPE html> ...

Vue で SVG アイコンを導入する 2 つの方法

Vue で SVG アイコンを導入する方法Vue で svg アイコンを導入する方法 1インストール...

Vueはフィルターを使用して日付をフォーマットします

この記事では、フィルターを使用して日付をフォーマットするVueの具体的なコードを参考までに紹介します...

HTMLウェブページテーブル構造化マークアップの応用に関する簡単な説明

Web テーブルの構造マークアップについて説明する前に、いくつかの画像を見てみましょう。 HTML ...

Dockerはjenkins+mavenコード構築および展開プラットフォームを構築します

目次Docker の基本概念Docker インストール プロセス (Centos6.9)カーネルのア...

VMware Workstation Pro が Win10 アップデートにより開けなくなる問題の解決方法

今夜の夕食後にノートパソコンの電源を入れたところ、問題が発生しました。通常、コンピューターがスリープ...

LinuxにNginxをインストールする詳細な手順

1. Nginxのインストール手順1.1 公式サイトの紹介http://nginx.org/en/d...

CSS3 列を使用したカード ウォーターフォール レイアウトを実装するためのサンプル コード

この記事では、カード ウォーターフォール レイアウトを実現するための CSS3 列のサンプル コード...