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
は、ColorPoint
とPoint
の両方のクラスのインスタンスであり、これは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
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()
}
}
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; //
}
}
let cp = new ColorPoint(25, 8, 'green');
cp instanceof ColorPoint // true
cp instanceof Point // true
Object.getPrototypeOf(ColorPoint) === Point
// true
class A {}
class B extends A {
constructor() {
super();
}
}
class A {}
class B extends A {
m() {
super(); //
}
}
class A {
p() {
return 2;
}
}
class B extends A {
constructor() {
super();
console.log(super.p()); // 2
}
}
let b = new B();
class A {
constructor() {
this.x = 1
}
}
class B extends A {
constructor() {
super()
console.log(super.x) // undefined
}
}
let p = new B()
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()
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
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
class A {}
class B extends A {
constructor() {
super();
console.log(super); //
}
}
var obj = {
toString() {
return "MyObject: " + super.toString();
}
};
obj.toString(); // MyObject: [object Object]
class A {
}
class B extends A {
}
B.__proto__ === A // true
class A {
}
class B extends A {
}
B.prototype.__proto__ === A.prototype // true