返回

方式 1:原型链继承

IOS

JavaScript 继承:揭开六种途径的奥秘

在 JavaScript 王国中,继承扮演着至关重要的角色,为重用代码、实现多态性和提高代码可维护性铺平了道路。通过继承,你可以创建类或对象,它们从现有类或对象(称为父类或父对象)中继承属性和行为,同时还可以添加自己的特有特性。

JavaScript 提供了六种主要途径来实现继承:原型链继承、借助构造函数继承、组合继承、Object.create方法、寄生式继承和寄生组合式继承。每种方法都有其独特的优点和缺点,让我们逐一探索。

原型链继承:沿袭祖先的足迹

原型链继承是 JavaScript 中最基本的继承机制。它基于这样的思想:每个对象都有一个指向其父对象的内部指针,称为 [[Prototype]]。当一个子对象访问一个它不直接拥有的属性或方法时,它会沿原型链向上查找,直到找到该属性或方法。

代码示例:

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

Person.prototype.greet = function() {
  console.log(`Hello, my name is ${this.name}.`);
};

function Employee(name, jobTitle) {
  this.name = name;
  this.jobTitle = jobTitle;
}

// 将 Employee 的原型指向 Person.prototype
Employee.prototype = new Person();

const employee = new Employee('John Doe', 'Software Engineer');

employee.greet(); // 输出: Hello, my name is John Doe.

借助构造函数继承:继承父辈的蓝图

借助构造函数继承更显式地实现继承。它使用父构造函数来设置子构造函数的 [[Prototype]] 属性。这种方法也被称为经典继承。

代码示例:

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

function Employee(name, jobTitle) {
  // 调用父构造函数
  Person.call(this, name);

  this.jobTitle = jobTitle;
}

const employee = new Employee('John Doe', 'Software Engineer');

employee.greet(); // 输出: Hello, my name is John Doe.

组合继承:借鉴传统与创新

组合继承融合了原型链继承和借助构造函数继承的优点。它首先通过 [[Prototype]] 属性建立原型链,然后使用 [[Prototype]] 属性指向父构造函数来借用构造函数。

代码示例:

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

Person.prototype.greet = function() {
  console.log(`Hello, my name is ${this.name}.`);
};

function Employee(name, jobTitle) {
  // 通过原型链继承
  this.__proto__ = Person.prototype;

  // 调用父构造函数
  Person.call(this, name);

  this.jobTitle = jobTitle;
}

const employee = new Employee('John Doe', 'Software Engineer');

employee.greet(); // 输出: Hello, my name is John Doe.

Object.create 方法:轻量级继承

Object.create 方法创建了一个新对象,该对象的 [[Prototype]] 属性指向指定的对象。这种方法提供了一种简洁的方式来创建对象,而无需涉及构造函数。

代码示例:

const person = {
  name: 'John Doe',

  greet: function() {
    console.log(`Hello, my name is ${this.name}.`);
  }
};

const employee = Object.create(person);
employee.jobTitle = 'Software Engineer';

employee.greet(); // 输出: Hello, my name is John Doe.

寄生式继承:间接继承

寄生式继承采用一种更灵活的方法,它创建一个对象来扩展另一个对象,而不是直接继承。这允许动态添加和修改属性和方法。

代码示例:

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

const employee = (function(person) {
  const newObject = Object.create(null);

  newObject.jobTitle = 'Software Engineer';

  return newObject;
})(new Person('John Doe'));

employee.greet(); // 输出: Hello, my name is John Doe.

寄生组合式继承:最佳实践

寄生组合式继承结合了寄生式继承和组合继承的优点。它创建了一个对象来扩展父对象,同时通过 [[Prototype]] 属性访问父原型。这种方法是最常用的 JavaScript 继承模式。

代码示例:

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

Person.prototype.greet = function() {
  console.log(`Hello, my name is ${this.name}.`);
};

const employee = (function(person) {
  const newObject = Object.create(person);

  newObject.jobTitle = 'Software Engineer';

  return newObject;
})(new Person('John Doe'));

employee.greet(); // 输出: Hello, my name is John Doe.

结语:选择最合适的继承方式

JavaScript 继承的六种途径为开发人员提供了构建复杂、可扩展应用程序的强大工具。选择哪种方法取决于具体需求和应用程序的设计。通过掌握这些技术,你可以利用 JavaScript 的强大功能,创建健壮且高效的代码。

常见问题解答

  1. 原型链继承和借助构造函数继承有什么区别?

    原型链继承使用 [[Prototype]] 属性在对象之间建立隐式连接,而借助构造函数继承使用父构造函数来显式设置子构造函数的 [[Prototype]] 属性。

  2. 组合继承有什么好处?

    组合继承同时利用了原型链继承和借助构造函数继承的优点,允许访问父原型和调用父构造函数。

  3. Object.create 方法与其他继承方法相比有什么优势?

    Object.create 方法提供了一种轻量级的方式来创建对象,而无需涉及构造函数,这在某些情况下可能是可取的。

  4. 寄生式继承和寄生组合式继承有什么不同?

    寄生式继承创建一个新对象来扩展另一个对象,而寄生组合式继承创建了一个对象来扩展父对象,同时访问父原型。

  5. 哪种继承方法是最常用的?

    寄生组合式继承是最常用的 JavaScript 继承模式,因为它结合了寄生式继承和组合继承的优点。