Nowa classskładnia to na razie głównie cukier syntaktyczny. (Ale wiesz, dobry rodzaj cukru.) W ES2015-ES2020 nie ma niczego class, czego nie można zrobić z funkcjami konstruktora Reflect.construct(łącznie z podklasami Errori Array¹). (Jest to prawdopodobnie będzie kilka rzeczy w ES2021, że można zrobić z class, że nie można zrobić inaczej: prywatne pola , metody prywatne i Pola statyczne / prywatne metody statyczne ).
Co więcej, czy jest classto inny rodzaj OOP, czy nadal jest to prototypowe dziedziczenie JavaScript?
Jest to to samo prototypowe dziedziczenie, które zawsze mieliśmy, tylko z czystszą i wygodniejszą składnią, jeśli lubisz używać funkcji konstruktorów ( new Fooitp.). (Szczególnie w przypadku wywodzenia się z Arraylub Error, czego nie mogłeś zrobić w ES5 i wcześniejszych. Możesz teraz z Reflect.construct[ spec , MDN ], ale nie ze starym stylem ES5.)
Czy mogę go zmodyfikować za pomocą .prototype?
Tak, prototypepo utworzeniu klasy nadal możesz modyfikować obiekt w konstruktorze klasy. Np. Jest to całkowicie legalne:
class Foo {
constructor(name) {
this.name = name;
}
test1() {
console.log("test1: name = " + this.name);
}
}
Foo.prototype.test2 = function() {
console.log("test2: name = " + this.name);
};
Czy są korzyści związane z szybkością?
Poprzez zapewnienie idiom specyficzne dla tego, Przypuszczam, że to możliwe , że silnik może być w stanie zrobić lepszą optymalizację pracy. Ale już teraz są okropnie dobrzy w optymalizacji, nie spodziewałbym się znaczącej różnicy.
Jakie korzyści classzapewnia składnia ES2015 (ES6) ?
W skrócie: jeśli w pierwszej kolejności nie używasz funkcji konstruktora, preferowanie Object.createlub classcoś podobnego nie jest dla ciebie przydatne.
Jeśli używasz funkcji konstruktora, istnieją pewne korzyści z class:
Składnia jest prostsza i mniej podatna na błędy.
O wiele łatwiej (i znowu mniej podatne na błędy) jest konfigurowanie hierarchii dziedziczenia przy użyciu nowej składni niż w przypadku starej.
classchroni Cię przed typowym błędem polegającym na niepowodzeniu użycia newfunkcji konstruktora (przez wywołanie przez konstruktora wyjątku, jeśli thisnie jest prawidłowym obiektem dla konstruktora).
Wywołanie wersji metody prototypu nadrzędnego jest znacznie prostsze w przypadku nowej składni niż starej ( super.method()zamiast ParentConstructor.prototype.method.call(this)lub Object.getPrototypeOf(Object.getPrototypeOf(this)).method.call(this)).
Oto porównanie składni dla hierarchii:
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() {
}
}
Przykład:
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());
vs.
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() {
};
Przykład na żywo:
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());
Jak widać, jest tam wiele powtarzających się i rozwlekłych rzeczy, które łatwo się pomylić i nudne do przepisania (dlatego napisałem kiedyś skrypt, który to robi ).
¹ „W ES2015-ES2018 classnie ma nic, czego nie można zrobić za pomocą funkcji konstruktora i Reflect.construct(w tym podklasy Errori Array)”
Przykład:
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;
}