JavaScript 中的继承是面向对象编程的核心概念,旨在实现代码复用和资源整合。以下是 JavaScript 中常见的继承方案及其特点:
1. 原型链继承- 核心:子类的原型指向父类的实例。
- 实现:function Person(name) { this.name = name;}Person.prototype.sayHi = function() { console.log('hello world'); };function Student(age) { this.age = age;}Student.prototype = new Person('千锋大前端');const s = new Student(10);
- 缺点:
子类没有自己的原型。
所有子类实例继承的属性相同。
- 优点:属性和方法都能继承。
2. 借用构造函数继承- 核心:利用 call 或 apply 调用父类构造函数,改变 this 指向。
- 实现:function Person(name) { this.name = name;}Person.prototype.sayHi = function() { console.log('hello world'); };function Student(age, name) { this.age = age; Person.call(this, name);}const s = new Student(10, '千锋大前端');
- 缺点:只能继承父类的属性,无法继承原型上的方法。
- 优点:
子类有自己的原型。
每个子类实例继承独立的属性。
3. 基础组合继承- 核心:结合原型链继承和借用构造函数继承。
- 实现:function Person(name) { this.name = name;}Person.prototype.sayHi = function() { console.log('hello world'); };function Student(age, name) { this.age = age; Person.call(this, name);}Student.prototype = new Person();const s = new Student(10, '千锋大前端');
- 优点:
继承属性和方法。
子类实例拥有独立属性。
4. 寄生继承- 核心:利用空对象包装父类实例,设置原型后返回。
- 实现:function Parent(name) { this.name = name;}Parent.prototype.sayHi = function() { console.log('hello world'); };function Student(parent, name) { let student = Object.create(parent); student.name = name; student.sayHello = function() { console.log(`Hello, my name is ${this.name}`); }; return student;}let parent = new Parent('千锋大前端');let student = Student(parent, '千锋大前端');
5. 寄生组合继承- 核心:结合寄生继承和组合继承,避免重复调用构造函数。
- 实现:function inheritPrototype(student, person) { let prototype = Object.create(person.prototype); prototype.constructor = student; student.prototype = prototype;}function Person(name) { this.name = name;}Person.prototype.sayHi = function() { console.log('hello world'); };function Student(age, name) { this.age = age; Person.call(this, name);}inheritPrototype(Student, Person);Student.prototype.sayHello = function() { console.log(`Hello, My name is ${this.name}`); };let instance = new Student(10, '千锋大前端');
- 优点:
避免重复调用构造函数。
防止原型链污染。
6. ES6 类继承- 核心:使用 extends 关键字和 super 方法。
- 实现:class Person { constructor(name) { this.name = name; } sayHi() { console.log('Hello world'); }}class Student extends Person { constructor(name, age) { super(name); this.age = age; } sayAge() { console.log(`Hello, My name is ${this.name}`); }}let instance = new Student('千锋大前端', 10);
- 注意:需在子类构造器中使用 super 继承父类属性。
总结- 原型链继承:简单但灵活性低。
- 借用构造函数继承:解决属性独立问题,但无法继承方法。
- 组合继承:结合两者优点,但效率较低。
- 寄生组合继承:高效且灵活,推荐使用。
- ES6 类继承:语法简洁,现代开发首选。
通过理解这些继承方案,可以更好地选择适合项目需求的实现方式,提升代码的可维护性和扩展性。