La nouvelle class
syntaxe est, pour l' instant , principalement du sucre syntaxique. (Mais, vous savez, le bon type de sucre.) Il n'y a rien dans ES2015-ES2020 qui class
puisse faire que vous ne puissiez pas faire avec les fonctions de constructeur et Reflect.construct
(y compris les sous Error
- classes et Array
¹). (Il est probable qu'il y aura des choses à ES2021 que vous pouvez faire avec class
ce que vous ne pouvez pas faire autrement: champs privés , des méthodes privées et les champs statiques / méthodes de statiques privées .)
De plus, est-ce class
un autre type de POO ou est-ce toujours l'héritage prototypique de JavaScript?
C'est le même héritage prototypique que nous avons toujours eu, juste avec une syntaxe plus propre et plus pratique si vous aimez utiliser des fonctions de constructeur ( new Foo
, etc.). (En particulier dans le cas de la dérivation de Array
ou Error
, ce que vous ne pouviez pas faire dans ES5 et les versions antérieures. Vous pouvez maintenant avec Reflect.construct
[ spec , MDN ], mais pas avec l'ancien style ES5.)
Puis-je le modifier en utilisant .prototype
?
Oui, vous pouvez toujours modifier l' prototype
objet sur le constructeur de la classe une fois que vous avez créé la classe. Par exemple, c'est parfaitement légal:
class Foo {
constructor(name) {
this.name = name;
}
test1() {
console.log("test1: name = " + this.name);
}
}
Foo.prototype.test2 = function() {
console.log("test2: name = " + this.name);
};
Y a-t-il des avantages de vitesse?
En fournissant un idiome spécifique pour cela, je suppose qu'il est possible que le moteur puisse faire un meilleur travail d'optimisation. Mais ils sont déjà extrêmement bons pour l'optimisation, je ne m'attendrais pas à une différence significative.
Quels sont les avantages de la class
syntaxe ES2015 (ES6) ?
En bref: si vous n'utilisez pas de fonctions de constructeur en premier lieu, préférer Object.create
ou similaire class
ne vous est pas utile.
Si vous utilisez des fonctions de constructeur, il y a quelques avantages à class
:
La syntaxe est plus simple et moins sujette aux erreurs.
Il est beaucoup plus facile (et encore moins sujet aux erreurs) de configurer des hiérarchies d'héritage en utilisant la nouvelle syntaxe qu'avec l'ancienne.
class
vous défend de l'erreur courante de ne pas utiliser new
avec la fonction constructeur (en demandant au constructeur de lancer une exception si ce this
n'est pas un objet valide pour le constructeur).
L'appel de la version du prototype parent d'une méthode est beaucoup plus simple avec la nouvelle syntaxe que l'ancienne ( super.method()
au lieu de ParentConstructor.prototype.method.call(this)
ou Object.getPrototypeOf(Object.getPrototypeOf(this)).method.call(this)
).
Voici une comparaison de syntaxe pour une hiérarchie:
class Person {
constructor(first, last) {
this.first = first;
this.last = last;
}
personMethod() {
}
}
class Employee extends Person {
constructor(first, last, position) {
super(first, last);
this.position = position;
}
employeeMethod() {
}
}
class Manager extends Employee {
constructor(first, last, position, department) {
super(first, last, position);
this.department = department;
}
personMethod() {
const result = super.personMethod();
return result;
}
managerMethod() {
}
}
Exemple:
class Person {
constructor(first, last) {
this.first = first;
this.last = last;
}
personMethod() {
return `Result from personMethod: this.first = ${this.first}, this.last = ${this.last}`;
}
}
class Employee extends Person {
constructor(first, last, position) {
super(first, last);
this.position = position;
}
personMethod() {
const result = super.personMethod();
return result + `, this.position = ${this.position}`;
}
employeeMethod() {
}
}
class Manager extends Employee {
constructor(first, last, position, department) {
super(first, last, position);
this.department = department;
}
personMethod() {
const result = super.personMethod();
return result + `, this.department = ${this.department}`;
}
managerMethod() {
}
}
const m = new Manager("Joe", "Bloggs", "Special Projects Manager", "Covert Ops");
console.log(m.personMethod());
contre.
var Person = function(first, last) {
if (!(this instanceof Person)) {
throw new Error("Person is a constructor function, use new with it");
}
this.first = first;
this.last = last;
};
Person.prototype.personMethod = function() {
};
var Employee = function(first, last, position) {
if (!(this instanceof Employee)) {
throw new Error("Employee is a constructor function, use new with it");
}
Person.call(this, first, last);
this.position = position;
};
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;
Employee.prototype.employeeMethod = function() {
};
var Manager = function(first, last, position, department) {
if (!(this instanceof Manager)) {
throw new Error("Manager is a constructor function, use new with it");
}
Employee.call(this, first, last, position);
this.department = department;
};
Manager.prototype = Object.create(Employee.prototype);
Manager.prototype.constructor = Manager;
Manager.prototype.personMethod = function() {
var result = Employee.prototype.personMethod.call(this);
return result;
};
Manager.prototype.managerMethod = function() {
};
Exemple en direct:
var Person = function(first, last) {
if (!(this instanceof Person)) {
throw new Error("Person is a constructor function, use new with it");
}
this.first = first;
this.last = last;
};
Person.prototype.personMethod = function() {
return "Result from personMethod: this.first = " + this.first + ", this.last = " + this.last;
};
var Employee = function(first, last, position) {
if (!(this instanceof Employee)) {
throw new Error("Employee is a constructor function, use new with it");
}
Person.call(this, first, last);
this.position = position;
};
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;
Employee.prototype.personMethod = function() {
var result = Person.prototype.personMethod.call(this);
return result + ", this.position = " + this.position;
};
Employee.prototype.employeeMethod = function() {
};
var Manager = function(first, last, position, department) {
if (!(this instanceof Manager)) {
throw new Error("Manager is a constructor function, use new with it");
}
Employee.call(this, first, last, position);
this.department = department;
};
Manager.prototype = Object.create(Employee.prototype);
Manager.prototype.constructor = Manager;
Manager.prototype.personMethod = function() {
var result = Employee.prototype.personMethod.call(this);
return result + ", this.department = " + this.department;
};
Manager.prototype.managerMethod = function() {
};
var m = new Manager("Joe", "Bloggs", "Special Projects Manager", "Covert Ops");
console.log(m.personMethod());
Comme vous pouvez le voir, il y a beaucoup de choses répétées et verbeuses qui sont faciles à se tromper et ennuyeuses à retaper (c'est pourquoi j'ai écrit un script pour le faire , à l'époque).
¹ "Il n'y a rien dans ES2015-ES2018 qui class
puisse faire que vous ne puissiez pas faire avec les fonctions de constructeur et Reflect.construct
(y compris les sous Error
- classes et Array
)"
Exemple:
function MyError(...args) {
return Reflect.construct(Error, args, this.constructor);
}
MyError.prototype = Object.create(Error.prototype);
MyError.prototype.constructor = MyError;
MyError.prototype.myMethod = function() {
console.log(this.message);
};
function outer() {
function inner() {
const e = new MyError("foo");
console.log("Callng e.myMethod():");
e.myMethod();
console.log(`e instanceof MyError? ${e instanceof MyError}`);
console.log(`e instanceof Error? ${e instanceof Error}`);
throw e;
}
inner();
}
outer();
.as-console-wrapper {
max-height: 100% !important;
}