JavaScript/OOP-类
面向对象编程中基于类的编程语言的流行程度激励了 JavaScript 社区,他们用模仿基于类的编程方法的语法来覆盖其基于原型的 OOP 实现。EcmaScript 2015 (ES6) 通过相应的关键词(如“class”或“extend”)得到了扩展。
类是用于创建对象的模板或“蓝图”。它们封装了它们的数据,并包含用于处理数据的函数。
class Person {
// Class body is always implicitly in "use strict" mode
constructor(name) {
// Data. Declarations like 'let x = 0' are not necessary.
this.name = name;
}
// functionality
showName() {
return "My name is: " + this.name;
}
}
const ada = new Person("Lovelace");
alert(ada.showName());
关键字 class
引入类定义。在示例中,Person 是类名。它后面跟着用花括号 { }
(第 1 行到第 11 行)括起来的类主体。在主体内部,有一个特殊方法 constructor
。此函数在类创建期间被调用。在示例中,它接受一个参数,即一个人的姓名。在 constructor
内部,此参数使用关键字“this”在内部存储。该类只提供一个功能:showName
方法。
上面的语法显示了如何处理单个对象(实例 - 就像上面示例中的“ada”)的属性和方法。还可以定义在单个对象级别不可用但在类级别可用的属性和方法 - 上述示例中的“Person”。它们由关键字 static
引入。
class Person {
constructor(name) {
// data
this.name = name;
}
static className = "The PERSON Class";
static showClassName() {return "The name of this class is: " + this.className};
showName() {
return "My name is: " + this.name;
}
}
const ada = new Person("Lovelace");
// alert(ada.showClassName()); // Error!
alert(Person.showClassName());
第 7 行和第 8 行使用“static”关键字。因此,属性和方法不适用于实例,而只适用于整个类。
类方法可以作为属性提供。这使程序员能够区分通过圆括号 ()
访问方法和属性。关键字 get
引入此功能。
class Person {
constructor(name) {
this.name = name;
}
// getter
get showTheName() {
return this.showName();
}
// 'regular' method
showName() {
return "My name is: " + this.name;
}
}
const ada = new Person("Lovelace");
// NO parenthesis ()
alert(ada.showTheName);
接下来,我们定义一个类层次结构。这是使用关键字 extends
完成的。在示例中,Employee
是 Person
的子类,并且可以访问其所有属性和方法。
class Person {
constructor(name) {
this.name = name;
}
// method
showName() {
return "My name is: " + this.name;
}
}
class Employee extends Person {
constructor(name, company) {
super(name);
this.company = company;
}
// method
showCompany() {
return "I, " + this.name + ", work at the company " + this.company;
}
}
const henry = new Employee("Henry Miller", "ACME Inc.");
alert(henry.showCompany());
alert(henry.showName()); // method of the parent class
第 12 行调用父类的构造函数。这是必要的,因为父类的 constructor
创建“this”。
默认情况下,类属性和方法是可访问的。您可以使用井号 #
作为它们名称的第一个字符来隐藏它们。
class Person {
// two hidden properties (sometimes called 'private fields')
#firstName;
#lastName;
constructor(firstName, lastName) {
this.#firstName = firstName;
this.#lastName = lastName;
// one public property
this.name = lastName + ", " + firstName;
}
#showName() { // hidden method
alert("My name is " + this.name);
}
}
const ada = new Person("Ada", "Lovelace");
alert(ada.name); // ok
alert(ada.firstName); // undefined
alert(ada.#firstName); // undeclared private field
alert(ada.#showName()); // undeclared private method
如果方法名在“父”类和“子”类中都被使用,JavaScript 引擎将调用相关类的那个方法。
class Person {
constructor(name) {
this.name = name;
}
// method name is used also in 'child'
showName() {
return "My name is: " + this.name;
}
}
class Employee extends Person {
constructor(name, company) {
super(name);
this.company = company;
}
// same method name as in 'parent'
showName() {
return "My name is: " + this.name + ". I'm working at the company " + this.company;
}
}
const henry = new Employee("Henry Miller", "ACME Inc.");
alert(henry.showName()); // from Employee
const nextPerson = new Person("John");
alert(nextPerson.showName()); // from Person
示例定义并使用两个不同的方法 showName
。
this
不是变量或对象;它是一个关键字。根据上下文,它指的是不同的东西。在类定义的上下文中,它指的是类本身,例如,this.city = "Nairobi"
指的是当前类的属性“city”。
当 this
在文件的最顶层使用时(换句话说,在任何函数或对象之外),它指的是全局对象。在严格模式下,在函数中,this 为 undefined
。在 DOM 事件中,它指的是接收事件的元素。