跳到主要内容

原型/构造函数/实例:三者关系是什么?

面试速答(30 秒版 TL;DR)

  • 构造函数(constructor):一个函数(或 class),用 new 来创建实例。
  • 原型对象(prototype object)Ctor.prototype 指向的那个对象,放“实例共享的方法/属性”。
  • 实例(instance)new Ctor() 产生的对象,它的 [[Prototype]] 会指向 Ctor.prototype,从而形成原型链。
  • 口诀:Ctor.prototype 给实例用;实例的 [[Prototype]] 指回它;prototype.constructor 再指回 Ctor

心智模型:两条链,别混

  1. 实例的原型链obj -> obj[[Prototype]] -> ... -> null
  2. 函数对象自己的原型链Ctor -> Ctor[[Prototype]] -> Function.prototype -> Object.prototype -> null

很多人混淆的点是:prototype函数对象上的属性;[[Prototype]]任意对象都有的内部槽。


图示:把 3 个对象和几条指针画出来


代码:用标准 API 验证关系(避免依赖 __proto__

function Foo() {}

const foo = new Foo();

console.log(Object.getPrototypeOf(foo) === Foo.prototype); // true
console.log(Foo.prototype.constructor === Foo); // true
console.log(Object.getPrototypeOf(Foo) === Function.prototype); // true
console.log(Object.getPrototypeOf(Foo.prototype) === Object.prototype); // true
console.log(Object.getPrototypeOf(Object.prototype) === null); // true

你在面试里可以用一句话解释 new

  • new Foo() 会创建对象 o,把 o[[Prototype]] 设为 Foo.prototype,再用 Foothis=o 执行,最后返回 o(除非构造函数显式返回一个对象)。

常见追问

Q1:prototype[[Prototype]] 有什么区别?

  • prototype:函数对象的属性,决定“用它 new 出来的实例”原型指向哪里。
  • [[Prototype]]:对象的内部槽,决定“属性查找往上委托”的路径。

Q2:为什么 Foo.prototype.constructor 能指回 Foo

因为默认情况下 JS 会在创建函数时初始化 Foo.prototype,并在其上放一个 constructor 指回函数本身(但你手动替换 Foo.prototype 时可能破坏它,见下一篇)。


易错点/坑

  • __proto__ 是历史遗留访问器,不推荐作为面试或生产代码的“规范写法”,优先用 Object.getPrototypeOf / Object.setPrototypeOf
  • 只有“可构造的函数”才有 prototype(例如箭头函数没有 prototype,不能 new)。

速记要点(可背诵)

  • prototype 在构造函数上,[[Prototype]] 在对象上。
  • 实例通过 [[Prototype]] 连接到 Ctor.prototype,方法共享靠原型链委托。