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 {...};".
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.
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方法 } }
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.
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
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; } }"
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}
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(); // 报错 } }
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 } }
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
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
4.Object.getPrototypeOf()
Object.getPrototypeOf()
class Point { /*...*/ } class ColorPoint extends Point { /*...*/ } Object.getPrototypeOf(ColorPoint) === Point // true
4.Object.getPrototypeOf()
La méthodeObject.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
class A { p() { return 2; } } class B extends A { constructor() { super(); console.log(super.p()); // 2 } } let b = new B();
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();
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 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高级教程】
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!