新的
class语法是,对于现在,大多是语法sugar。(但是,您知道,这是很好的sugar。)ES2015-ES2019中
class没有什么可以构造函数无法做到的,并且
Reflect.construct(包括子类
Error和
Array¹)也无法做到。(有
是
有可能在ES2021一些东西,你可以做
class,你不能这样做,否则:私人领域,私有方法和静态字段/私有静态方法。)
而且,是
class另一种OOP还是Javascript的原型继承?
这与我们一直拥有的原型继承相同,只是如果您喜欢使用构造函数(
newFoo等等),则使用更简洁,更方便的语法。(特别是在源自
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)
orObject.getPrototypeOf(Object.getPrototypeOf(this)).method.call(this)
)要简单得多。
这是层次结构的语法比较:
// ***ES2015+**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(); // ...use `result` for something... return result; } managerMethod() { // ... }}例:
// ***ES2015+**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());与
// **ES5**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); // ...use `result` for something... return result;};Manager.prototype.managerMethod = function() { // ...};现场示例:
// **ES5**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)”
例:
// Creating an Error subclass: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);};// Example use: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;}


