ES5继承最佳实践和ES6(class + extends)对比
在 ** ES6** 中,class 和 extends 关键字提供了一种更简洁、更易读的方式来实现继承。实际上,ES6 的类继承机制在底层实现上与 ES5 的寄生组合继承相似。下面我们将分别使用 ES6 的 class 和 extends 关键字以及 ES5 的寄生组合继承方式来实现继承,并进行对比。
使用 ES6 的 class 和 extends 关键字实现继承
class Parent {
constructor(name) {
this.name = name;
}
sayHello() {
console.log(`Hello, ${this.name}`);
}
static staticMethod() {
console.log('This is a static method in Parent.');
}
}
class Child extends Parent {
constructor(name, age) {
super(name); // 调用父类的构造函数
this.age = age;
}
introduce() {
console.log(`Hi, I'm ${this.name} and I'm ${this.age} years old.`);
}
static staticMethod() {
super.staticMethod(); // 调用父类的静态方法
console.log('This is a static method in Child.');
}
}
const child = new Child('Alice', 25);
child.sayHello(); // 输出: Hello, Alice
child.introduce(); // 输出: Hi, I'm Alice and I'm 25 years old.
Child.staticMethod(); // 输出: This is a static method in Parent. This is a static method in Child.
使用 ES5 的寄生组合继承实现继承
function Parent(name) {
this.name = name;
}
Parent.prototype.sayHello = function() {
console.log(`Hello, ${this.name}`);
};
Parent.staticMethod = function() {
console.log('This is a static method in Parent.');
};
function Child(name, age) {
Parent.call(this, name); // 调用 Parent 构造函数
this.age = age;
}
function inheritPrototype(child, parent) {
var prototype = Object.create(parent.prototype); // 创建父类原型的一个副本
prototype.constructor = child; // 修复构造函数指向
child.prototype = prototype; // 将副本赋值给子类的原型
}
inheritPrototype(Child, Parent);
Child.prototype.introduce = function() {
console.log(`Hi, I'm ${this.name} and I'm ${this.age} years old.`);
};
Child.staticMethod = function() {
Parent.staticMethod(); // 调用父类的静态方法
console.log('This is a static method in Child.');
};
const child = new Child('Alice', 25);
child.sayHello(); // 输出: Hello, Alice
child.introduce(); // 输出: Hi, I'm Alice and I'm 25 years old.
Child.staticMethod(); // 输出: This is a static method in Parent. This is a static method in Child.
对比和结论
1. 语法简洁性:
- ES6:使用 class 和 extends 关键字实现继承,语法更加简洁和清晰,符合面向对象编程的直观表达方式。
-
- ES5:寄生组合继承通过函数和原型链实现继承,语法相对复杂,需要手动设置原型链和修复 constructor 属性。
2. 实例属性和方法:
- ES6:实例属性和方法在类的 constructor 和类体内定义,易于阅读和维护。
- ES5:实例属性在构造函数内定义,方法在原型对象上定义,分离较为明显。
3.静态属性和方法:
- ES6:使用 static 关键字定义静态属性和方法,语法直观且易于理解。
- ES5:静态属性和方法直接赋给构造函数,需要额外定义。
4. 调用父类方法:
- ES6:使用 super 关键字调用父类的构造函数和静态方法,语法简单。
- ES5:调用父类方法需要显式地使用 call 方法或父类构造函数名,较为繁琐。
总结
ES6 的 class 和 extends 关键字实际上是寄生组合继承的一种语法糖,底层实现类似,只是提供了一种更简洁和直观的方式来进行面向对象编程。
评论区