Maison > interface Web > Questions et réponses frontales > Qu'est-ce qui est utilisé pour implémenter l'héritage dans es6

Qu'est-ce qui est utilisé pour implémenter l'héritage dans es6

青灯夜游
Libérer: 2023-02-14 13:56:57
original
2452 Les gens l'ont consulté

Dans es6, les mots-clés class et extends sont utilisés pour implémenter l'héritage. Le mot-clé class a été introduit dans ES6 pour déclarer une classe, et la classe (class) peut être héritée via le mot-clé extends, permettant à la sous-classe d'hériter des propriétés et des méthodes de la classe parent. La syntaxe est "class parent class name {.. .} le nom de sous-classe de classe étend le nom de classe parent {...};".

Qu'est-ce qui est utilisé pour implémenter l'héritage dans es6

L'environnement d'exploitation de ce tutoriel : système Windows 7, ECMAScript version 6, ordinateur Dell G3.

Dans es6, le mot-clé class et le mot-clé extends peuvent être utilisés pour implémenter l'héritage.

Héritage de la classe ES6

1 Introduction

La classe peut obtenir l'héritage via le mot-clé extends, permettant aux sous-classes d'hériter des propriétés et des méthodes de la classe parent. C'est beaucoup plus clair et plus pratique que l'implémentation de l'héritage dans ES5 en modifiant la chaîne de prototypes.

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

Dans le code ci-dessus, le mot-clé super apparaît à la fois dans la méthode constructeur et dans la méthode toString. Super représente ici le constructeur de la classe parent, qui est utilisé pour créer un nouvel objet instance de la classe parent.

ES6 stipule que les sous-classes doivent appeler super() dans la méthode constructeur, sinon une erreur sera signalée car l'objet this de la sous-classe doit d'abord être façonné via le constructeur de la classe parent pour obtenir les mêmes attributs d'instance que la classe parent. . et méthodes, puis ajoutez les propres propriétés et méthodes d’instance de la sous-classe.

Pourquoi le constructeur d'une sous-classe doit-il appeler super() ?

En effet, dans le mécanisme d'héritage d'ES5, un objet instance d'une sous-classe indépendante est d'abord créé, puis les méthodes de la classe parent sont ajoutées à cet objet, c'est-à-dire « l'instance d'abord, l'héritage ES6 en dernier » ; Le mécanisme d'héritage consiste à ajouter d'abord les attributs et les méthodes de la classe parent à un objet vide, puis à utiliser l'objet comme instance de la sous-classe, c'est-à-dire « l'héritage d'abord, l'instance en dernier ».

Cela signifie que chaque fois qu'une nouvelle instance de sous-classe est créée, le constructeur de la classe parent doit être exécuté une fois

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

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

const bar = new Bar(); // 1 2
Copier après la connexion

Dans le code ci-dessus, lorsque la sous-classe Bar crée une nouvelle instance, elle affichera 1 et 2. C'est la construction de la classe factorielle Lorsque la fonction appelle super(), le constructeur de la classe parent sera exécuté une fois. Ce mot-clé ne peut être utilisé qu'après avoir appelé super dans le constructeur d'une sous-classe, sinon une erreur sera signalée. En effet, la construction d'une instance de sous-classe doit d'abord terminer l'héritage de la classe parent. Seule la super méthode permet à l'instance de sous-classe d'hériter de la classe parent.

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;
	}
}"
Copier après la connexion

Si la sous-classe ne définit pas de méthode constructeur, cette méthode sera ajoutée par défaut et super y sera appelé, c'est-à-dire que peu importe qu'elle soit explicitement définie ou non, toute sous-classe a une méthode constructeur. .

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}
Copier après la connexion

2. Héritage privé des propriétés et des méthodes privées

Toutes les propriétés et méthodes de la classe parent seront héritées par la sous-classe, à l'exception des propriétés et méthodes privées. Les sous-classes ne peuvent pas hériter des propriétés privées de la classe parent, ou les propriétés privées ne peuvent être utilisées que dans la classe dans laquelle elles sont définies.

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

class Bar extends Foo {
  constructor() {
    super();
    console.log(this.#p); // 报错
    this.#m(); // 报错
  }
}
Copier après la connexion

Dans l'exemple ci-dessus, si la sous-classe Bar appelle les propriétés privées ou les méthodes privées de la classe parent Foo, une erreur sera signalée.

Si la classe parent définit des méthodes de lecture et d'écriture pour les propriétés privées, la sous-classe peut lire et écrire des propriétés privées via ces méthodes.

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

class Bar extends Foo {
  constructor() {
    super();
    console.log(this.getP()); // 1
  }
}
Copier après la connexion

3. Héritage des propriétés et méthodes statiques

Les propriétés statiques et les méthodes statiques de la classe parent seront également héritées par la sous-classe.

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

class B extends A {
}

B.hello()  // hello world
Copier après la connexion

Dans le code ci-dessus, hello() est une méthode statique de la classe A, et B hérite de A</code >, hérite également de la méthode statique de <code>A. hello()A类的静态方法,B继承A,也继承了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
Copier après la connexion

4.Object.getPrototypeOf()

Object.getPrototypeOf()

Notez que les propriétés statiques sont héritées par copie superficielle. Si la propriété héritée est un type de données primitif, le fonctionnement de la propriété statique héritée dans la sous-classe n'affectera pas la classe parent, mais si la propriété héritée est un objet, alors le subclass Modifier cette propriété impressionnera la classe parent

class Point { /*...*/ }

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

Object.getPrototypeOf(ColorPoint) === Point
// true
Copier après la connexion

4.Object.getPrototypeOf()

La méthode Object.getPrototypeOf() peut être utilisée pour obtenir la classe parent de la sous-classe.

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

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

new A(); // A
new B(); // B
Copier après la connexion

Par conséquent, vous pouvez utiliser cette méthode pour déterminer si une classe hérite d'une autre classe.

5. super mot-clé

Le super mot-clé peut être utilisé comme fonction ou comme objet

Dans le premier cas, lorsque super est appelé comme fonction, il représente le constructeur de la classe parent. La fonction de l'appel de super est de former l'objet this de la sous-classe et de placer les attributs et méthodes d'instance de la classe parent sur cet objet this.

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

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

let b = new B();
Copier après la connexion

Dans le deuxième cas, lorsque super est utilisé comme objet, dans les méthodes ordinaires, il pointe vers l'objet prototype de la classe parent ; dans les méthodes statiques, il pointe vers la classe parent. 🎜
class A {
	constructor() {
		this.p = 2;
	}
}

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

let b = new B();
b.m // undefined
Copier après la connexion
🎜Dans le code ci-dessus, super.p() dans la sous-classe B utilise super comme objet. À l'heure actuelle, super dans l'objet ordinaire pointe vers A.prototype, et super.p() est équivalent à A.prototype. .p(). 🎜🎜Étant donné que super pointe vers l'objet prototype de la classe parent, les méthodes ou attributs définis sur l'instance de classe parent ne peuvent pas être appelés via super. Comme indiqué ci-dessous : 🎜
class A {};
A.prototype.x = 2;

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

let b = new B();
Copier après la connexion
🎜Afin de résoudre ce problème, vous pouvez définir des attributs sur l'objet prototype de la classe parent🎜
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
Copier après la connexion
Copier après la connexion
🎜ES6 stipule que lors de l'appel de la méthode de la classe parent via super dans la méthode ordinaire de la sous-classe, le this à l'intérieur de la méthode pointe vers l'instance de sous-classe actuelle🎜
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
Copier après la connexion
Copier après la connexion

上面代码中,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
	}
}
Copier après la connexion

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

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

class Parent {
	static myMethod(msg) {
		console.log(&#39;static&#39;, msg);
	}

	myMethod(msg) {
		console.log(&#39;instance&#39;, 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
Copier après la connexion

上面代码中,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
Copier après la connexion

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

【推荐学习:javascript高级教程

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal