js で継承を実装する 5 つの方法

js で継承を実装する 5 つの方法

コンストラクタの借用

この手法の基本的な考え方は単純です。サブタイプ コンストラクター内からスーパータイプ コンストラクターを呼び出します。また、関数は特定の環境でコードを実行するオブジェクトにすぎないため、apply() メソッドと call() メソッドを使用すると、新しく作成されたオブジェクトでコンストラクターを実行することもできます。

関数 Box(名前){
 this.name = 名前
}
ボックスプロトタイプ年齢 = 18

関数デスク(名前){
 Box.call(this, name) // オブジェクトの偽装、オブジェクトの偽装はコンストラクタ内の情報のみを継承できます}

var デスク = 新しいデスク('ccc')
console.log(desk.name) // --> ccc
console.log(desk.age) // --> 未定義

このことから、インスタンス プロパティのみが継承され、プロトタイプのプロパティにはアクセスできないことがわかります。このパターンは 2 つの問題を解決します。パラメータの受け渡しと継承は可能ですが、プロトタイプがないと再利用できません。

コンポジション継承

関数 Box(名前){
 this.name = 名前
}
Box.prototype.run = 関数 (){
 console.log(this.name + '実行中...')
}

関数デスク(名前){
 Box.call(this, name) // オブジェクトの偽装}

Desk.prototype = new Box() // プロトタイプチェーン var desk = new Desk('ccc')
console.log(desk.name) // --> ccc
desk.run() // --> ccc が実行中です...

この継承方法の背後にある考え方は、プロトタイプ チェーンを使用してプロトタイプ プロパティとメソッドを継承し、コンストラクターを使用してインスタンス プロパティを継承することです。

プロトタイプ継承

プロトタイプの継承: プロトタイプを使用すると、カスタム タイプを作成しなくても、既存のオブジェクトに基づいて新しいオブジェクトを作成できます。これについて言えば、ある人物について言及しなければなりません。Douglas Crockford 氏は、2006 年に執筆した記事「Javascript でのプロトタイプ継承」で、次のようなメソッドを紹介しました。

function object(o) { // リテラル関数を渡す function F(){} // コンストラクターを作成する F.prototype = o; // リテラル関数をコンストラクターのプロトタイプに割り当てる return new F() // 最後にインスタンス化されたコンストラクターを返す }

次の例を考えてみましょう。

関数obj(o) {
 関数F(){}
 F.プロトタイプ = o;
 新しいF()を返す
}

var ボックス = {
 名前: 'ccc',
 年齢: 18歳
 家族: ['兄弟','姉妹']
}

var box1 = obj(ボックス)
console.log(box1.name) // --> ccc
box1.family.push('姉妹')
console.log(box1.family) // --> ["兄弟", "姉妹", "姉妹"]

var box2 = obj(ボックス)
console.log(box2.family) // --> ["兄弟", "姉妹", "姉妹"]

上記コードの実装ロジックはプロトタイプチェーン継承と非常に似ているため、参照配列、つまりファミリ属性が共有されます。

寄生遺伝

関数obj(o) {
 関数F(){}
 F.プロトタイプ = o;
 新しいF()を返す
}
関数create(o){
 var clone = obj(o) // 関数を呼び出して新しいオブジェクトを作成します clone.sayName = function(){ // 何らかの方法でこのオブジェクトを強化します console.log('hi')
 }
 return clone // このオブジェクトを返す }

var 人 = {
 名前: 'ccc',
 友達: ['aa','bb']
}

var anotherPerson = create(人)
anotherPerson.sayName() // --> こんにちは

この例のコードは、person に基づいて新しいオブジェクト anotherPerson を返します。新しいオブジェクトには person のすべてのプロパティとメソッドがあるだけでなく、独自の sayHi() メソッドもあります。寄生継承は、カスタム型やコンストラクターではなくオブジェクトを主に考慮する状況でも役立つパターンです。寄生継承を使用してオブジェクトに関数を追加すると、関数を再利用できないため効率が低下します。これはコンストラクター パターンに似ています。

寄生的組み合わせ継承

前述したように、複合継承は JavaScript で最も一般的に使用される継承モードですが、独自の欠点もあります。複合継承の最大の問題は、状況に関係なく、スーパータイプ コンストラクターが 2 回呼び出されることです。1 回はサブタイプ プロトタイプを作成するときに、もう 1 回はサブタイプ コンストラクター内で呼び出されます。はい、サブタイプには最終的にスーパータイプ オブジェクトのすべてのインスタンス プロパティが含まれますが、サブタイプ コンストラクターを呼び出すときにこれらのプロパティを書き換える必要があります。次の例を見てみましょう。

関数SuperType(名前){
 this.name = 名前;
 this.colors = ['赤','黒']
}
SuperType.prototype.sayName = 関数 (){
 console.log(この名前)
}
関数 SubType(名前, 年齢){
 SuperType.call(this, name) // SuperType への 2 回目の呼び出し
 this.age = 年齢
}

SubType.prototype = new SuperType() // SuperTypeへの最初の呼び出し
SubType.prototype.constructor = サブタイプ
SubType.prototype.sayAge = 関数 (){
 コンソールログ(this.age)
}

SuperType コンストラクターが初めて呼び出されると、SubType.prototype は name と colors という 2 つのプロパティを取得します。これらはすべて SuperType のインスタンス プロパティですが、現在は SubType のプロトタイプに配置されています。 SubType コンストラクターが呼び出されると、SuperType コンストラクターが再度呼び出され、新しいオブジェクトにインスタンス属性の名前と色が再度作成されます。したがって、これら 2 つのプロパティは、プロトタイプ内の同じ名前を持つ 2 つのプロパティをマスクします。つまり、名前と色の属性のセットが 2 つあります。1 つはインスタンスにあり、もう 1 つはプロトタイプにあります。これは、SuperType コンストラクターを 2 回呼び出した結果です。この問題の解決策は寄生的組み合わせ継承です。
いわゆる寄生的な組み合わせ継承とは、コンストラクタを借用してプロパティを継承し、プロトタイプ チェーンのハイブリッド形式を通じてメソッドを継承することです。この背後にある基本的な考え方は、サブタイプのプロトタイプを作成するためにスーパータイプのコンストラクターを呼び出す必要はなく、必要なのはスーパータイプのプロトタイプのコピーだけであるということです。基本的に、寄生継承を使用してスーパータイプのプロトタイプから継承し、その結果をサブタイプのプロトタイプに割り当てます。寄生複合遺伝の基本的なパターンは次のとおりです。

関数オブジェクト(o) {
 関数F(){}
 F.プロトタイプ = o;
 新しいF()を返す
}
関数 inheritPtototype(サブタイプ、スーパータイプ){
 var prototype = object(superType.prototype) // オブジェクトを作成 prototype.constructor = subType // オブジェクトを拡張 subType.prototype = prototype // オブジェクトを指定 }

関数SuperType(名前){
 this.name = 名前
 this.colors = ['赤', '白']
}

SuperType.prototype.sayName = function(){
 console.log(この名前)
}

関数 SubType(名前,年齢){
 SuperType.call(これ、名前)
 this.age = 年齢
}

継承Ptototype(サブタイプ、スーパータイプ)

SubType.prototype.sayAge = function(){
 コンソールログ(this.age)
}

var インスタンス = 新しいサブタイプ ('ccc'、18)

instance.sayName() // --> ccc
instance.sayAge() // --> 18
console.log(インスタンス)

コンソールによって出力される構造:

詳細図:

この例の効率性は、SuperType コンストラクターを 1 回だけ呼び出すため、SubType.prototype に不要な冗長プロパティが作成されないことです。同時に、プロトタイプ チェーンは変更されないため、instanceof と isPrototypeOf() は引き続き正常に使用できます。これは多くの大企業が採用している継承方法でもあります。

以上がjsで継承を実装する5つの方法の詳細です。js継承の詳細については、123WORDPRESS.COMの他の関連記事にも注目してください。

以下もご興味があるかもしれません:
  • ネイティブ JavaScript 継承方法とその長所と短所の詳細な説明
  • JavaScriptで継承を実装するいくつかの方法
  • JS継承の実装方法とメリット・デメリットを詳しく解説
  • JavaScript クラス継承の複数の実装方法
  • JavaScriptはプロトタイププロパティを使用して継承操作を実装する例
  • JavaScriptを使用して継承を実装する方法

<<:  Linux ファイルシステムの説明: ext4 以降

>>:  テーブルパーティションとパーティション分割とは何ですか?MySqlデータベースパーティションとテーブルパーティション分割方法

推薦する

MySQL のクエリパフォーマンスに対する制限の影響

I. はじめにまず、MySQL のバージョンについて説明します。 mysql> バージョンを選...

Mysql GTID Mha 設定方法

Gtid + Mha + Binlog サーバー構成: 1: テスト環境OS: CentOS 6.5...

SpringBoot のパッケージ化と Docker へのアップロード、およびマルチインスタンス デプロイメントの実装に関する簡単な分析 (IDEA バージョン)

最近友人からDockerを触ったことがあるかと聞かれました。あまり自信がなかったので答えられませんで...

MySQL で CURRENT_TIMESTAMP を使用する方法

目次CURRENT_TIMESTAMPの使用CURRENT_TIMESTAMPを使用したタイムスタン...

jsonファイルの書き方の詳細説明

目次JSONとはなぜこの技術なのでしょうか? JSONの使い方- データ形式- メモ- JSには2つ...

CSSオーバーフローメカニズムについての簡単な説明

CSS オーバーフローのメカニズムを詳細に学ぶ必要があるのはなぜですか?実際の開発プロセスでは、コン...

7つのMySQL JOINタイプのまとめ

始める前に、これから紹介する JOIN タイプを示すために 2 つのテーブルを作成します。テーブルを...

MySQL全文インデックスを使用して検索エンジンのサンプルコードの簡易版を実現する

序文全文インデックスを使用できるのは Innodb と MyISAM ストレージ エンジンのみです ...

Linux システムに 3 つ以上の Tomcat をインストールする (詳細な手順)

複数のTomcatをインストールする場合は、システムにJDKがインストールされている必要があり、 T...

Dockerで同じIDを持つ2つのイメージを削除する

今日 Docker コンテナを作成したとき、誤ってイメージの名前を間違って入力しました。その結果、コ...

Vue の基本入門: Vuex のインストールと使用

目次1. vuexとは何か2. インストールと導入3. vuexの使用4. プロセスの紹介5. 突然...

LinuxサーバーでRabbitMQ管理ページにアクセスできない問題を解決

私のプロジェクトの特定の機能ではサーバーが rabbitmq にメッセージを送信する必要があるため、...

Vmvare 仮想マシンを使用して Ubuntu のルート ディレクトリをパーティション分割する方法の紹介

目次序文根拠手順1. CDから仮想マシンを起動する2. GPartedツールを使用してパーティション...

Windows での Nginx のインストールと環境設定 (nginx をサービスとして実行)

最初で最も重要なステップは、Windows 環境に Ngnix サービスをインストールする方法です。...

Vueはプルダウンを実装してさらに読み込む

Element-UI に慣れた開発者なら、無限スクロールの InfiniteScroll が使いにく...