通俗易懂理解 JavaScript 原型链

93 阅读3分钟

JavaScript 是一门基于原型的语言,它的核心概念之一就是原型链。理解原型链是掌握 JavaScript 面向对象编程的关键。本文将通过通俗易懂的方式,带你彻底理解原型链。

1. 什么是原型链?

简单来说,原型链是 JavaScript 中对象之间的一种继承机制。每个对象都有一个隐藏的 __proto__ 属性,指向它的“原型对象”。当你访问一个对象的属性或方法时,如果对象本身没有这个属性,JavaScript 就会沿着 __proto__ 向上查找,直到找到该属性或到达原型链的顶端(null)。

2. 从一个例子开始

我们先来看一个简单的例子:

const animal = {
  name: '动物',
  eat() {
    console.log(this.name + '正在吃东西');
  }
};

const dog = {
  name: '小狗'
};

// 将 dog 的原型指向 animal
dog.__proto__ = animal;

dog.eat(); // 输出:小狗正在吃东西

发生了什么?

  1. dog 对象本身没有 eat 方法。

  2. JavaScript 发现 dog.__proto__ 指向 animal,于是去 animal 中查找 eat 方法。

  3. 找到了 eat 方法,并调用它。

这就是原型链的基本工作原理!

3. 原型链的结构

为了更好地理解原型链,我们需要了解几个关键概念:

1. __proto__ 属性

  • 每个对象都有一个 __proto__ 属性,指向它的原型对象。

  • 例如:dog.__proto__ === animal

2. prototype 属性

  • 每个函数都有一个 prototype 属性(只有函数有)。

  • 当你使用 new 关键字创建一个对象时,这个对象的 __proto__ 会指向该函数的 prototype

3. constructor 属性

  • 每个原型对象都有一个 constructor 属性,指向它的构造函数。

  • 例如:animal.constructor === Object

4. 原型链的尽头

原型链的顶端是 null。当你访问一个属性时,如果沿着原型链一直找不到,最终会到达 null,这时 JavaScript 会返回 undefined

console.log(dog.toString); // 输出:[Function: toString]
console.log(dog.someNonExistentProperty); // 输出:undefined

5. 构造函数与原型链

当我们使用构造函数创建对象时,原型链的作用更加明显。

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

Animal.prototype.eat = function() {
  console.log(this.name + '正在吃东西');
};

const dog = new Animal('小狗');
dog.eat(); // 输出:小狗正在吃东西

发生了什么?

  1. new Animal('小狗') 创建了一个新对象 dog

  2. dog.__proto__ 指向 Animal.prototype

  3. Animal.prototype 上有 eat 方法,所以 dog 可以调用它。

6. 原型链的继承

JavaScript 通过原型链实现继承。例如:

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

Animal.prototype.eat = function() {
  console.log(this.name + '正在吃东西');
};

function Dog(name, breed) {
  Animal.call(this, name); // 调用父类构造函数
  this.breed = breed;
}

// 设置 Dog 的原型为 Animal 的实例
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function() {
  console.log(this.name + '在汪汪叫');
};

const myDog = new Dog('小黑', '哈士奇');
myDog.eat(); // 输出:小黑正在吃东西
myDog.bark(); // 输出:小黑在汪汪叫

关键点:

  1. Dog.prototype = Object.create(Animal.prototype):将 Dog 的原型指向 Animal 的原型。

  2. Dog.prototype.constructor = Dog:修复 constructor 的指向。

7. 总结

  • 原型链是 JavaScript 中对象之间继承属性的机制。

  • 每个对象都有一个 __proto__ 属性,指向它的原型对象。

  • 每个函数都有一个 prototype 属性,用于定义通过该函数创建的对象共享的属性和方法。

  • 原型链的顶端是 null

  • 通过原型链,JavaScript 实现了类似传统面向对象语言中的继承。

8. 小练习

  1. 创建一个 Person 构造函数,给它添加一个 greet 方法。

  2. 创建一个 Student 构造函数,继承 Person,并添加一个 study 方法。

  3. 创建一个 Student 实例,调用 greetstudy 方法。

通过动手实践,你会对原型链有更深的理解!