类和构造函数
你可以使用 class 关键字声明一个类。下面是上一篇文章中关于 Person 类的一个声明:
jsclass Person {
name;
constructor(name) {
this.name = name;
}
introduceSelf() {
console.log(`Hi! I'm ${this.name}`);
}
}
在这个 Person 类的声明中,有:
一个 name 属性。
一个需要 name 参数的构造函数,这一参数用于初始化新的对象的 name 属性。
一个 introduceSelf() 方法,使用 this 引用了对象的属性。
name; 这一声明是可选的:你可以省略它,因为在构造函数中的 this.name = name; 这行代码会在初始化 name 属性前自动创建它。但是,在类声明中明确列出属性可以方便阅读代码的人更容易确定哪些属性是这个类的一部分。
你也可以在声明属性时,为其初始化一个默认值。就像这样:name = '';。
构造函数使用 constructor 关键字来声明。就像在类声明外的构造函数一样,它会:
创建一个新的对象
将 this 绑定到这个新的对象,你可以在构造函数代码中使用 this 来引用它
执行构造函数中的代码
返回这个新的对象
如上文中给出的类声明的代码,你可以像这样创建和使用一个新的 Person 实例:
jsconst giles = new Person("Giles");
giles.introduceSelf(); // Hi! I'm Giles
注意,我们使用类的名字来调用构造函数,即示例中的 Person。
省略构造函数
如果你不需要任何特殊的初始化内容,你可以省略构造函数,默认的构造函数会被自动生成:
jsclass Animal {
sleep() {
console.log("zzzzzzz");
}
}
const spot = new Animal();
spot.sleep(); // 'zzzzzzz'
继承
对于上文给出的 Person 类,我们声明一个它的子类 Professor。
jsclass Professor extends Person {
teaches;
constructor(name, teaches) {
super(name);
this.teaches = teaches;
}
introduceSelf() {
console.log(
`My name is ${this.name}, and I will be your ${this.teaches} professor.`,
);
}
grade(paper) {
const grade = Math.floor(Math.random() * (5 - 1) + 1);
console.log(grade);
}
}
我们使用 extends 关键字来声明这个类继承自另一个类。
我们为 Professor 类添加了一个新的属性 teaches,就像声明的那样。
因为我们想在创建新的 Professor 时设置 teaches,我们需要声明一个需要 name 和 teaches 参数的构造函数。构造函数中需要做的第一件事是使用 super() 调用父类的构造函数,并传递 name 参数。父类的构造函数会设置 name 属性。然后 Professor 的构造函数接着设置 teaches 属性。
备注:如果子类有任何自己的初始化内容需要完成,它也必须先使用 super() 来调用父类的构造函数,并传递父类构造函数期望的任何参数。
我们还覆盖了父类的 introduceSelf() 方法,并添加了一个新的方法 grade(),来为论文打分(我们的教授不是很好,只是随意地为论文打分)。
有了这个声明,我们现在可以创建和使用 professor 实例了:
jsconst walsh = new Professor("Walsh", "Psychology");
walsh.introduceSelf(); // 'My name is Walsh, and I will be your Psychology professor'
walsh.grade("my paper"); // some random grade
封装
最后,让我们了解一下 JavaScript 中如何实现封装。在上一篇文章中,我们讨论了我们为什么想要使得 Student 的 year 属性变为私有的,我们可以在不破坏任何使用了 Student 类的代码的情况下,修改射箭课程的规则。
这里,就像我们之前想要的那样,声明了 Student 类:
jsclass Student extends Person {
#year;
constructor(name, year) {
super(name);
this.#year = year;
}
introduceSelf() {
console.log(`Hi! I'm ${this.name}, and I'm in year ${this.#year}.`);
}
canStudyArchery() {
return this.#year > 1;
}
}
在这个类的声明中,#year 是一个私有字段。我们可以构造一个 Student 对象,然后在内部使用 #year,但如果在类的外部尝试访问 #year,浏览器将会抛出错误:
jsconst summers = new Student("Summers", 2);
summers.introduceSelf(); // Hi! I'm Summers, and I'm in year 2.
summers.canStudyArchery(); // true
summers.#year; // SyntaxError
私有字段必须在类的声明中声明,而且其名称需以 # 开头。
私有方法
与私有字段一样,你也可以声明私有方法。而且名称也是以 # 开头,只能在类自己的方法中调用:
jsclass Example {
somePublicMethod() {
this.#somePrivateMethod();
}
#somePrivateMethod() {
console.log("You called me?");
}
}
const myExample = new Example();
myExample.somePublicMethod(); // 'You called me?'
myExample.#somePrivateMethod(); // SyntaxError
技能测试!
你已经看到了本文的结尾,但你还记得本文的绝大多数重要的信息吗?在继续学习新的内容之前,你可以找一些进一步的测验来验证你已经掌握了这些信息——参见技能测试:面向对象的 JavaScript。
总结
本文中,我们介绍了 JavaScript 中可用的面向对象编程的主要工具。我们没有涵盖所有的内容,但这些应该足以让你入门。我们的关于类的文章可让你进一步学习相关的知识。
上一页 概述:JavaScript 对象入门 下一页
Help improve MDN
Was this page helpful to you?
Yes
No
Learn how to contribute
This page was last modified on 2025年7月1日 by MDN contributors.
View this page on GitHub • Report a problem with this content