JavaScript继承机制主要包括原型链继承、构造函数继承、组合继承(原型+构造函数)、原型式继承和寄生式继承等方法,通过这些方法实现对象间的属性和方法复用。
JavaScript(简称JS)继承机制是面向对象编程中的一个重要概念,它允许一个对象获得另一个对象的属性和方法,本文将详细介绍JS的继承机制源码,并使用小标题和单元表格进行组织,文章末尾将包含一个相关问题与解答栏目,提出两个与本文相关的问题,并做出解答。
1. 原型链继承
原型链继承是JS中最基础的继承方式,通过原型链实现对象间的继承关系。
代码示例
function Animal(name) {    this.name = name;}Animal.prototype.sayName = function() {    console.log(this.name);}function Dog(name, breed) {    Animal.call(this, name);    this.breed = breed;}Dog.prototype = Object.create(Animal.prototype);Dog.prototype.constructor = Dog;Dog.prototype.bark = function() {    console.log("Woof!");}var myDog = new Dog("Max", "Golden Retriever");myDog.sayName(); // MaxmyDog.bark(); // Woof!优缺点分析
| 优点 | 缺点 | 
| 实现简单,易于理解 | 实例化子类时,无法向父类构造函数传参 | 
2. 构造函数继承
构造函数继承通过在子类构造函数中调用父类构造函数来实现继承。
代码示例
function Animal(name) {    this.name = name;}Animal.prototype.sayName = function() {    console.log(this.name);}function Dog(name, breed) {    Animal.call(this, name);    this.breed = breed;}Dog.prototype = new Animal();Dog.prototype.bark = function() {    console.log("Woof!");}var myDog = new Dog("Max", "Golden Retriever");myDog.sayName(); // MaxmyDog.bark(); // Woof!优缺点分析
| 优点 | 缺点 | 
| 可以实现多重继承 | 父类方法被多次调用,影响性能 | 
3. 组合继承
组合继承结合了原型链继承和构造函数继承的优点,是实现继承的常用方式之一。
代码示例
function Animal(name) {    this.name = name;}Animal.prototype.sayName = function() {    console.log(this.name);}function Dog(name, breed) {    Animal.call(this, name);    this.breed = breed;}Dog.prototype = Object.create(Animal.prototype);Dog.prototype.constructor = Dog;Dog.prototype.bark = function() {    console.log("Woof!");}var myDog = new Dog("Max", "Golden Retriever");myDog.sayName(); // MaxmyDog.bark(); // Woof!优缺点分析
| 优点 | 缺点 | 
| 融合了原型链和构造函数的优点 | 调用两次父类构造函数,影响性能 | 
4. 寄生组合继承
寄生组合继承是对组合继承的优化,通过中间函数实现原型链继承。
代码示例
function Animal(name) {    this.name = name;}Animal.prototype.sayName = function() {    console.log(this.name);}function Dog(name, breed) {    Animal.call(this, name);    this.breed = breed;}Dog.prototype = Object.create(Animal.prototype);Dog.prototype.constructor = Dog;Dog.prototype.bark = function() {    console.log("Woof!");}var myDog = new Dog("Max", "Golden Retriever");myDog.sayName(); // MaxmyDog.bark(); // Woof!优缺点分析
| 优点 | 缺点 | 
| 避免了两次调用父类构造函数的性能问题 | 实现复杂,不如组合继承直观 | 
5. ES6 Class继承
ES6引入了class关键字,使继承更加简洁和易读。
代码示例
class Animal {    constructor(name) {        this.name = name;    }    sayName() {        console.log(this.name);    }}class Dog extends Animal {    constructor(name, breed) {        super(name);        this.breed = breed;    }    bark() {        console.log("Woof!");    }}let myDog = new Dog("Max", "Golden Retriever");myDog.sayName(); // MaxmyDog.bark(); // Woof!优缺点分析
| 优点 | 缺点 | 
| 语法简洁,易于阅读和编写 | 浏览器兼容性问题,需要Babel转码 | 
相关问题与解答
1、问题:为什么ES6中的class实际上是原型继承的语法糖?
解答:ES6中的class关键字本质上是对原型继承机制的封装,提供了一种更简洁、更易读的语法形式,class背后的实现仍然是基于原型链的继承机制,当使用extends关键字时,子类的原型会被设置为父类的实例,从而实现了原型继承,ES6 class只是一种语法糖,其本质并未改变JS原有的原型继承机制。
2、问题:如何避免在组合继承中重复调用父类构造函数?
解答:为了避免在组合继承中重复调用父类构造函数,可以使用寄生组合继承,寄生组合继承通过创建一个中间函数,利用Object.create()方法创建子类的原型,并将父类的原型赋值给子类的原型,这样,父类构造函数只会被调用一次,从而避免了性能问题,具体实现如下:
“`javascript
function inherits(Child, Parent) {
// …省略中间函数实现…
}
“`
 

 QQ客服
QQ客服