JavaScript を使用して寄生コンポーザブル継承を実装する方法

亚连
リリース: 2018-06-13 14:40:59
オリジナル
1527 人が閲覧しました

この記事では、主に 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);

プロトタイプの継承は、多くのクラス ライブラリのソース コードで見られる、上記の「オブジェクト」関数です。

簡単に言うと、プロトタイプの継承は、親クラスをインスタンス化する必要はなく、同じプロトタイプ チェーンの継承を直接インスタンス化します。 。 (つまり、サブクラスのプロトタイプは、プロトタイプの共有を実現するために、親クラスのコピーのインスタンスを指します)

🎜ヒント:🎜 ご存知のとおり、プロトタイプ チェーンの継承は、サブクラスのプロトタイプがインスタンスを指すことを意味します。プロトタイプの共有を実現するための親クラスのプロトタイプの継承、および 🎜プロトタイプの継承 サブクラスのプロトタイプは、プロトタイプの共有を実現するための親クラスのコピーのインスタンスを指します🎜。 🎜🎜ECMAScirpt 5 は、新しい 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 サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート