手写支持原型链绑定的动态对象工厂函数需三步:先用Object.create(Ctor.prototype)创建空对象并设置原型,再用Ctor.apply(instance, args)执行初始化,最后按new规则处理返回值(若构造函数返回非null对象则返回它,否则返回instance)。

<p>要手写一个支持原型链绑定的动态对象工厂函数,核心是让创建的对象能正确继承指定构造函数的原型,并且能接收动态参数初始化实例属性。</p>
<H3>基础结构:用函数返回新实例</H3>
<p>工厂函数本质是封装了 <strong>new</strong> 操作,但不直接暴露构造函数。关键点在于:用 <strong>Object.create</strong> 手动设置原型,再用 <strong>apply</strong> 绑定构造逻辑。</p>
<ul>
<li>不能直接 <strong>return new Ctor(...args)</strong> —— 这样无法解耦构造函数与工厂,也失去“动态绑定原型”的控制权</li>
<li>必须显式创建空对象,并将其 <strong>__proto__</strong>(或内部 [[Prototype]])指向目标构造函数的 <strong>prototype</strong></li>
<li>再把初始化逻辑(通常是构造函数体)在该对象上执行</li>
</ul>
<H3>支持原型链:用 Object.create 设置原型</H3>
<p>这是实现继承的关键一步。比如想让工厂产出的对象拥有 Array 的方法,就得让它原型链连到 <strong>Array.prototype</strong>;想继承自自定义类,就链到那个类的 <strong>prototype</strong>。</p>
<ul>
<li><strong>Object.create(Ctor.prototype)</strong> 创建一个空对象,其内部原型已设为 <strong>Ctor.prototype</strong></li>
<li>这样后续调用 <strong>obj.push()</strong>(若 Ctor 是 Array)或 <strong>obj.customMethod()</strong> 都能沿原型链找到</li>
<li>注意:不能用 <strong>{}</strong> 或 <strong>new Object()</strong>,它们的原型默认是 <strong>Object.prototype</strong>,无法直接替换</li>
</ul>
<H3>动态初始化:用 call/apply 执行构造逻辑</H3>
<p>光有原型不够,还得把传入的参数用于初始化实例属性(如 <strong>this.name = name</strong>)。这需要在新对象上调用构造函数,并绑定 this。</p>
<ul>
<li>用 <strong>Ctor.apply(instance, args)</strong> 把构造函数逻辑“注入”到新对象上</li>
<li>如果构造函数本身返回对象(非 null 对象),则优先返回它;否则返回 instance —— 这和原生 <strong>new</strong> 行为一致</li>
<li>所以完整流程是:<font color="red">创建实例 → 绑定原型 → 执行初始化 → 处理返回值</font></li>
</ul>
<H3>最终实现代码(带注释)</H3>
<p>这是一个通用、健壮的工厂函数:</p>
<pre><code>function createInstance(Ctor, ...args) {
// 1. 创建空对象,原型指向 Ctor.prototype
const instance = Object.create(Ctor.prototype);
// 2. 执行构造函数,在 instance 上初始化属性
const result = Ctor.apply(instance, args);
// 3. 兼容构造函数返回对象的情况(如 return {x:1})
// 原生 new 也会优先取这个返回值
return (result !== null && typeof result === 'object') ? result : instance;
}
// 使用示例:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function() {
return `Hi, I'm ${this.name}`;
};
const p = createInstance(Person, 'Alice', 30);
console.log(p.sayHello()); // "Hi, I'm Alice"
console.log(p instanceof Person); // true
</code></pre>