JavaScript ES6 类与继承
ES6 引入 class 语法,提供更清晰的面向对象编程方式,extends 实现继承,底层仍是原型链机制。
类的基本语法
JavaScript
// ES6 类定义
class Person {
// 构造函数
constructor(name, age) {
this.name = name;
this.age = age;
}
// 实例方法(自动放在原型上)
sayHello() {
console.log(`Hello, I'm ${this.name}`);
}
// 静态方法(类本身调用)
static create(name) {
return new Person(name, 0);
}
}
const p = new Person('Tom', 25);
p.sayHello(); // "Hello, I'm Tom"
Person.create('Guest'); // 静态方法调用
// 类本质仍是函数
console.log(typeof Person); // 'function'
console.log(Person.prototype.sayHello); // 方法在原型上
类的特性
JavaScript
class Person {
// 私有属性约定(ES2022 真私有用 #)
_secret = 'hidden'; // 类字段(ES2022)
// getter/setter
get info() {
return `${this.name}, ${this.age}`;
}
set info(value) {
const [name, age] = value.split(',');
this.name = name;
this.age = parseInt(age);
}
// 类字段(直接定义实例属性)
species = 'human'; // 实例属性
static planet = 'Earth'; // 静态属性
}
const p = new Person('Tom', 25);
console.log(p.info); // "Tom, 25"
p.info = 'Jerry,30';
console.log(p.name); // 'Jerry'
console.log(p.species); // 'human'
console.log(Person.planet); // 'Earth'
extends 继承
JavaScript
// 父类
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} speaks`);
}
}
// 子类继承
class Dog extends Animal {
constructor(name, breed) {
super(name); // 调用父类构造函数(必须先调用 super)
this.breed = breed;
}
speak() {
console.log(`${this.name} barks`);
}
fetch() {
console.log(`${this.name} fetches`);
}
}
const dog = new Dog('Buddy', 'Golden');
dog.speak(); // "Buddy barks"(重写方法)
dog.fetch(); // "Buddy fetches"(子类方法)
console.log(dog instanceof Dog); // true
console.log(dog instanceof Animal); // true
super 关键字
JavaScript
class Parent {
constructor(name) {
this.name = name;
}
method() {
console.log('Parent method');
}
}
class Child extends Parent {
constructor(name, extra) {
super(name); // 调用父类构造函数
this.extra = extra;
}
method() {
super.method(); // 调用父类方法
console.log('Child method');
}
static staticMethod() {
super.staticMethod(); // 调用父类静态方法
}
}
const child = new Child('Tom', 'data');
child.method(); // "Parent method" → "Child method"
继承原理
JavaScript
// ES6 继承底层仍是原型链
class Animal {}
class Dog extends Animal {}
console.log(Dog.__proto__ === Animal); // true(类继承)
console.log(Dog.prototype.__proto__ === Animal.prototype); // true(原型继承)
// 对比 ES5 寄生组合继承
// ES6 extends 自动实现:
// 1. Dog.prototype 继承 Animal.prototype
// 2. Dog 继承 Animal 的静态属性/方法
// 3. super 调用父类构造函数
// ES5 等价实现
function Dog(name, breed) {
Animal.call(this, name); // super(name)
this.breed = breed;
}
Object.setPrototypeOf(Dog, Animal); // 继承静态方法
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
静态方法继承
JavaScript
class Animal {
static create(name) {
return new Animal(name);
}
}
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
}
// 子类继承父类静态方法
const dog = Dog.create('Buddy'); // Animal 实例,不是 Dog
console.log(dog instanceof Animal); // true
console.log(dog instanceof Dog); // false
// 修复:子类重写静态方法
class Dog extends Animal {
static create(name, breed) {
return new Dog(name, breed);
}
}
const realDog = Dog.create('Buddy', 'Golden');
console.log(realDog instanceof Dog); // true
方法重写与 super
JavaScript
class Animal {
speak() {
console.log(`${this.name} makes a sound`);
}
}
class Dog extends Animal {
speak() {
// super.speak() 调用父类版本
super.speak(); // "Buddy makes a sound"
console.log(`${this.name} barks`); // "Buddy barks"
}
}
class Cat extends Animal {
speak() {
// 不调用 super,完全重写
console.log(`${this.name} meows`);
}
}
const dog = new Dog('Buddy');
dog.speak();
// "Buddy makes a sound"
// "Buddy barks"
const cat = new Cat('Whiskers');
cat.speak(); // "Whiskers meows"
ES2022 私有属性
JavaScript
class Person {
// 私有属性(真正私有,外部无法访问)
#secret = 'private data';
#password;
constructor(name, password) {
this.name = name;
this.#password = password;
}
// 私有方法
#validate() {
return this.#password.length > 6;
}
getSecret() {
return this.#secret; // 内部可访问
}
}
const p = new Person('Tom', '1234567');
console.log(p.name); // 'Tom'
console.log(p.getSecret()); // 'private data'
console.log(p.#secret); // Error: 私有属性外部不可访问
console.log(p.#validate()); // Error: 私有方法外部不可访问
注意事项
- 子类构造函数必须先调用
super()才能使用thisextends会继承父类的静态方法和静态属性- 类方法没有函数提升,必须先定义后使用
- 类内部默认严格模式
JavaScript
// 必须先调用 super
class Child extends Parent {
constructor() {
// this.x = 1; // Error: 必须先调用 super
super(); // 正确顺序
this.x = 1; // super 之后才能使用 this
}
}
// 类无提升
const dog = new Dog(); // Error: Dog 未定义
class Dog extends Animal {}
// 正确顺序
class Dog extends Animal {}
const dog = new Dog(); // OK
要点总结
class是语法糖,底层仍是原型链和构造函数extends实现继承,自动处理原型链和静态继承super()在子类构造函数中调用父类构造函数,必须先执行super.method()调用父类方法,super.staticMethod()调用父类静态方法- 子类构造函数必须先调用
super()才能使用this - ES2022
#私有属性真正私有,外部无法访问
📝 发现内容有误?点击此处直接编辑