ホームページ  >  記事  >  ウェブフロントエンド  >  es6 で継承を実装するために使用されるもの

es6 で継承を実装するために使用されるもの

青灯夜游
青灯夜游オリジナル
2023-02-14 13:56:572422ブラウズ

class キーワードと extends キーワードは、es6 で継承を実装するために使用されます。 ES6 ではクラスを宣言するために class キーワードが導入され、extends キーワードを通じてクラス (クラス) を継承できるため、サブクラスが親クラスの属性とメソッドを継承できるようになります。構文は「class 親クラス名 {.. .} クラスのサブクラス名は親クラス名を拡張します {...};"。

es6 で継承を実装するために使用されるもの

このチュートリアルの動作環境: Windows 7 システム、ECMAScript バージョン 6、Dell G3 コンピューター。

es6 では、class キーワードと extends キーワードを使用して継承を実装できます。

ES6 クラスの継承

1. はじめに

クラスは extends を渡すことができますキーワードは継承を実装し、サブクラスが親クラスのプロパティとメソッドを継承できるようにします。これは、プロトタイプ チェーンを変更することによる ES5 の継承の実装よりもはるかに明確で便利です。

//父类
class Point {
 ...
}
//子类
class ColorPoint extends Point {
	constructor(x, y, color) {
		super(x, y);
		this.color = color;
	}
	toString() {
		return this.color + '' + super.toString(); // 调用父类的toString方法
	}
}

上記のコードでは、コンストラクター メソッドと toString メソッド内に super キーワードが表示されています。ここでの Super は、親クラスの新しいインスタンス オブジェクトを作成するために使用される親クラスのコンストラクターを表します。

ES6 では、サブクラスがコンストラクター メソッドで super() を呼び出す必要があると規定しています。そうしないと、エラーが報告されます。これは、サブクラス独自のこのオブジェクトが、最初に親クラスのコンストラクターを通じて整形され、同じオブジェクトを取得する必要があるためです。親クラスと同じインスタンスのプロパティとメソッドを作成し、サブクラス独自のインスタンスのプロパティとメソッドを追加します。

サブクラスのコンストラクターが super() を呼び出す必要があるのはなぜですか?

これは、ES5 の継承メカニズムでは、最初に独立したサブクラスのインスタンス オブジェクトが作成され、その後、親クラスのメソッドがこのオブジェクトに追加される、つまり「インスタンス ファースト」であるためです。 , "最初に継承"; ES6 の継承メカニズムは、まず親クラスの属性とメソッドを空のオブジェクトに追加し、次にそのオブジェクトをサブクラスのインスタンスとして使用します。つまり、"最初に継承、最後にインスタンス" です。

これは、新しいサブクラス インスタンスが作成されるたびに、親クラスのコンストラクターを 1 回実行する必要があることを意味します。

class Foo {
	constructor() {
		console.log(1);
	}
}

class Bar extends Foo {
	constructor() {
		super();
		console.log(2);
	}
}

const bar = new Bar(); // 1 2

上記のコードでは、サブクラス Bar が新しいインスタンスを作成するときに、 1 と 2 が出力されます。これは、因子クラスのコンストラクターが super() を呼び出すときに、親クラスのコンストラクターが 1 回実行されます。このキーワードは、サブクラスのコンストラクターで super を呼び出した後にのみ使用できます。使用しない場合は、エラーが報告されます。これは、サブクラス インスタンスの構築では、まず親クラスの継承が完了する必要があり、サブクラス インスタンスが親クラスを継承できるのはスーパー メソッドのみであるためです。

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

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

サブクラスがコンストラクター メソッドを定義していない場合、このメソッドはデフォルトで追加され、その中で super が呼び出されます。つまり、明示的に指定されているかどうかに関係なく、すべてのサブクラスにはコンストラクター メソッドがあります。定義済み.

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

let cp = new ColorPoint(25, 8);
console.log(cp); //{x: 25, y: 8}

class ColorPoint extends Point {
  constructor(...args) {
    super(...args);
  }
}

let cp = new ColorPoint(25, 8);
console.log(cp); //{x: 25, y: 8}

2. プライベート プロパティとプライベート メソッドの継承

親クラスのすべてのプロパティとメソッドはサブクラスに継承されます。ただし、プライベート プロパティとメソッドは除きます。サブクラスは親クラスのプライベート プロパティを継承できません。また、プライベート プロパティは、サブクラスが定義されているクラス内でのみ使用できます。

class Foo {
  #p = 1;
  #m() {
    console.log('hello');
  }
}

class Bar extends Foo {
  constructor() {
    super();
    console.log(this.#p); // 报错
    this.#m(); // 报错
  }
}

上記の例では、サブクラス Bar が親クラス Foo のプライベート プロパティまたはプライベート メソッドを呼び出すと、エラーが報告されます。

親クラスがプライベート プロパティの読み取りおよび書き込みメソッドを定義している場合、サブクラスはこれらのメソッドを通じてプライベート プロパティの読み取りおよび書き込みを行うことができます。

class Foo {
  #p = 1;
  getP() {
    return this.#p;
  }
}

class Bar extends Foo {
  constructor() {
    super();
    console.log(this.getP()); // 1
  }
}

3. 静的プロパティと静的メソッドの継承

親クラスの静的プロパティと静的メソッドは、サブクラスにも継承されます。 。

class A {
  static hello() {
    console.log('hello world');
  }
}

class B extends A {
}

B.hello()  // hello world

上記のコードでは、hello() はクラス A の静的メソッドであり、BA を継承し、またA の静的メソッドを継承します。

静的プロパティは浅いコピーによって継承されることに注意してください。継承されたプロパティがプリミティブ データ型の場合、サブクラスで継承された静的プロパティを操作しても親クラスには影響しませんが、継承されたプロパティがオブジェクトの場合は、この場合、サブクラスは、この属性

class C {
	static foo = 100;
}

class D extends C {
	constructor() {
		super();
		D.foo--;
	}
}

const d = new D();
C.foo; // 100
D.foo;  // 99

class A {
	static foo = { n: 100 };
}

class B extends A {
	constructor() {
		super();
		B.foo.n--;
	}
}

const b = new B();
B.foo.n // 99
A.foo.n  // 99

4.Object.getPrototypeOf()

Object を変更するときに親クラスの影響を受けます。 .getPrototypeOf () メソッドを使用して、サブクラスから親クラスを取得できます。

class Point { /*...*/ }

class ColorPoint extends Point { /*...*/ }

Object.getPrototypeOf(ColorPoint) === Point
// true

したがって、このメソッドを使用して、クラスが別のクラスを継承しているかどうかを判断できます。

5.super キーワード

super キーワードは関数またはオブジェクトとして使用できます

ある場合には、 、 super が関数として呼び出された場合、それは親クラスのコンストラクターを表します。スーパーを呼び出す機能は、サブクラスの this オブジェクトを形成し、親クラスのインスタンス属性とメソッドをこの this オブジェクトに配置することです。

class A {
	constructor() {
    console.log(new.target.name);
  }
}

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

new A(); // A
new B(); // B

2 番目のケースでは、super がオブジェクトとして使用される場合、通常のメソッドでは親クラスのプロトタイプ オブジェクトを指しますが、静的メソッドでは親クラスを指します。

class A {
	p() {
    return 2;
  }
}

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

let b = new B();

上記のコードでは、サブクラス B の super.p() が super をオブジェクトとして使用していますが、このとき通常のオブジェクトの super は A.prototype を指しており、 super.p() は In と等価です。 A.prototype.p()。

super は親クラスのプロトタイプ オブジェクトを指すため、親クラスのインスタンスで定義されたメソッドや属性を super 経由で呼び出すことはできません。以下に示すように:

class A {
	constructor() {
		this.p = 2;
	}
}

class B extends A {
	get m() {
		return spuer.p;
	}
}

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

この問題を解決するには、親クラスのプロトタイプ オブジェクトに属性を定義できます。

class A {};
A.prototype.x = 2;

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

let b = new B();

ES6 では、サブクラスの通常のメソッドで次の呼び出しを行うことが規定されています。スーパー メソッドを介した親クラス。メソッド内の 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(),但是此时方法内部的this指向是子类B的实例,所以输出2。

由于this指向的是子类实例,所有如果通过super对某个属性赋值,这时super就是this,赋值的属性会变成子类实例的属性

class A {
	constructor() {
		this.x = 1;
	}
}

class B extends A {
	constructor() {
		super();
		this.x = 2;
		super.x = 3;
		console.log(super.x); //undefind
		console.log(this.x); // 3
	}
}

上面代码中,super.x赋值为3,这时等同于对this.x赋值为3。而当读取super.x 的时候,读的是A.prototype.x,所以返回undefined

如果super作为对象,用在静态方法之中,这时super将指向父类,而不是父类的原型对象。

class Parent {
	static myMethod(msg) {
		console.log('static', msg);
	}

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

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

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

Child.myMethod(1); // static 1

var child = new Child();
child.myMethod(2); // instance 2

上面代码中,super在静态方法之中指向父类,在普通方法之中指向父类的原型对象。

另外,在子类的静态方法中通过super调用父类的方法时,方法内部的this指向当前的子类,而不是子类的实例

class A {
	constructor() {
    this.x = 1;
  }
  static print() {
    console.log(this.x);
  }
}

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

B.x = 3;
B.m() // 3

在静态方法m中,super.print指向父类的静态方法,到那时this指向的是类B,而不是B的实例。

【推荐学习:javascript高级教程

以上がes6 で継承を実装するために使用されるものの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。