返回

前端百题斩【017】——清晰解析原型链及其运作机制

前端

一、前端百题斩【017】——初探原型链

在JavaScript中,每一个对象都自带一个原型属性,它充当了连接对象的纽带,使得对象可以访问另一个对象的所有属性和方法。这些对象间的关联恰似一条原型链,将各个对象串联起来,形成了一条牢固而有序的链条。

举个简单的例子,假设我们定义了以下两个对象:

const person = {
  name: 'John Doe',
  age: 30
};

const student = {
  name: 'Jane Smith',
  age: 20,
  major: 'Computer Science'
};

这两个对象通过原型链关联在一起,原因如下:

  • student对象有一个原型属性,该属性指向person对象。
  • person对象有一个原型属性,该属性指向Object.prototype对象。
  • Object.prototype对象是一个特殊的对象,它是所有JavaScript对象的原型。

二、主线一:原型继承

原型链的主要目的之一是实现原型继承。原型继承是一种在对象之间共享属性和方法的机制。

当一个对象访问一个不存在的属性或方法时,JavaScript会自动沿着原型链向上查找,直到找到该属性或方法为止。

例如,如果我们尝试访问student对象的major属性,JavaScript会执行以下步骤:

  1. student对象中查找major属性。
  2. 找不到major属性,则沿着原型链向上查找,直到找到person对象。
  3. person对象中找不到major属性,则沿着原型链向上查找,直到找到Object.prototype对象。
  4. Object.prototype对象中找不到major属性,因此返回undefined

主线二:双机制理解原型链

原型链的运作机制可以从两种不同的视角来理解:

  • 从对象的角度来看: 每个对象都包含一个原型属性,用于关联另一个对象,关联后就能够使用那个对象的属性和方法。
  • 从类的角度来看: 每个类都包含一个原型对象,该对象包含了该类所有实例的共享属性和方法。当创建一个新实例时,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(`I am studying ${this.major}.`);
  }
}

const john = new Person('John Doe', 30);
const jane = new Student('Jane Smith', 20, 'Computer Science');

john.greet(); // Hello, my name is John Doe and I am 30 years old.
jane.greet(); // Hello, my name is Jane Smith and I am 20 years old.
jane.study(); // I am studying Computer Science.

在这个示例中,Person类是一个父类,它包含了所有人的共有属性和方法。Student类是一个子类,它继承了Person类的所有属性和方法,并添加了新的属性和方法。

当我们创建johnjane这两个对象时,JavaScript会自动将它们的原型属性指向它们的类原型对象。因此,johnjane可以访问所有Person类和Student类的属性和方法。

四、结语

原型链是JavaScript中一种重要的机制,它可以实现原型继承,共享属性和方法。理解原型链对于深入理解JavaScript的运作机制非常重要。