Новый classсинтаксис, для теперь , в основном синтаксического сахара. (Но, знаете, хороший вид сахара.) В ES2015-ES2020 classнет ничего такого, что нельзя было бы сделать с функциями конструктора и Reflect.construct(включая подклассы Errorи Array¹). (Это является , вероятно , будут какие - то вещи в ES2021 , что вы можете сделать с , classчто вы не можете сделать иначе: частные поля , частные методы и статические поля / частные статические методы .)
Более того, является classли ООП другим видом или это все еще прототипное наследование JavaScript?
Это то же прототипное наследование, которое у нас всегда было, только с более чистым и удобным синтаксисом, если вам нравится использовать функции конструктора ( new Fooи т. Д.). (В особенности в случае наследования от Arrayили Error, чего нельзя было сделать в ES5 и ранее. Теперь вы можете использовать Reflect.construct[ spec , MDN ], но не в старом стиле ES5.)
Могу ли я изменить его с помощью .prototype?
Да, вы все равно можете изменить prototypeобъект в конструкторе класса после создания класса. Например, это совершенно законно:
class Foo {
constructor(name) {
this.name = name;
}
test1() {
console.log("test1: name = " + this.name);
}
}
Foo.prototype.test2 = function() {
console.log("test2: name = " + this.name);
};
Есть ли преимущества в скорости?
Предоставляя для этого определенную идиому, я полагаю, что возможно, что движок сможет лучше выполнять оптимизацию. Но они уже ужасно хороши в оптимизации, я бы не ожидал значительной разницы.
Какие преимущества дает синтаксис ES2015 (ES6) class?
Вкратце: если вы в первую очередь не используете функции-конструкторы, предпочитаемые Object.createили подобные им, они вам classне пригодятся.
Если вы все же используете функции-конструкторы, есть некоторые преимущества class:
Синтаксис проще и менее подвержен ошибкам.
Это гораздо проще (и снова, менее подвержены ошибкам) , чтобы создать иерархии наследования , используя новый синтаксис , чем со старым.
classзащищает вас от распространенной ошибки, связанной newс thisневозможностью использования функции конструктора (за счет того, что конструктор генерирует исключение, если он не является допустимым объектом для конструктора).
Вызвать версию метода родительского прототипа с новым синтаксисом намного проще, чем со старым ( super.method()вместо ParentConstructor.prototype.method.call(this)или Object.getPrototypeOf(Object.getPrototypeOf(this)).method.call(this)).
Вот сравнение синтаксиса для иерархии:
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() {
}
}
Пример:
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() {
};
Живой пример:
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());
Как видите, там много повторяющихся и многословных вещей, в которых легко ошибиться и скучно перепечатывать (именно поэтому я написал сценарий для этого в свое время).
¹ "В ES2015-ES2018 classнет ничего такого, что нельзя было бы сделать с функциями конструктора и Reflect.construct(включая подклассы ErrorиArray )»
Пример:
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;
}