原型链 - ChatGPT

在 JavaScript 中,**原型链(Prototype Chain)**是实现对象继承的一种机制,它允许一个对象继承另一个对象的属性和方法。了解原型链的概念对理解 JavaScript 的面向对象编程至关重要。

原型(Prototype)

JavaScript 是基于 原型(prototype)而非类(class)的语言。每个 JavaScript 对象都有一个特殊的属性 __proto__,指向它的 原型对象(prototype)。原型对象本身也是对象,因此也有自己的 __proto__,形成一个链式结构,即原型链

构造函数与原型

在 JavaScript 中,函数都可以作为构造函数来创建对象。当使用 new 关键字创建对象时:

  1. 会创建一个新对象。

  2. 该对象的 __proto__ 指向构造函数的 prototype 属性。

  3. 继承 prototype 上的属性和方法。

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

const p1 = new Person("Alice");
p1.sayHello(); // Hello, my name is Alice

console.log(p1.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype); // true

原型链

当访问一个对象的属性或方法时,JavaScript 引擎会按照以下步骤查找:

  1. 先检查该对象自身是否有该属性/方法;

  2. 如果没有,则查找该对象的 __proto__(即构造函数的 prototype);

  3. 如果仍然找不到,就沿着 __proto__ 继续向上查找,直到 Object.prototype

  4. 如果 Object.prototype 仍然没有该属性/方法,则返回 undefined

console.log(p1.toString()); 
// 没有在 p1 对象中找到 -> 查找 Person.prototype -> 仍然没有 -> 继续查找 Object.prototype

原型链的终点

所有对象最终都会继承自 Object.prototype,而 Object.prototype.__proto__null,表示原型链的终点:

console.log(Object.prototype.__proto__); // null

原型链继承

原型链可以实现继承,比如:

function Animal(name) {
  this.name = name;
}
Animal.prototype.eat = function () {
  console.log(this.name + " is eating.");
};

function Dog(name, breed) {
  Animal.call(this, name); // 继承 Animal 的属性
  this.breed = breed;
}

// 继承 Animal 的方法
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog; // 修正构造函数指向

Dog.prototype.bark = function () {
  console.log(this.name + " is barking.");
};

const dog = new Dog("Buddy", "Golden Retriever");
dog.eat(); // Buddy is eating.
dog.bark(); // Buddy is barking.

这里 Dog.prototype = Object.create(Animal.prototype)Dog 继承 Animal 的方法,同时保证 Dog.prototype.__proto__ === Animal.prototype,形成继承关系。

ES6 Class 继承原型链

ES6 引入 class 语法,本质上仍然是基于原型链:

class Animal {
  constructor(name) {
    this.name = name;
  }
  eat() {
    console.log(this.name + " is eating.");
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name); // 相当于 Animal.call(this, name)
    this.breed = breed;
  }
  bark() {
    console.log(this.name + " is barking.");
  }
}

const dog = new Dog("Buddy", "Labrador");
dog.eat(); // Buddy is eating.
dog.bark(); // Buddy is barking.

extends 关键字简化了原型链继承,但底层仍然是 Object.create() 机制。

总结

  1. JavaScript 采用原型(prototype)机制实现继承。

  2. 每个对象都有 __proto__ 指向其构造函数的 prototype,形成原型链。

  3. 原型链的终点是 Object.prototype,其 __proto__null

  4. 通过 Object.create()class extends 语法可实现继承。

原型链是 JavaScript 继承和属性查找的核心机制,理解它有助于深入掌握 JavaScript 的面向对象编程。

Last updated