class
ไวยากรณ์ใหม่ในตอนนี้ส่วนใหญ่เป็นน้ำตาลที่เป็นไวยากรณ์ ( แต่คุณรู้ที่ดีชนิดของน้ำตาล.) มีอะไรใน ES2015 ES2020-ที่class
สามารถทำเช่นนั้นคุณจะไม่สามารถทำอะไรกับฟังก์ชั่นคอนสตรัคและReflect.construct
(รวม subclassing Error
และArray
¹) (มันเป็นแนวโน้มที่จะมีบางสิ่งบางอย่างใน ES2021 ที่คุณสามารถทำอะไรกับclass
ที่คุณไม่สามารถทำอย่างอื่น: เขตข้อมูลส่วนตัว , วิธีเอกชนและเขตข้อมูลคงที่ / วิธีการคงส่วนตัว .)
ยิ่งไปกว่านั้นclass
OOP ประเภทอื่นหรือยังคงเป็นมรดกต้นแบบของ 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);
};
มีประโยชน์ด้านความเร็วหรือไม่?
ด้วยการให้สำนวนเฉพาะสำหรับสิ่งนี้ฉันคิดว่าเป็นไปได้ว่าเครื่องยนต์อาจสามารถเพิ่มประสิทธิภาพงานได้ดีขึ้น แต่พวกเขาเก่งมากในการเพิ่มประสิทธิภาพอยู่แล้วฉันไม่คาดหวังความแตกต่าง
class
ไวยากรณ์ES2015 (ES6) ให้ประโยชน์อะไรบ้าง?
โดยสังเขป: หากคุณไม่ได้ใช้ฟังก์ชันตัวสร้างตั้งแต่แรกเลือก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());
เทียบกับ
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;
}