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 sql_modeの適切な設定に関する詳細な説明

MySQL sql_modeの適切な設定sql_mode は見落とされやすい変数です。デフォルト値は...

Javascript Bootstrapのグリッドシステム、ナビゲーションバー、カルーセルの詳細な説明

目次ブートストラップと関連コンテンツの紹介グリッドシステムネストされた列列オフセット列の並べ替えナビ...

MySQLデッドロック問題の詳細な分析

序文私たちのビジネスがまだ初期段階にあり、同時実行の度合いが比較的低い場合、数年間はデッドロックの問...

nginx + セカンダリドメイン名 + https サポートを使用する

ステップ1: Alibaba Cloudプライマリドメイン名にセカンダリドメイン名を追加する2 番目...

JS配列の一般的な方法とテクニックを学び、マスターになりましょう

目次splice() メソッドjoin() メソッド逆() メソッドevery() メソッド削減()...

解決策 - BASH: /HOME/JAVA/JDK1.8.0_221/BIN/JAVA: 権限が不十分です

1) jdkファイルが保存されているフォルダパスを入力します私はここにいますusr/local/jd...

MySQL インデックス障害の上位 10 の問題の概要

目次背景1. クエリ条件に「or」が含まれているため、インデックスが失敗する可能性があります。 2....

Windows10のマウスを模倣して境界線を光らせる効果を実現するCSSの詳細解説

最新の Windows 10 アップデートをインストールした後、システム UI の詳細な効果が顕著に...

ウェブデザインと制作に関する科学的原則と提案の要約

<br />ネットワーク設計の分野では、アイトラッキングに関する研究が非常に盛んに行われ...

MySQL 起動エラーを解決する: エラー 2003 (HY000): 'localhost' の MySQL サーバーに接続できません (10061)

このエラーは初心者によく発生します。この記事では主に、エラー 2003 (HY000): '...

誰もが知っておくべきウェブサイトのユーザビリティに関する 10 のヒント

これ以上時間を無駄にせず、早速本題に入りましょう。 1. ロゴに代替テキストを追加するこれには 2 ...

CSSで特殊なグラフィックを描く方法

1. 三角形境界線の設定 コード: 幅: 300ピクセル; 高さ: 300px; 背景: 赤; 境界...

MySQL データ型 DECIMAL(N,M) における N と M の意味の詳細な説明

同僚から、MySQL データ型 DECIMAL(N,M) の N と M の意味を尋ねられました。言...

ページングのどのページでMySQLのレコードをクエリするか

序文実際には、次のような問題に遭遇する可能性があります。特定のレコードの ID がわかっていて、その...

CentOSにDockerをインストールする方法

ここでは比較的簡単なインストール方法のみを紹介します。 1. yumを使用してインストールするyum...