JavaScript的类是ES6中实现的一种面向对象的设计模型。它是对组封和重用进行优化的一种方式,尽管它是一种较为面向类型语言的仿造,但它本质上仍然是一种基于原型的语言。
类的概述
在JavaScript中,类是为了实现对象面向类型结构而设计的。它使用class关键字定义,尽管是一种声明式规范,本质上依然基于原型和实例。
声明一个类
可以通过class 关键字声明一个类:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
}
}
构造函数
构造函数是类中的特殊方法,依赖于constructor关键字:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
const person = new Person('Alice', 30);
console.log(person.name); // Alice
实例方法
实例方法是为实例实现专属功能的方法:
class Person {
sayHello() {
console.log('Hello!');
}
}
const person = new Person();
person.sayHello(); // Hello!
私有字段
私有字段通过# 声明,只能在类内部访问:
class Person {
#id;
constructor(id) {
this.#id = id;
}
getId() {
return this.#id;
}
}
const person = new Person(123);
console.log(person.getId()); // 123
console.log(person.#id); // SyntaxError
Getter和Setter字段
通过get 和set实现属性的读写控制:
class Person {
constructor(name) {
this._name = name;
}
get name() {
return this._name;
}
set name(newName) {
this._name = newName;
}
}
const person = new Person('Alice');
console.log(person.name); // Alice
person.name = 'Bob';
console.log(person.name); // Bob
公共字段
公共字段通过在构造函数之外直接声明:
class Person {
name = 'Anonymous';
}
const person = new Person();
console.log(person.name); // Anonymous
静态属性
通过static 关键字声明属于类本身的属性或方法:
class MathUtil {
static add(a, b) {
return a + b;
}
}
console.log(MathUtil.add(2, 3)); // 5
扩展与继承
通过extends 实现类之间的继承,并使用super 调用父类方法:
class Employee extends Person {
constructor(name, age, position) {
super(name, age); // 调用父类构造函数
this.position = position;
}
sayHello() {
super.sayHello(); // 调用父类方法
console.log(`I work as a ${this.position}.`);
}
}
const employee = new Employee('Bob', 25, 'Developer');
employee.sayHello();
// Hello, my name is Bob and I am 25 years old.
// I work as a Developer.
为什么用类?
- 规范化结构:使开发者更易给实例连续和维护。
- 重用和抽象化:优化了实现,减少重复代码。
- 实现应用情境中的复杂功能:如系统属性管理。
- 软件兼容性:便于从其他面向对象的语言迁移到JavaScript。
常见面试题
-
如何创建一个类?
- 答案:使用
class关键字定义类。类可以包含构造函数和方法。
示例:
class Person { constructor(name) { this.name = name; } sayHello() { console.log(`Hello, ${this.name}`); } } - 答案:使用
-
构造函数的作用是什么?
- 答案:构造函数是用于初始化类的实例的特殊方法。它在创建对象时自动调用。
示例:
class Person { constructor(name) { this.name = name; } } const person = new Person('Alice'); console.log(person.name); // Alice -
类的继承是如何实现的?
- 答案:通过
extends关键字实现继承,并用super调用父类的构造函数和方法。
示例:
class Animal { constructor(name) { this.name = name; } makeSound() { console.log('Generic animal sound'); } } class Dog extends Animal { makeSound() { console.log('Bark!'); } } const dog = new Dog('Buddy'); dog.makeSound(); // Bark! - 答案:通过
-
什么是静态方法?它与实例方法有何区别?
- 答案:静态方法是属于类本身的方法,而不是实例的方法。通过类名调用,而非实例。
示例:
class MathUtil { static square(num) { return num * num; } } console.log(MathUtil.square(4)); // 16 -
如何实现私有字段?它们的作用是什么?
- 答案:使用
#声明私有字段,保护数据不被外部直接访问。
示例:
class Person { #id; constructor(id) { this.#id = id; } getId() { return this.#id; } } const person = new Person(123); console.log(person.getId()); // 123 - 答案:使用
-
如何通过getter和setter控制属性?
- 答案:使用
get和set关键字定义属性访问器,控制属性读取和写入逻辑。
示例:
class Person { constructor(name) { this._name = name; } get name() { return this._name; } set name(newName) { this._name = newName; } } - 答案:使用
-
JavaScript中的类与传统面向对象语言(如Java)中的类有何不同?
- 答案:JavaScript的类基于原型,而传统语言的类是基于类型的。
-
什么是多态?在JavaScript中如何实现多态?
- 答案:多态指同一方法在不同对象中具有不同表现。通过继承和方法重写实现。
-
如何检测一个对象是否是某个类的实例?
- 答案:使用
instanceof操作符。
示例:
console.log(person instanceof Person); // true - 答案:使用
-
类的属性和方法是否可以枚举?
- 答案:实例属性可以通过
Object.keys或for...in枚举,类的方法通常不可枚举。
- 答案:实例属性可以通过