返回

剖析JavaScript常用继承模式,披荆斩棘迈向进阶之路

前端

编程世界中,JavaScript以其灵活性脱颖而出,而理解继承的奥秘则是开启进阶大门的关键。从面向对象编程的角度出发,JavaScript提供了多种继承模式,助力开发者构建出强大灵活的应用。接下来,我们将踏上精彩的探索之旅,详细解析JavaScript中常见的继承模式,助您成为一名娴熟的程序员。

一、原型链继承:初探JavaScript的根基

在JavaScript中,对象可以通过原型链实现继承,这是一种简单却又强大的方式。我们都知道,对象可以通过Object.create()方法来创建,而Object.create()返回的新对象会将原对象作为其原型。这样一来,新对象就能直接访问原对象的属性和方法。接下来,让我们借用代码加深对原型链继承的理解:

const person = {
  name: '张三',
  age: 30,
};

const student = Object.create(person);
student.school = '清华大学';

console.log(student.name); // '张三'
console.log(student.age); // 30
console.log(student.school); // '清华大学'

在上面的例子中,我们创建了一个person对象,并通过Object.create()方法创建了一个student对象,student对象的原型是person对象。因此,student对象可以访问person对象的属性和方法,同时也能拥有自己的属性和方法。

二、构造函数继承:深入理解继承的本质

构造函数继承是JavaScript中另一种常见的继承方式,它利用了构造函数的特性来实现继承。在构造函数中,通过调用父类的构造函数,子类就能继承父类的属性和方法。理解构造函数继承的关键在于,它创建了一个新的对象,该对象是父类构造函数的实例。让我们通过一个代码例子来巩固对构造函数继承的认识:

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

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

const student = new Student('李四', 25, '北京大学');

console.log(student.name); // '李四'
console.log(student.age); // 25
console.log(student.school); // '北京大学'

在上面的例子中,我们定义了两个构造函数,Person和Student。Student构造函数继承了Person构造函数,这意味着Student对象可以访问Person对象的所有属性和方法。同时,Student对象也可以拥有自己的属性和方法。

三、组合继承:融合原型链与构造函数的智慧

组合继承是一种更加灵活的继承方式,它将原型链继承和构造函数继承结合起来。通过组合继承,子类可以同时继承父类的属性和方法,以及父类的原型链。组合继承的实现方法是先通过构造函数继承父类,然后再通过Object.create()方法设置子类的原型为父类的实例。以下是组合继承的代码示例:

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

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

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

const student = new Student('王五', 28, '复旦大学');

console.log(student.name); // '王五'
console.log(student.age); // 28
console.log(student.school); // '复旦大学'

在上面的例子中,Student构造函数继承了Person构造函数,同时Student对象的原型被设置为Person对象的实例。这样一来,Student对象就可以访问Person对象的属性和方法,也可以访问Person对象的原型链上的属性和方法。

四、原型式继承:另辟蹊径的继承之路

原型式继承是一种与前面提到的继承方式截然不同的继承方式。在原型式继承中,子对象是通过克隆父对象来创建的。这样一来,子对象就拥有了父对象的属性和方法。原型式继承的实现方法是通过Object.create()方法来创建子对象,并指定父对象为原型。以下是原型式继承的代码示例:

const person = {
  name: '赵六',
  age: 35,
};

const student = Object.create(person);
student.school = '上海交通大学';

console.log(student.name); // '赵六'
console.log(student.age); // 35
console.log(student.school); // '上海交通大学'

在上面的例子中,我们使用Object.create()方法创建了一个student对象,并指定person对象为原型。这样一来,student对象就拥有了person对象的属性和方法,同时也可以拥有自己的属性和方法。

五、寄生式继承:巧妙地借用父类功能

寄生式继承是一种非常巧妙的继承方式,它通过创建一个新的对象来继承父对象。这个新对象包含了父对象的属性和方法,同时也可以拥有自己的属性和方法。寄生式继承的实现方法是通过Object.create()方法创建一个新对象,并将其作为父对象的方法来执行。以下是寄生式继承的代码示例:

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

function Student(name, age, school) {
  const person = new Person(name, age);
  person.school = school;
  return person;
}

const student = new Student('孙七', 40, '浙江大学');

console.log(student.name); // '孙七'
console.log(student.age); // 40
console.log(student.school); // '浙江大学'

在上面的例子中,我们创建了一个Person构造函数和一个Student函数。Student函数通过new Person()创建了一个person对象,然后将school属性添加到person对象上,最后返回person对象。这样一来,student对象就拥有了Person对象的所有属性和方法,同时也可以拥有自己的属性和方法。

六、寄生组合式继承:集大成者的智慧结晶

寄生组合式继承是将寄生式继承和组合继承结合起来的一种继承方式。它融合了原型链继承、构造函数继承和寄生式继承的优点,是一种非常灵活且强大的继承方式。寄生组合式继承的实现方法是先通过构造函数继承父类,然后再通过Object.create()方法设置子类的原型为父类的实例,最后通过寄生式继承的方式将父对象的方法添加到子对象上。以下是寄生组合式继承的代码示例:

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

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

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

function StudentWrapper(name, age, school) {
  const person = new Person(name, age);
  person.school = school;
  return person;
}

const student = new StudentWrapper('周八', 45, '中山大学');

console.log(student.name); // '周八'
console.log(student.age); // 45
console.log(student.school); // '中山大学'

在上面的例子中,我们创建了一个Person构造函数、一个Student构造函数和一个StudentWrapper函数。Student构造函数继承了Person构造函数,Student对象的原型被设置为Person对象的实例。StudentWrapper函数通过new Person()创建了一个person对象,然后将school属性添加到person对象上,最后返回person对象。这样一来,student对象就拥有了Person对象的所有属性和方法,同时也可以拥有自己的属性和方法。

七、extends 类继承:ES6的强大助力

在ES6中,我们迎来了更加简洁和直观的类继承方式。通过extends,我们可以轻松实现类的继承。在子类中,我们可以直接访问父类的方法和属性,而无需使用复杂的技巧。以下是extends类继承的代码示例:

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

  getName() {
    return this.name;
  }

  getAge() {
    return this.age;
  }
}

class Student extends Person {
  constructor(name, age, school