Es 6ゼロから学ぶ(四):Classの継承

6116 ワード

Es 6ゼロから学ぶ(四):Classの継承


一:継承の方式


1、Classはextendsキーワードで継承できる
class Point {
}
class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y); //  constructor(x, y)
    this.color = color;
  }

  toString() {
    return this.color + ' ' + super.toString(); //  toString()
  }
}
constructorメソッドおよびtoStringメソッドには、親のsuperオブジェクトを新規作成するための親の構造関数を表すthisキーワードが表示されます.
サブクラスは、constructorメソッドでsuperメソッドを呼び出さなければなりません.そうしないと、インスタンスを新規作成するとエラーが発生します.これは、子が自分のthisオブジェクトを持たず、親のthisオブジェクトを継承して加工するためである.superメソッドを呼び出さないと、サブクラスはthisオブジェクトを得ることができません.これは、ES 6の継承メカニズムが全く異なり、実質的に親クラスのインスタンスオブジェクトthisを作成し(したがって、superメソッドを呼び出す必要がある)、次いでthisをサブクラスの構造関数で変更するためである.
2、サブクラスのコンストラクション関数では、superを呼び出した後にのみ、thisキーワードを使用できます.そうしないと、エラーが発生します.
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
}

class ColorPoint extends Point {
  constructor(x, y, color) {
    this.color = color; // ReferenceError
    super(x, y);
    this.color = color; //  
  }
}

これは、サブクラスインスタンスの構築が、親インスタンスの加工に基づいており、superメソッドのみが親インスタンスを返すことができるためです.
3、サブクラスインスタンスオブジェクトは親と子の両方のクラスのインスタンスである
let cp = new ColorPoint(25, 8, 'green');

cp instanceof ColorPoint // true
cp instanceof Point // true

上記のコードでは、インスタンスオブジェクトcpは、ColorPointPointの両方のクラスのインスタンスであり、これはES 5の動作と完全に一致する.
4、親の静的な方法は、布団類にも引き継がれます.
 

二:Object.getPrototypeOf()

Object.getPrototypeOfメソッドは、子から親を取得するために使用することができる.
Object.getPrototypeOf(ColorPoint) === Point
// true

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

三:superキーワード

superというキーワードは、関数としてもオブジェクトとしても使用できます.この2つの場合、その使い方は全く違います.
1、superを関数として呼び出す場合、親を表すコンストラクション関数
class A {}

class B extends A {
  constructor() {
    super();
  }
}

上記のコードでは、サブクラスBのコンストラクタのうちsuper()は、親クラスを呼び出すコンストラクタを表す.これは必須です.そうしないとJavaScriptエンジンがエラーを報告します.
2、関数としての場合、super()はサブクラスのコンストラクション関数にしか使用できず、他の場所で使用するとエラーが報告されます.
class A {}

class B extends A {
  m() {
    super(); //  
  }
}

3、superをオブジェクトとする場合、一般的な方法では、親のプロトタイプオブジェクトを指し、静的方法では、親を指す.
class A {
  p() {
    return 2;
  }
}

class B extends A {
  constructor() {
    super();
    console.log(super.p()); // 2
  }
}

let b = new B();

4.superは親のプロトタイプオブジェクトを指すため、親インスタンスに定義されたメソッドまたは属性は、superで呼び出すことができません.
class A {
      constructor() {
        this.x = 1
      }
    }

    class B extends A {
      constructor() {
        super()
        console.log(super.x) // undefined
      }
    }
    let p = new B()

5、属性が親のプロトタイプオブジェクトに定義されている場合、superが取得できます.
class A {
      constructor() {
        this.x = 1
      }
    }
    A.prototype.x = 2

    class B extends A {
      constructor() {
        super()
        console.log(super.x) //2
      }
    }
    let p = new B()

6.superで親クラスのメソッドを呼び出す場合、メソッド内部のthisは子クラスを指す
class A {
  constructor() {
    this.x = 1;
  }
  print() {
    console.log(this.x);
  }
}

class B extends A {
  constructor() {
    super();
    this.x = 2;
  }
  m() {
    super.print();
  }
}

let b = new B();
b.m() // 2

上記のコードでは、super.print()A.prototype.print()を呼び出すが、A.prototype.print()の内部のthisはサブクラスBを指し、2ではなく1を出力する.
7.superがオブジェクトとして使用される場合、superは親のプロトタイプオブジェクトではなく親を指す.
class Parent {
  static myMethod(msg) {
    console.log('static', msg);
  }

  myMethod(msg) {
    console.log('instance', msg);
  }
}

class Child extends Parent {
  static myMethod(msg) {
    super.myMethod(msg);
  }

  myMethod(msg) {
    super.myMethod(msg);
  }
}

Child.myMethod(1); // static 1

var child = new Child();
child.myMethod(2); // instance 2
superは、静的メソッドの中で親を指し、一般的なメソッドの中で親のプロトタイプオブジェクトを指す.
8、superを使用する場合は、関数として使用するか、オブジェクトとして使用するかを明示的に指定しなければなりません.そうしないと、エラーが発生します.
class A {}

class B extends A {
  constructor() {
    super();
    console.log(super); //  
  }
}

9、オブジェクトは常に他のオブジェクトを継承するので、いずれかのオブジェクトでsuperキーワードを使用することができます.
var obj = {
  toString() {
    return "MyObject: " + super.toString();
  }
};

obj.toString(); // MyObject: [object Object]

  

四:クラスのprototypeと_proto__ツールバーの


1、子クラスの__proto__属性は、構造関数の継承を表し、常に親クラスを指す.
class A {
}

class B extends A {
}

B.__proto__ === A // true

2、子クラスprototype属性の__proto__属性は、メソッドの継承を表し、常に親クラスのprototype属性を指す.
class A {
}

class B extends A {
}

B.prototype.__proto__ === A.prototype // true