返回

JavaScript继承

前端

原型链继承

JavaScript中最传统的继承方式是原型链继承,其基本思想是通过将父类的原型对象赋给子类的原型对象来实现继承。这种方式可以简单理解为:子类继承父类的属性和方法,子类可以访问和修改这些继承的属性和方法,但父类不能访问和修改子类独有的属性和方法。

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

Parent.prototype.greet = function() {
  console.log("Hello, my name is " + this.name);
};

function Child(name) {
  Parent.call(this, name);
}

Child.prototype = new Parent();

Child.prototype.sayHello = function() {
  console.log("Hello from the child!");
};

const parent = new Parent("John");
const child = new Child("Mary");

parent.greet(); // Hello, my name is John
child.greet(); // Hello, my name is Mary
child.sayHello(); // Hello from the child!

缺点:

  1. 内存开销: 由于每个子类都会创建一个新的原型对象,因此原型链继承可能导致内存开销。
  2. 属性共享: 由于所有子类共享父类的原型对象,因此父类的属性和方法在子类之间是共享的。这意味着对父类属性或方法的更改将影响所有子类。
  3. 方法调用开销: 由于每次调用子类方法时都需要沿着原型链搜索,因此原型链继承可能导致方法调用开销。

ES6 class继承

ES6中引入了新的class,提供了更简洁和更现代的继承语法。ES6 class继承本质上仍然是原型链继承,但它提供了更清晰和更易于理解的语法。

class Parent {
  constructor(name) {
    this.name = name;
  }

  greet() {
    console.log("Hello, my name is " + this.name);
  }
}

class Child extends Parent {
  constructor(name) {
    super(name);
  }

  sayHello() {
    console.log("Hello from the child!");
  }
}

const parent = new Parent("John");
const child = new Child("Mary");

parent.greet(); // Hello, my name is John
child.greet(); // Hello, my name is Mary
child.sayHello(); // Hello from the child!

优势:

  1. 简洁的语法: ES6 class继承提供了简洁的语法,使代码更易于阅读和理解。
  2. 更好的错误处理: ES6 class继承提供了更好的错误处理,当继承关系出现问题时会抛出错误。
  3. 私有和受保护的属性和方法: ES6 class继承允许定义私有和受保护的属性和方法,从而提高代码的安全性。

缺点:

  1. 不支持多重继承: ES6 class继承不支持多重继承,这意味着一个子类只能继承一个父类。

继承类型

单继承: 一个子类只继承一个父类。

多重继承: 一个子类继承多个父类。JavaScript不支持多重继承,但可以使用组合或代理等技术来模拟多重继承。

层次继承: 父类和子类形成一个层次结构,子类继承父类的属性和方法,并且可以进一步派生出子类。

接口继承: 子类继承父类的接口,但并不继承父类的实现。接口继承可以使代码更灵活和更易于维护。

结论

JavaScript的继承模型拥有独特的特性和优缺点,理解并掌握这些特性将帮助你写出更健壮的代码。在选择继承机制时,需要考虑具体的需求和权衡各种继承方式的利弊。