javascript中如何实现继承(附案例)

在 JavaScript 中,有多种实现继承的方法,最常用的有原型链继承、构造函数继承、组合继承和 class 继承(ES6)。下面以 ES6 的 class 继承为例,展示如何实现继承:

示例:

// 父类
class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} makes a noise.`);
  }
}

// 子类继承父类
class Dog extends Animal {
  constructor(name, breed) {
    super(name); // 调用父类构造函数
    this.breed = breed;
  }

  speak() {
    console.log(`${this.name} barks.`);
  }
}

const dog = new Dog('Buddy', 'Golden Retriever');
dog.speak(); // 输出: Buddy barks.

解释:

  1. Animal 是父类,它有一个构造函数和一个方法 speak()
  2. Dog 是子类,使用了 extends 关键字继承 Animal。子类的构造函数使用 super() 调用了父类的构造函数。
  3. 子类可以继承父类的方法,也可以重写父类方法(如 speak())。

这是 ES6 中推荐的继承方式,简洁且符合面向对象编程的设计。

在 JavaScript 中,实现继承的方式有多种,下面分别给出几种常用继承方式的代码示例。

1. 原型链继承

通过将子类的原型指向父类的实例来实现继承。

// 父类构造函数
function Animal(name) {
  this.name = name;
}

Animal.prototype.speak = function() {
  console.log(this.name + ' makes a noise.');
};

// 子类构造函数
function Dog(name) {
  this.name = name;
}

// 原型链继承
Dog.prototype = new Animal();

const dog = new Dog('Buddy');
dog.speak(); // 输出: Buddy makes a noise.

缺点:所有子类实例共享父类实例的属性,如果修改父类引用类型的属性会影响所有子类实例。


2. 构造函数继承

通过在子类构造函数中调用父类构造函数,来避免共享父类的引用属性。

// 父类构造函数
function Animal(name) {
  this.name = name;
}

// 子类构造函数
function Dog(name, breed) {
  Animal.call(this, name); // 调用父类构造函数
  this.breed = breed;
}

const dog = new Dog('Buddy', 'Golden Retriever');
console.log(dog.name); // 输出: Buddy
console.log(dog.breed); // 输出: Golden Retriever

优点:可以避免原型链继承中的共享引用问题。


3. 组合继承

组合了原型链和构造函数继承的优点,父类的属性通过构造函数继承,方法通过原型链继承。

// 父类构造函数
function Animal(name) {
  this.name = name;
}

Animal.prototype.speak = function() {
  console.log(this.name + ' makes a noise.');
};

// 子类构造函数
function Dog(name, breed) {
  Animal.call(this, name); // 继承属性
  this.breed = breed;
}

// 继承父类方法
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

const dog = new Dog('Buddy', 'Golden Retriever');
dog.speak(); // 输出: Buddy makes a noise.

优点:能够避免原型链的引用共享问题,并且继承了父类的属性和方法。


4. ES6 class 继承

使用 class 语法更加简洁,且语义更清晰。

// 父类
class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name} makes a noise.`);
  }
}

// 子类
class Dog extends Animal {
  constructor(name, breed) {
    super(name); // 调用父类构造函数
    this.breed = breed;
  }

  speak() {
    console.log(`${this.name} barks.`);
  }
}

const dog = new Dog('Buddy', 'Golden Retriever');
dog.speak(); // 输出: Buddy barks.

优点:语法简洁,且 ES6 class 是语法糖,底层仍是基于原型实现的。


5. 寄生组合式继承

这是组合继承的优化版本,避免了调用两次父类构造函数的问题。

function Animal(name) {
  this.name = name;
}

Animal.prototype.speak = function() {
  console.log(this.name + ' makes a noise.');
};

function Dog(name, breed) {
  Animal.call(this, name); // 调用父类构造函数,继承属性
  this.breed = breed;
}

// 优化继承
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

const dog = new Dog('Buddy', 'Golden Retriever');
dog.speak(); // 输出: Buddy makes a noise.

优点:避免了调用两次父类构造函数的问题,性能更优。


总结:

  1. 原型链继承:简单但存在引用共享问题。
  2. 构造函数继承:可以避免共享引用类型,但无法继承方法。
  3. 组合继承:结合原型链和构造函数继承的优点,但调用了两次父类构造函数。
  4. ES6 class 继承:语法简洁,是基于原型链的语法糖。
  5. 寄生组合式继承:优化版的组合继承,性能更好。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端李易安

打赏1元鼓励作者

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值