前言
在 ES6 之前,JavaScript 主要通过 构造函数 + 原型 来实现类似“类”的效果。
到了 ES6,JavaScript 引入了
class
语法,让代码看起来更像 Java、C++ 等传统面向对象语言。
但是很多人会有疑问:
-
class到底是什么?
-
它和构造函数有什么关系?
-
它和原型有什么关系?
-
JavaScript 的 class 是不是真正的类?
本文就来系统讲清楚这个问题。
一、什么是类?
在 ES6 中,我们可以这样定义一个类:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`你好,我是 ${this.name}`);
}
}
const p = new Person('Tom', 18);
p.sayHello(); // 你好,我是 Tom
这里:
-
class Person定义了一个类
-
constructor是构造方法
-
new Person()用来创建实例
二、类的基本组成
1)constructor
构造函数,在创建实例时自动执行。
class Person {
constructor(name) {
this.name = name;
}
}
2)实例属性
通过
this.xxx
定义。
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
3)方法
写在类体中的方法,会放到原型上。
class Person {
sayHello() {
console.log('hello');
}
}
三、类本质上是什么?
很多人以为
class
是一套全新的机制,其实不是。
JavaScript 中的
class
本质上还是基于 原型 实现的,只是语法更清晰了。
例如下面两段代码本质上是类似的。
class 写法
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
console.log(this.name);
}
}
构造函数写法
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function () {
console.log(this.name);
};
所以可以记住一句话:
class 是原型继承的语法糖。
四、类的继承
ES6 使用
extends
实现继承。
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
console.log(`你好,我是 ${this.name}`);
}
}
class Student extends Person {
constructor(name, grade) {
super(name);
this.grade = grade;
}
study() {
console.log(`${this.name} 正在学习`);
}
}
const s = new Student('Alice', '三年级');
s.sayHello(); // 你好,我是 Alice
s.study(); // Alice 正在学习
五、super 的作用
在子类中,
super()
用来调用父类构造函数。
super(name);
它的作用是把父类里的初始化逻辑执行一遍。
如果子类写了
constructor
,一般都要先调用
super()
。
六、类适合什么场景?
类更适合这些情况:
- 创建多个结构相同的对象
- 明确表达继承关系
- 组织面向对象代码
- 管理实例属性和共享方法
不过在现代前端开发中,并不是所有代码都必须用类。
很多场景下,函数式写法也很常见。
七、总结
ES6 的
class
让 JavaScript 写法更接近传统面向对象语言,但本质上仍然离不开原型机制。
重点记住:
-
class是语法糖
-
constructor是构造方法
-
类的方法本质上在原型上
-
extends用于继承
-
super()用于调用父类构造逻辑