ECMAScript 6-Classの継承

5636 ワード

基本的な使い方


Class間ではextendsのキーワードで継承を実現できます.これはES 5のプロトタイプチェーンの修正による継承よりも、明確で便利です.
class Test extends Component {}

上記のコードは、Testクラスを定義し、extendsキーワードを介してComponentクラスのすべての属性と方法を継承します.しかし、コードが配置されていないため、この2つのクラスは完全に同じであり、Componentクラスがコピーされたことに等しい.次に、Testの内部にコードを追加します.
class Test extends Component {
  constructor(props) {
    super(props); //  constructor(props)
  }
  
  toTest() {
    super.toTest(); //  toTest()
  }
}

上記のコードでは、constructorメソッドとtoTestメソッドの両方に、親の構造関数を表し、親のthisオブジェクトを新規作成するためのsuperキーワードが表示されます.
サブクラスは、constructorメソッドでsuperメソッドを呼び出さなければなりません.そうしないと、インスタンスを新規作成するとエラーが発生します.これは、子が自分のthisオブジェクトを持たず、親のthisオブジェクトを継承して加工するためである.superメソッドを呼び出さないと、サブクラスはthisオブジェクトを取得できません.
class Component {}

class Test extends Component {
  cosntructor() {
    
  }
}

let a = new Test();

上記のコードでは、Testは親Componentを継承していますが、そのコンストラクション関数はsuperメソッドを呼び出さず、新しいインスタンス・タイムズが間違っています.
ES 5の継承は、本質的には、サブクラスのインスタンスオブジェクトthisを作成した後、親のメソッドをthisに追加する(Parent.apply(this)).ES 6の継承メカニズムはまったく異なり、実質的には、親のインスタンスオブジェクトthisを作成し(したがって、superメソッドを呼び出す必要がある)、次いで、thisをサブクラスの構造関数で変更する.
サブクラスがconstructorメソッドを定義していない場合、このメソッドはデフォルトで追加されます.コードは次のとおりです.すなわち、明示的な定義があるかどうかにかかわらず、どのサブクラスにもconstructorの方法がある.
constructor(...args) {
  super(...args);
}

もう1つ注意しなければならないのは、サブクラスのコンストラクション関数でsuperを呼び出した後にのみthisキーワードを使用できます.そうしないと、エラーが発生します.これは、サブクラスインスタンスの構築が、親インスタンスの加工に基づいており、superメソッドのみが親インスタンスを返すためです.
class Component {
  constructor(props) {
    this.props = props;
  }
}

class Test extends Component {
  cosntructor(props, a) {
    this.a = a; // ReferenceError
    super(props);
    this.a = a; //  
  }
}

上記のコードでは、サブクラスのconstructorメソッドがsuperを呼び出さない前に、thisキーワードを使用し、結果をエラーとして報告し、superメソッドの後に置くのが正しい.

クラスのprototypeプロパティとprotoプロパティ


ほとんどのブラウザのES 5インプリメンテーションでは、各オブジェクトには__proto__のプロパティがあり、対応するコンストラクション関数のprototypeのプロパティを指します.Classは、構造関数の構文糖として、prototype属性と__proto__属性を同時に有するため、2つの継承鎖が同時に存在する.
  • サブクラスの__proto__属性は、構造関数の継承を表し、常に親
  • を指す.
  • サブクラスprototype属性の__proto__属性は、メソッドの継承を示す、常に親クラスのprototype属性
  • を指す.
    class A { }
    
    class B extends A { }
    
    B.__proto__ === A;  // true
    B.prototype.__proto__ === A.prototype;  // true
    

    上記のコードでは、サブクラスB__proto__属性は親クラスAを指し、サブクラスBprototype属性は親クラス__proto__A属性を指す.

    Extendsの継承目標

    prototypeキーワードの後には、複数のタイプの値を付けることができます.
    class B extends A {}
    

    上のコードのextendsは、Aの属性を持つ関数であれば、prototypeに継承されます.関数にはBの属性(prototypeの関数を除く)があるため、Function.prototypeは任意の関数であってもよい.
    以下、3つの特殊な状況について議論する.
    第1の特殊な場合、サブクラスはAクラスを継承する.
    class A extends Object {
      
    }
    
    A.__proto__ === Object;  // true
    A.prototype.__proto__ === Object.prototype;  // true
    

    この場合、Objectは構造関数Aの複製であり、Objectの例はAの例である.
    第2の特殊な状況では、継承は存在しません.
    class A {}
    
    A.__proto__ === Function.prototype;  // true
    A.prototype.__proto__ === Object.prototype;  // true
    

    この場合、Objectはベースクラス(すなわち、継承は存在しない)として通常の関数であるため、Aを直接継承する.しかし、Funciton.prototypeが呼び出されると、空のオブジェクト(すなわち、Aのインスタンス)が返されるので、Objectは、コンストラクション関数(A.prototype.__proto__)のObject属性を指す.
    第3の特殊な場合、サブクラスはprototypeを継承する
    class A extends null {
      
    }
    
    A.__proto__ === Function.prototype;  // true
    A.prototype.__proto__ === undefined;  // true
    

    この状況は第2の状況と非常に似ている.nullも一般的な関数なので、Aを直接継承します.ただし、Funciton.prototype呼び出し後に返されるオブジェクトはメソッドを継承しないため、A__proto__を指し、すなわち実質的に次のコードが実行される.
    class C extends null {
      constructor() {
        return Object.create(null);
      }
    }
    

    Object.getPrototypeOf()

    Function.prototypeメソッドは、子から親を取得するために使用することができる.
    Object.getPrototypeOf(A) === B;
    

    したがって,この手法を用いて,あるクラスが別のクラスを継承しているか否かを判断することができる.

    superキーワード

    Object.getPrototypeOfというキーワードは、2つの使い方があり、意味が違います.
  • が関数として呼び出す場合(すなわちsuper)、super(...args)は親のコンストラクション関数
  • を表す.
  • がオブジェクトとして呼び出された場合(すなわち、superまたはsuper.prop)、super.method()は親を表す.なお、このときsuperは、親インスタンスの属性およびメソッドを参照してもよいし、親の静的メソッド
  • を参照してもよい.
    class B extends A {
      get m() {
        return this._p * super._p;
      }
      
      set m() {
        throw new Error(' ');
      }
    }
    

    上記のコードでは、サブクラスはsuperキーワードを介して、親インスタンスのsuper属性を呼び出す.
    オブジェクトは常に他のオブジェクトを継承するため、いずれかのオブジェクトで_pキーワードを使用できます.
    var obj = {
      toString() {
        return "MyObject: " + super.toString();
      }
    };
    
    obj.toString(); // MyObject: [object Object]
    

    生命は止まらず、振り回されて止まらない...I'm not a real coder, but i love it so much!