JavaScriptによくある継承方式のまとめ


プロトタイプチェーン機構:
ECMAscriptでは、プロトタイプチェーンの概念を説明し、プロトタイプチェーンを継承を実現する主な方法として使用しています。
コンストラクターとプロトタイプとは、実例との関係があります。
各コンストラクタにはプロトタイプオブジェクトがあり、プロトタイプオブジェクトにはコンストラクタを指すポインタが含まれていますが、例としてはプロトタイプオブジェクトを指す内部ポインタが含まれています。propto。関係図は下の図のようになります。

各FunctはObjectベースの一例ですので、Functごとに一つの__u uがあります。プロト.Object.prototypeを指しました。
インスタンスの属性を検索すると、このインスタンスのカスタム属性から検索します。ない場合は、__uを通じて検索します。プロト.例の属する種類の原型を探しに行きます。まだないなら原型を通します。プロト.属性)の__uプロト.Objectの原型に行って探して、1級の1級の探すこと、もしないならundefined。
したがって、参照タイプ間の継承はプロトタイプチェーン機構によって達成される。
一.原型継承
プロトタイプ引継ぎ:親類の私有+共有の属性と方法を、サブクラス共有の属性とします。
コア:親の私有+共有の属性を同じ部分にクローンするのではなく、サブクラスの共有です。彼はクゥを通していますプロト.子と子の間のプロトタイプチェーンを構築し、子クラスの例が親の属性と方法を使用する必要がある場合は、__u uプロト.一級を探して使います。 

function Parent(){
  this.x = 199;
  this.y = 299;
}
Parent.prototype.say = function(){
  console.log('say')
}
function Child(){
  this.g = 90;
}
Child.prototype = new Parent();
var p = new Parent();
var c = new Child();
console.dir(c)
実现の本质は、原型の対象を书き直して、子类の原型を父类の実例に向けることによって、子类の実例は_u u u u u u u u u u u u uプロト.Child.prototype、つまりPartの例にアクセスすれば、親のプライベートな方法にアクセスできます。そしてまた_u u u u u u uを通過しますプロト.親タイプのプロトタイプを指すと、親タイプの原型に入る方法があります。
このようにして、親の私有、公有の方法、属性をすべてサブクラスの共有属性とすることができる。こうしてプロトタイプチェーンによって継承されました。
しかし、デフォルトのプロトタイプはすべてObjectを継承しているので、サブクラスはすべてObjectにアクセスできる方法はtostring()、valueOf()などです。
結果は下図のようになります。

サブクラスに新しい方法を追加したり、親タイプを書き換える方法が必要な場合は、必ず元の形を変えた文を入れてから記入します。

function Parent(){
  this.x = 199;
  this.y = 299;
}
Parent.prototype.say = function(){
  console.log('say')
}
function Child(){
  this.g = 90;
}
/*Child.prototype.Bs = function(){
  console.log('Bs')
}*/                            ,            
Child.prototype = new Parent();
Child.prototype.constructor=Child//       Child           constructor  ,         ,     ,      
Child.prototype.Bs = function(){
  console.log('Bs')
}
Child.prototype.say = function(){
  console.log('    ')
}
var p = new Parent();
var c = new Child();
console.dir(c)
c.Bs() //Bs
c.say()  //     
p.say() //say               
存在する問題:
1.サブクラスの親クラスの属性と方法は、親類のプライベート属性と共有方法を自分の共有属性と方法として扱うことであり、基本データタイプを操作する時には値を操作し、データタイプを操作する時には住所を操作することであり、親類のプライベート属性の中でタイプの属性を参照すると、彼は布団類を継承する際に共有属性として扱います。このような属性を操作すると、サブクラス2に影響を与えます。
2.サブクラスのインスタンスを作成する場合、パラメータは親タイプのコンストラクタに渡されません。すべてのオブジェクトインスタンスに影響を及ぼさないで、親のような構造関数にパラメータを伝達する方法がないということです。
したがって、実際には単独で原型を使うことは少ない。
二.call引継ぎ
方法のthis指向を変えながら方法を実行します。サブコンストラクタにおいては、親類のプライベートをサブクラスのプライベートにすることができます。

function Parent() {
  this.x = 100;
  this.y = 199;
}
Parent.prototype.fn = function() {}
 
function Child() {
  this.d = 100;
  Parent.call(this); //      this      
}
var p = new Parent();
var c = new Child();
console.log(p) //Parent {x: 100, y: 199}
console.log(c) //Child {d: 100, x: 100, y: 199}
サブクラスのコンストラクタでは、親の種類のthis指向を変えて、サブクラスの例に変えて、父の種類の方法を実行します。このようにして、父のクラスのthis.xはサブクラスの実例となります。xは、この方法によって父のクラスのプライベート属性を継承することができ、父のクラスのプライベート属性と方法を継承することができます。
三.なりすまし相続
親クラスのインスタンスを巡回し、親クラスのインスタンスのプライベートな方法をすべて持ってサブクラスのインスタンスに追加することは、オブジェクトの継承に偽る原理である。

function Parent(){
  this.x = 100;
}
Parent.prototype.getX = function(){
  console.log('getX')
}
function Child(){
  var p = new Parent();
  for(var attr in p){//for in                 
    this[attr] = p[attr]
  }
  //                ,                     
  /*if(e.hasOwnProperty(attr)){
    this[attr] = e[attr]
  }
  e.propertyIsEnumerable()*///     ==>             
}
var p = new Parent();
var c = new Child();
console.dir(c)
for inはオリジナルの共有カスタム属性を遍歴することができますので、彼はプライベートと共有の属性と方法を入手できます。しかし、ハスOwnPropertyの判断をしないなら、父類の共有と私有のものを全部持ってきて私有にします。
四.混合引継ぎ
カルル継承と原型継承を集合させ、私有でも公有でも持ってきた。しかし、問題があるのは、子の原型には親の私有属性が多くなっていますが、問題はありません。サブクラスの私有属性も同じセットがありますので、コールで引き継いで持ってきました。

function Parent(){
  this.x=100;
}
Parent.prototype.getX = function(){}
function Child(){
  Parent.call(this);
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
var p = new Parent();
var c = new Child();
console.log(c)//Child {x: 100}
存在する問題:
いずれにしても、2回のコンストラクタを呼び出します。1回はサブタイプのプロトタイプを作成する時、もう1回はサブタイプのコンストラクタの内部にあります。間違いなく、サブタイプは最終的には親タイプのオブジェクトの全部のインスタンス属性を含みますが、サブクラスのコンストラクタを呼び出した時にこれらの属性を書き換えなければなりません。
もう一つはcall+コピー継承です。

//    :call  +    
  function extend(newEle,oldEle){
    for(var attr in oldEle){
      newEle[attr]=oldEle[attr];
    }
  }
  function F(){
    this.x=100;
    this.showX=function(){}
  }
  F.prototype.getX=function(){};
  F.prototype.getX1=function(){};
  var f1=new F;
  console.dir(f1)
  function S(){
    F.call(this)//call  
  }
  extend(S.prototype, F.prototype);//    
  S.prototype.cc=function(){ }
  var p1=new S;
  console.dir(p1);
このように、call継承を使って親類のプライベート方法を継承し、for inコピーを使って親類の共有属性と方法を継承するのが実用的です。
五.中間部品引継ぎ
中間継手とはプロトタイプチェーンを通す仕組みで、サブタイプのプロトタイプです。プロト.本来はObject.prototypeを直接指すべきです。
父類の原型からの_u u uプロト.Object.prototypeに行ってもいいです。父類.prototypeに留まりました。父類.prototypeは中間部品ですので、子類は父類の共有方法を継承して自分の共有方法とします。

function Parent(){
  this.x = 100;
}
Parent.prototype.getX = function(){}
function Child(){
  
}
Child.prototype.__proto__ = Parent.prototype;
var p = new Parent();
var c = new Child()
console.log(c)
六.寄生組合式継承
寄生式グループ:call継承+Object.creat()
寄生結合式継承とは、構造関数を用いて属性を継承し、プロトタイプチェーンの混合形式によって継承する方法である。
基本的な考え方は、サブタイプのプロトタイプを指定するために、親タイプの構造関数を呼び出す必要がないということです。私たちが必要なのは、親タイプのプロトタイプのコピーです。
本質的には、寄生式を使って父種の原型を継承し、結果をサブタイプの原型に指定します。

function F(){
  this.x=100;
}
F.prototype.showX=function(){};
function S(){
  this.y = 200
  F.call(this)//       ;
}
function inheritPrototype(subType,superType){
  var prototype = Object.create(superType.prototype);//    
  prototype.constructor = subType;//    
  subType.prototype = prototype;//    
}
inheritPrototype(S,F)
var p1=new S;
console.dir(p1)
1、第一歩は親タイプの原型を作成するコピーです。
2、第二ステップは、作成したコピーのためにconstructorの属性を追加し、原型の書き換えによって失われたデフォルトのconstructorの属性を補いました。
3、第3ステップは、作成したオブジェクトをサブタイプの原型に割り当てます。
この例の高効率化は彼がSuperType構造関数を一回だけ呼び出したことによって、SubType.prototype上に不必要な、余分な属性を作成することを避けた。また、プロトタイプチェーンは変わらないので、instance ofとisProttypeOf()を正常に使用できるので、寄生グループ継承は引用タイプの一番理想的な継承方法です。
七.クラス継承
classはextensのキーワードを通じて継承を実現できます。これはES 5のプロトタイプチェーンを修正することにより継承を実現します。

class Father{
  constructor(x, y) {
     this.x = x;
     this.y = y;
  }

  toString() {
     return '(' + this.x + ', ' + this.y + ')';
  }
}
class Son extends Father{
  constructor(x,y,color){
     super(x,y); //      constructor(x, y)
     this.color = color;
  }
  toString() {
        console.log( super.toString()+this.color); //      toString()
  }
}
let son = new Son(3,4,'red');
son.toString();//   (3,4)red
上のコードは、1つのSonクラスを定義しています。このクラスは、extensキーワードを通じて、Fatherクラスのすべての属性と方法を継承しています。
上のコードの中で、constructor方法とtostring方法の中にsuperキーワードが現れています。ここでは父の種類の構造関数を表して、父の種類のthisオブジェクトを新規作成します。
サブクラスはconstructorメソッドでsuperメソッドを呼び出す必要があります。そうでないと、新しいインスタンスを作成する時にエラーが発生します。これは、サブクラスの自分のthisオブジェクトは、父親の構造関数を介して、最初に作成し、父親と同じインスタンスの属性と方法を得て、その後、それを加工し、サブクラスの自分のインスタンスの属性と方法を加える必要があります。superメソッドを起動しないと、サブクラスはthisオブジェクトを得られません。
以上はJavaScriptによくある継承方式のまとめの詳細です。JavaScript継承方式に関する資料は他の関連記事に注目してください。