object.create 用空构造函数本质是绕过原构造函数副作用,仅复用 prototype 链传递能力;通过 f.prototype = proto 后 new f() 创建原型指向 proto 的干净对象,避免初始化行为,符合只设原型、不触发逻辑的语义。

手写 Object.create 时用空构造函数(如 function F() {})做过渡,本质是**绕过调用原构造函数的副作用,只借用其 prototype 链传递能力**。JavaScript 的原型链继承依赖于对象的 [[Prototype]](即 __proto__),而 new F() 创建的实例,其 [[Prototype]] 指向 F.prototype —— 所以只要把目标原型赋给 F.prototype,再用 new 实例化,就能得到一个“干净”的、原型指向指定对象的新对象。
为什么不能直接 new 一个带逻辑的构造函数?
如果直接用已有构造函数(比如 new Person()),会执行其内部代码(初始化属性、发请求、改全局状态等),这违背了 Object.create(proto) 的语义:**只设置原型,不触发初始化行为**。空函数没有副作用,安全可控。
空构造函数如何桥接原型链?
关键三步:
- 定义一个空函数
F,它本身不干任何事 - 把传入的目标原型
proto赋给F.prototype—— 这样所有new F()出来的实例,[[Prototype]]都会指向proto - 用
new F()创建新对象,它就自然继承了proto上的所有属性和方法
手写实现示例与细节说明
标准写法如下:
function create(proto) {
if (proto !== null && typeof proto !== 'object') {
throw new TypeError('Object prototype may only be an Object or null');
}
function F() {}
F.prototype = proto;
return new F();
}
注意点:
-
F.prototype = proto必须在new F()之前赋值,否则实例的原型还是F.prototype的初始值(Object.prototype) - 不需要
F.prototype.constructor = F,因为Object.create返回的对象本就不该有合理的constructor指向 —— 它是“无构造器凭空继承”的产物 - 若传入
null,需特殊处理(返回一个无原型的对象),可用Object.setPrototypeOf({}, null)或更兼容的create(null)+ 特判
对比直接设置 __proto__ 的问题
有人想用 obj.__proto__ = proto 替代,但:
-
__proto__是非标准(尽管被广泛支持)、已废弃的访问器,性能差且不可靠 - 某些环境(如严格模式下的某些引擎)可能禁止修改
__proto__ - 用空函数 +
new是符合 ES5 规范的、可预测的、一次性的原型委托方式
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











