792 字
4 分钟
原型与原型链

什么是原型#

在 JavaScript 中,每个对象都有一个内部属性 __proto__,这个属性指向另一个对象,这个对象就是该对象的原型。通过原型,对象可以继承原型对象的属性和方法。类似于 lua 中的元表(metatable)。

当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。

准确地说,这些属性和方法定义在Object的构造器函数(constructor functions)的 prototype 属性上,而不是直接定义在对象本身上。

function doSomething() {}
console.log(doSomething.prototype.constructor === doSomething); // true
const obj = new doSomething();
console.log(obj.__proto__ === doSomething.prototype); // true

可以看到,原型对象有一个自有属性 constructor,这个属性指向该构造函数本身。

什么是原型链#

原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。 这种层层相连的原型对象就形成了所谓的“原型链”(prototype chain)。

在对象实例和它的构造器之间建立一个链接(它是 __proto__ 属性,是从构造函数的 prototype 属性派生的),之后通过上溯原型链,在构造器中找到这些属性和方法。

原型链的顶端是 Object.prototype,它的原型是 null。这意味着所有对象最终都继承自 Object.prototype

函数本身也是一种对象,所以函数也有自己的也有 __proto__ 属性,它指向 Function.prototype,而 Function.prototype 的原型又是 Object.prototype

function doSomething() {}
console.log(doSomething.__proto__ === Function.prototype); // true
console.log(Function.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__ === null); // true
doSomething
↓ (__proto__)
Function.prototype
↓ (__proto__)
Object.prototype
↓ (__proto__)
null

特别的: Function.__proto__Object.__proto__#

console.log(Object instanceof Function); // true
console.log(Function instanceof Object); // true

二者都返回 true 说明:

  1. Object 是由 Function 构造的(因为 Object 是函数)
  2. Function 也是由 Object 构造的(因为 Function 是对象)

所以 ObjectFunction 之间形成了一个循环引用。

分析:

  1. Function.__proto__ 指向 Function.prototype 因为 Function 是一个函数
  2. Object.__proto__ 指向 Function.prototype 因为 Object 是一个函数。
console.log(Function.__proto__ === Function.prototype); // true
console.log(Object.__proto__ === Function.prototype); // true

于是整个原型链如下:

console.log(Function.__proto__ === Function.prototype); // true
console.log(Object.__proto__ === Function.prototype); // true
console.log(Function.prototype.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__ === null); // true
Function ──────┐
↓ (__proto__)
Object ────→ Function.prototype
↓ (__proto__)
Object.prototype
↓ (__proto__)
null

实现 instanceof#

instanceof 运算符用于检测构造函数的 prototype 属性是否存在于某个实例对象的原型链上。

function instanceOf(instance, constructor) {
if (
(typeof instance !== "object" && typeof instance !== "function") ||
instance === null
) {
return false; // 基础类型直接返回 false
}
let proto = Object.getPrototypeOf(instance); // 获取实例的原型
const prototype = constructor.prototype; // 获取构造函数的原型
while (proto !== null) {
if (proto === prototype) {
return true;
}
proto = Object.getPrototypeOf(proto);
}
return false;
}
console.log(instanceOf([], Array)); // true
console.log(instanceOf([], Object)); // true
console.log(instanceOf({}, Array)); // false
console.log(instanceOf(function () {}, Function)); // true
console.log(instanceOf(function () {}, Object)); // true
console.log(instanceOf(null, Object)); // false

总结#

所有函数(包括 Object)都是 Function 的实例,因此它们的 __proto__ 都指向 Function.prototype。 所有对象(包括 Function)都是 Object 的实例,因此它们的 __proto__ 都指向 Object.prototypeFunction.prototype 的原型是 Object.prototype,而 Object.prototype 的原型是 null

原型与原型链
https://fuyuki.fun/posts/前端/原型与原型链/
作者
Fuyuki_Vila
发布于
2025-10-14
许可协议
CC BY-NC-SA 4.0
Music Off