返回

JS 6 种继承方式的优缺点大赏,从此掌握 JS 世界的“三座大山”之一

前端

JavaScript 继承:深入理解六种常见继承方式

引言

在 JavaScript 中,继承是一种至关重要的概念,它允许我们基于现有对象创建新的对象,从而实现代码复用、提高可维护性和编写更简洁的程序。本文将深入探讨 JavaScript 中六种常见的继承方式,包括原型链继承、组合继承、原型继承、ES6 class、对象冒充和寄生组合式继承。

原型链继承

原型链继承是一种基础而流行的继承方式,利用对象的原型属性实现继承。每个对象都拥有一个原型属性,指向另一个称为原型对象的对象。当对象尝试访问其自身属性中不存在的属性时,它会沿着原型链向上查找,直到找到该属性或到达原型链的顶部。

原型链继承的优点在于其简单易用,且无需使用特殊语法。然而,它也存在一些缺点,如可能导致难以理解和维护的代码,以及无法适用于所有情况。

代码示例:

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.greet = function() {
  console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};

function Student(name, age, major) {
  Person.call(this, name, age);
  this.major = major;
}

Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;

Student.prototype.study = function() {
  console.log(`${this.name} is studying ${this.major}.`);
};

const student = new Student('John Doe', 20, 'Computer Science');
student.greet(); // Hello, my name is John Doe and I am 20 years old.
student.study(); // John Doe is studying Computer Science.

组合继承

组合继承融合了原型链继承和构造函数继承的优点。它通过创建一个新对象,并将这个新对象的原型属性设置为另一个对象的实例来实现继承。这样,新对象既可以访问另一个对象的属性和方法,又可以拥有自己的属性和方法。

组合继承的优势在于它同时具备原型链继承和构造函数继承的优点。然而,它也更加复杂,可能导致难以理解和维护的代码。

代码示例:

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.greet = function() {
  console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};

function Student(name, age, major) {
  Person.call(this, name, age);
  this.major = major;
}

Student.prototype = new Person();
Student.prototype.constructor = Student;

Student.prototype.study = function() {
  console.log(`${this.name} is studying ${this.major}.`);
};

const student = new Student('John Doe', 20, 'Computer Science');
student.greet(); // Hello, my name is John Doe and I am 20 years old.
student.study(); // John Doe is studying Computer Science.

原型继承

原型继承是一种通过直接将一个对象的原型属性设置为另一个对象的实例来实现继承的方式。这样,新对象可以访问另一个对象的属性和方法,但无法拥有自己的属性和方法。

原型继承简单易用,且无需特殊语法。然而,它同样存在一些局限性,如无法适用于所有情况,并且可能导致难以理解和维护的代码。

代码示例:

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.greet = function() {
  console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};

function Student(name, age, major) {
  Person.call(this, name, age);
  this.major = major;
}

Student.prototype = Person.prototype;

Student.prototype.study = function() {
  console.log(`${this.name} is studying ${this.major}.`);
};

const student = new Student('John Doe', 20, 'Computer Science');
student.greet(); // Hello, my name is John Doe and I am 20 years old.
student.study(); // John Doe is studying Computer Science.

ES6 class

ES6 class 引入了更简洁、更易读、更易维护的继承方式。它借鉴了其他编程语言中 class 的概念。

ES6 class 的优势在于它简单易用,且无需特殊语法。然而,它仅适用于 ES6 环境,并且可能与其他 JavaScript 代码不兼容。

代码示例:

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  greet() {
    console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
  }
}

class Student extends Person {
  constructor(name, age, major) {
    super(name, age);
    this.major = major;
  }

  study() {
    console.log(`${this.name} is studying ${this.major}.`);
  }
}

const student = new Student('John Doe', 20, 'Computer Science');
student.greet(); // Hello, my name is John Doe and I am 20 years old.
student.study(); // John Doe is studying Computer Science.

对象冒充

对象冒充是一种通过将一个对象的属性和方法复制到另一个对象来实现继承的方式。这样,新对象可以访问另一个对象的属性和方法,但无法拥有自己的属性和方法。

对象冒充简单易用,且无需特殊语法。然而,它同样存在局限性,如无法适用于所有情况,并且可能导致难以理解和维护的代码。

代码示例:

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.greet = function() {
  console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};

function Student(name, age, major) {
  const person = new Person(name, age);

  person.major = major;
  person.study = function() {
    console.log(`${this.name} is studying ${this.major}.`);
  };

  return person;
}

const student = new Student('John Doe', 20, 'Computer Science');
student.greet(); // Hello, my name is John Doe and I am 20 years old.
student.study(); // John Doe is studying Computer Science.

寄生组合式继承

寄生组合式继承融合了原型链继承、构造函数继承和对象冒充的优点。它通过创建一个新对象,并将这个新对象的原型属性设置为另一个对象的实例,同时将另一个对象的属性和方法复制到新对象来实现继承。这样,新对象既可以访问另一个对象的属性和方法,又可以拥有自己的属性和方法。

寄生组合式继承的优势在于它结合了多种继承方式的优点。然而,它也更加复杂,可能导致难以理解和维护的代码。

代码示例:

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.greet = function() {
  console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};

function Student(name, age, major) {
  const person = new Person(name, age);

  person.major = major;
  person.】