JavaScript 的原型链(Prototype Chain)是实现继承的核心机制,理解它需要从「对象」和「原型」的关系入手。
- 原型(Prototype)是什么?
每个 JavaScript 对象(除 null 外)都有一个隐藏的 [[Prototype]] 属性(可通过 Object.getPrototypeOf() 访问),这个属性指向另一个对象,即「原型对象」。
原型对象本身也是对象,它也有自己的原型,由此形成一条链式结构 —— 这就是「原型链」。
const obj = {};
const proto = Object.getPrototypeOf(obj);
// proto 是 obj 的原型,即 Object.prototype
- 原型链的作用:属性查找
当访问一个对象的属性时,JS 引擎会先在对象自身查找:
若找到,直接返回;
若没找到,会沿着 [[Prototype]] 向上查找原型对象;
以此类推,直到找到属性或到达原型链的终点(null)。
// 1. 定义一个原型对象
const animalProto = {
eat: function() {
console.log('吃食物');
}
};
// 2. 创建一个对象,指定其原型为 animalProto
const cat = Object.create(animalProto);
cat.name = '小花';
// 3. 访问属性
console.log(cat.name); // 自身有 name → '小花'
cat.eat(); // 自身没有 eat,查原型 → '吃食物'
// 4. 继续向上查找(animalProto 的原型是 Object.prototype)
console.log(cat.toString());
// 查找到 Object.prototype 上的 toString → "[object Object]"
// 5. 原型链终点(Object.prototype 的原型是 null)
console.log(Object.getPrototypeOf(Object.prototype)); // null
- 构造函数与原型的关系
构造函数(如 Object、Array 或自定义函数)有一个 prototype 属性,指向其创建的实例的原型对象。
// 自定义构造函数
function Person(name) {
this.name = name;
}
// 构造函数的 prototype 是实例的原型
Person.prototype.sayHi = function() {
console.log(`Hi, ${this.name}`);
};
// 创建实例
const person = new Person('张三');
// 关系:实例 → 构造函数.prototype → ...
console.log(Object.getPrototypeOf(person) === Person.prototype); // true
- 原型链的本质:继承
原型链的核心作用是实现「继承」—— 子对象可以共享父原型对象的属性和方法,而无需重复定义。
例如,所有数组都继承自 Array.prototype,因此都能使用 push()、map() 等方法:
const arr = [1, 2, 3];
arr.push(4); // 继承自 Array.prototype.push
arr.toString(); // 继续向上,继承自 Object.prototype.toString
- 原型链的经典结构
一个典型的原型链结构如下(以数组为例):
arr(实例) → Array.prototype → Object.prototype → null
最底层是实例对象(如 arr)
中间是各级原型(Array.prototype、Object.prototype)
顶端是 null(原型链的终点)