JavaScript を使用して寄生コンポーザブル継承を実装する方法
この記事では、主に JavaScript 寄生結合継承を紹介し、寄生結合継承の原理、実装方法、および関連する注意事項を例の形式で詳細に分析します。必要な友人は参考にしてください。継承。詳細は次のとおりです:
実際、「JavaScript Advanced Programming」という本にはすでに完全なコードが記載されています。コードを理解していれば、この継承が何であるかがわかります。
まず第一に、js ではオブジェクトの属性を定義する方法が 2 つあります:
//通过执行构造函数设置属性 function A(){ this.a = 1; } //通过原型设置属性 A.prototype.b = 1;
つまり:
クラス Sub が別のクラス Super を継承したい場合、親クラスのプロトタイプの下にある属性を継承する必要があります。 、また親クラスのコンストラクターも実行します。
つまり、クラス Sub が別のクラス Super を継承したい場合、プロトタイプ チェーンを通じてプロトタイプ属性とメソッドを継承するだけでなく、サブクラス コンストラクター内で親クラス コンストラクターを呼び出すことによってインスタンス属性も継承する必要があります。
1. プロトタイプ以下の属性を継承する
上記の通り、スーパークラスのプロトタイプ以下の属性は継承されないので、この部分は以下に継承する必要があります。 Direct "=" は絶対に機能しません。Sub.prototype のプロパティを変更した後は、Super.prototype のオブジェクトに影響を与えることはできません。つまり、Sub.prototype=Super.prototype
にすることはできません。 。
最初にオブジェクトのコピーを作成するメソッドを作成します
function object(o){ function A(){} A.prototype = o var ox = new A() return ox }
上記の関数によって取得されたオブジェクト ox は、オブジェクト o (プロトタイプ チェーン上) のすべての属性を持ち、ox の属性を変更しても o には影響しません。これは、oMade a copy を変更することと同じです。 Sub.prototype=Super.prototype
。
首先写一个创建对象副本的方法
function inherit(subType,superType){ var prototype=Object.create(superType.prototype); prototype.constructor=subType; subType.prototype=prototype; }
上面的函数得到的对象ox,拥有了对象o的全部属性(在原型链上),而修改ox的属性,不会影响到o,相当于把o复制了一份。
原型式继承就是上面的“object”函数,在很多类库源码中都能发现它的身影
简单而言,原型式继承就是不用实例化父类了,直接实例化一个临时副本实现了相同的原型链继承。(即子类的原型指向父类副本的实例从而实现原型共享)
tips:总所周知,原型链继承是子类的原型指向父类的实例从而实现原型共享,而原型式继承是子类的原型指向父类副本的实例从而实现原型共享。
ECMAScirpt 5通过新增Object.create()
方法规范化了原型式继承。
使用object方法,就可以将Super.prototype的属性「复制」到Sub.prototype上了,当然这儿还需要修正一下constructor的指向。
//父类 function Super(){ this.sss=1 } //子类 function Sub(){ //arguments是Sub收到的参数,将这个参数传给Super Super.apply(this, arguments) } //实例 sub = new Sub()
2. 分别执行父类和子类的构造函数,继承这部分下的属性:
function SuperType(name,colors){ this.name=name; this.colors=colors; } SuperType.prototype.getSuperProperty=function(){ return this.name; } function SubType(job,name,colors){ SuperType.call(this,name,colors); this.job=job; } SubType.prototype.getSubPrototype=function(){ return this.job; } function inherit(subType,superType){ var prototype=Object.create(superType.prototype); prototype.constructor=subType; subType.prototype=prototype; } inherit(SubType,SuperType); var instance=new SubType("doctor","John",["red","green"]); console.log(instance.getSubPrototype()); //输出"doctor" console.log(instance.getSuperProperty()); //输出"John",成功调用在父类原型定义的方法
Super.apply(this, arguments)
这一句,将Super类作为一个普通函数来执行,但是Super类的this被换成了Sub类的this,Sub收到的参数也传给了Super
最后执行结果相当于sub.sss=1
附上各种继承方式的特点和优缺点
曾经一段时间因为javascript关于类实现继承的不规范,导致各种各样实现继承的代码;而实际上不管代码怎么变,继承都基于两种方式:
1.通过原型链,即子类的原型指向父类的实例从而实现原型共享。
2.借用构造函数,即通过js的apply、call实现子类调用父类的属性、方法;
原型链方式可以实现所有属性方法共享,但无法做到属性、方法独享(例如Sub1修改了父类的函数,其他所有的子类Sub2、Sub3...想调用旧的函数就无法实现了);
而借用构造函数除了能独享属性、方法外还能在子类构造函数中传递参数,但代码无法复用。总体而言就是可以实现所有属性方法独享,但无法做到属性、方法共享(例如,Sub1新增了一个函数,然后想让Sub2、Sub3...都可以用的话就无法实现了,只能Sub2、Sub3...各自在构造函数中新增)。
组合继承就是把以上两种继承方式一起使用,把共享的属性、方法用原型链继承实现,独享的属性、方法用借用构造函数实现,所以组合继承几乎完美实现了js的继承;为什么说是“几乎”?因为认(dan)真(teng)的geek们发现组合继承有一个小bug,实现的时候调用了两次超类(父类),性能上不合格啊有木有!怎么解决呢?于是“寄生继承”就出来了。
寄生继承(原型式继承)就是不用实例化父类了,直接实例化一个临时副本实现了相同的原型链继承。(即子类的原型指向父类副本的实例从而实现原型共享)
“寄生组合继承”用了“寄生继承”修复了“组合继承”的小bug,从而让js完美实现继承了。
实例代码:
rrreee属性继承代码是SuperType.call(this,name,colors);
原型继承代码是inherit(SubType,SuperType);
Object.create()
メソッドを追加することにより、プロトタイプの継承を標準化します。 🎜🎜オブジェクト メソッドを使用すると、Super.prototype のプロパティを Sub.prototype に「コピー」できます。もちろん、ここでコンストラクターのポインティングを修正する必要もあります。 🎜rrreee🎜🎜2. 親クラスとサブクラスのコンストラクターをそれぞれ実行し、この部分の属性を継承します: 🎜🎜rrreee🎜Super.apply(this, argument)
この文では、次を使用します。 Superクラスをそのまま通常の関数を実行しますが、SuperクラスのこれをSubクラスのこれに置き換え、Subで受け取ったパラメータもSuperに渡します🎜🎜 最終的な実行結果はsub.sss=1と同等になります🎜🎜🎜メソッドの特徴、長所、短所を添付します🎜🎜🎜 JavaScriptがクラス実装の継承に関して標準化されていなかった時代があり、その結果、継承を実装するためのさまざまなコードが作成されましたが、実際には、コードがどのように変更されても、 、継承は 2 つの方法に基づいています:🎜🎜🎜 1. プロトタイプ チェーン🎜 を通じて、つまり、サブクラスのプロトタイプが親クラスのインスタンスを指し、プロトタイプの共有を実現します。 🎜2. コンストラクターを借用します🎜、つまり、js の apply と call を通じて、サブクラスは親クラスの属性とメソッドを呼び出すことができます🎜🎜🎜 プロトタイプ チェーン メソッドは、すべての属性とメソッドの共有を実現できます。ただし、属性とメソッドの共有は実現できません。 (たとえば、Sub1 は親クラスの関数を変更し、他のすべてのサブクラス Sub2、Sub3... は古い関数を呼び出すことができません)。 🎜 排他的なプロパティとメソッドに加えて、サブクラスのコンストラクターでパラメーターを渡すことができますが、コードを再利用することはできません。一般的に、すべての属性メソッドは排他的ですが、属性とメソッドを共有することはできません (たとえば、Sub1 が新しい関数を追加し、それを Sub2、Sub3... が使用できるようにすることはできません。コンストラクターにはそれぞれ Sub2、Sub3... のみを追加できます)。 🎜🎜結合継承とは、上記の 2 つの継承メソッドを併用することです。共有プロパティとメソッドはプロトタイプ チェーン継承を使用して実装され、排他的プロパティとメソッドは借用コンストラクターを使用して実装されます。したがって、結合継承は、「ほぼ完全に js 継承を実現します。」 「?」真面目にやっているオタクが、実装時にスーパークラス(親クラス)が2回呼ばれるバグがあることに気づいたので、性能が規格に達していない可能性はありますか?どうやって解決すればいいでしょうか?そこで出てきたのが「寄生遺伝」です。 🎜🎜🎜 寄生継承 (プロトタイプ継承) は、親クラスをインスタンス化する必要がなく、代わりに一時コピーが直接インスタンス化されて、同じプロトタイプ チェーンの継承を実現します。 (つまり、サブクラスのプロトタイプは親クラスのコピーのインスタンスを指し、プロトタイプの共有を実現します) 🎜🎜🎜 「寄生組み合わせ継承」は「寄生継承」を使用して「組み合わせ継承」の小さなバグを修正し、 js を使用して継承を完全に実装します。 🎜🎜コード例: 🎜rrreee🎜 属性継承コードは
SuperType.call(this,name,colors);
です🎜🎜 プロトタイプ継承コードは inherit(SubType,SuperType); です。 code> 🎜🎜上記は私があなたのためにまとめたものです。将来役立つことを願っています。 🎜🎜関連記事: 🎜<p><a href="http://www.php.cn/js-tutorial-402702.html" target="_blank">JS で衝突検出を実装する方法</a></p>
<p><a href="http://www.php.cn/js-tutorial-402705.html" target="_blank"> angular1 で gulp と bower で使用するにはどうすればよいですか? </a></p>
<p><a href="http://www.php.cn/js-tutorial-402707.html" target="_blank">js スクリプトをデバッグするにはどのような方法がありますか? </a></p>
<p><a href="http://www.php.cn/js-tutorial-402709.html" target="_blank">Angularを使用して検索ボックスを実装する方法</a></p>
<p><a href="http://www.php.cn/js-tutorial-402711.html" target="_blank">vueでの補間の詳細な紹介</a></p>
以上がJavaScript を使用して寄生コンポーザブル継承を実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









関数の継承では、「基底クラス ポインター」と「派生クラス ポインター」を使用して継承メカニズムを理解します。基底クラス ポインターが派生クラス オブジェクトを指す場合、上方変換が実行され、基底クラスのメンバーのみにアクセスされます。派生クラス ポインターが基本クラス オブジェクトを指す場合、下向きキャストが実行される (安全ではない) ため、注意して使用する必要があります。

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

継承エラーのデバッグのヒント: 正しい継承関係を確認します。デバッガーを使用してコードをステップ実行し、変数値を調べます。仮想修飾子を正しく使用してください。隠れた相続によって引き起こされる相続ダイアモンド問題を調べてください。抽象クラスに実装されていない純粋仮想関数がないか確認します。

C++の関数継承を詳しく解説:「is-a」と「has-a」の関係をマスターしよう 関数継承とは?関数の継承は、派生クラスで定義されたメソッドを基本クラスで定義されたメソッドに関連付ける C++ の手法です。これにより、派生クラスが基本クラスのメソッドにアクセスしてオーバーライドできるようになり、基本クラスの機能が拡張されます。 「is-a」および「has-a」関係 関数継承では、「is-a」関係は、派生クラスが基本クラスのサブタイプであること、つまり、派生クラスが基本クラスの特性と動作を「継承」することを意味します。基本クラス。 「has-a」関係は、派生クラスに基本クラス オブジェクトへの参照またはポインターが含まれていること、つまり、派生クラスが基本クラス オブジェクトを「所有」していることを意味します。構文関数継承を実装する方法の構文は次のとおりです: classDerivedClass:pu

継承とポリモーフィズムはクラスの結合に影響します。派生クラスは基本クラスに依存するため、継承により結合が増加します。ポリモーフィズムにより、オブジェクトは仮想関数と基本クラス ポインターを通じて一貫した方法でメッセージに応答できるため、結合が軽減されます。ベスト プラクティスには、継承を控えめに使用すること、パブリック インターフェイスを定義すること、基本クラスへのデータ メンバーの追加を回避すること、依存関係の注入を通じてクラスを分離することが含まれます。ポリモーフィズムと依存性注入を使用して銀行口座アプリケーションの結合を軽減する方法を示す実践的な例。

JavaScript で HTTP ステータス コードを取得する方法の紹介: フロントエンド開発では、バックエンド インターフェイスとの対話を処理する必要があることが多く、HTTP ステータス コードはその非常に重要な部分です。 HTTP ステータス コードを理解して取得すると、インターフェイスから返されたデータをより適切に処理できるようになります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法と、具体的なコード例を紹介します。 1. HTTP ステータス コードとは何ですか? HTTP ステータス コードとは、ブラウザがサーバーへのリクエストを開始したときに、サービスが

オブジェクト指向プログラミングとは何ですか?オブジェクト指向プログラミング (OOP) は、現実世界のエンティティをクラスに抽象化し、オブジェクトを使用してこれらのエンティティを表すプログラミング パラダイムです。クラスはオブジェクトのプロパティと動作を定義し、オブジェクトはクラスをインスタンス化します。 OOP の主な利点は、コードの理解、保守、再利用が容易になることです。 OOP の基本概念 OOP の主な概念には、クラス、オブジェクト、プロパティ、メソッドが含まれます。クラスはオブジェクトの設計図であり、オブジェクトのプロパティと動作を定義します。オブジェクトはクラスのインスタンスであり、クラスのすべてのプロパティと動作を備えています。プロパティは、データを保存できるオブジェクトの特性です。メソッドは、オブジェクトのデータを操作できるオブジェクトの関数です。 OOP の利点 OOP の主な利点は次のとおりです。 再利用性: OOP はコードをより高度なものにすることができます。

インターフェイス: 実装のないコントラクト インターフェイスは、Java でメソッド シグネチャのセットを定義しますが、具体的な実装は提供しません。これは、インターフェイスを実装するクラスに、その指定されたメソッドを強制的に実装するコントラクトとして機能します。インターフェイス内のメソッドは抽象メソッドであり、メソッド本体はありません。コード例: publicinterfaceAnimal{voideat();voidsleep();} 抽象クラス: 部分的に実装されたブループリント 抽象クラスは、そのサブクラスによって継承できる部分的な実装を提供する親クラスです。インターフェイスとは異なり、抽象クラスには具体的な実装と抽象メソッドを含めることができます。抽象メソッドは、abstract キーワードを使用して宣言され、サブクラスによってオーバーライドされる必要があります。コード例: publicabstractcla
