[3-2] 原型与面向对象 · 对象的缔造者 (Object Creation & The `new` Operator)

3 阅读2分钟

所属板块:3. 原型与面向对象(OOP)

记录日期:2026-03-xx
更新:遇到 new 操作符或手写题时补充

1. 对象创建模式的演进史(从笨到精)

JS 没有真正的“类”,对象是逐步进化出来的:

  1. 字面量 / Object() 构造函数

    const obj = { name: "张三" };   // 最简单
    

    缺点:无法批量生产同类对象。

  2. 工厂模式(Factory Pattern)

    function createPerson(name) {
      return { name, say() { console.log(this.name); } };
    }
    

    缺点:无法识别对象类型(instanceof 失效)。

  3. 构造函数模式(Constructor Pattern)

    function Person(name) {
      this.name = name;
      this.say = function() { console.log(this.name); };
    }
    

    缺点:每个实例的方法都在内存里重复一份,浪费内存。

  4. 原型模式(Prototype Pattern)
    把共享方法放到 Person.prototype 上。
    缺点:引用类型属性会被所有实例共享(容易被意外修改)。

  5. 组合模式(构造函数 + 原型) —— JS 中最推荐的自定义对象方式

    • 私有/实例属性放构造函数
    • 共享方法放原型
      这就是 [3-1] 原型机制的实际应用。

2. new 操作符的底层四步曲(面试必考)

当执行 new Person(...) 时,JS 引擎实际做了以下四件事:

  1. 创建一个全新的空对象
    let obj = {};

  2. 将新对象的 [[Prototype]](即 __proto__)链接到构造函数的 prototype
    obj.__proto__ = Person.prototype;

  3. 将构造函数的 this 绑定到新对象,并执行构造函数代码
    Person.call(obj, ...args);

  4. 判断构造函数返回值

    • 如果返回的是引用类型(对象/数组/函数等),则直接返回该引用
    • 否则返回新创建的 obj

这就是为什么 new 能把普通函数变成构造函数。

3. 手写 myNew(面试高频手写题)

function myNew(Constructor, ...args) {
  // 1. 创建空对象
  const obj = Object.create(Constructor.prototype);   // 一步完成第1、2步

  // 2. 执行构造函数,绑定 this
  const result = Constructor.apply(obj, args);

  // 3. 返回逻辑
  return result instanceof Object ? result : obj;
}

// 使用示例
function Person(name) {
  this.name = name;
}
Person.prototype.say = function() { console.log(this.name); };

const p = myNew(Person, "李四");
p.say();                    // "李四"
console.log(p instanceof Person);   // true

Object.create() 是最优雅的实现方式,面试时可直接用)

4. 小结 & 复习时的“缔造者视角”

  • 对象创建的核心是:实例属性放构造函数,共享方法放原型
  • new 的四步曲是理解后面继承和 class 语法的关键
  • [3-1] 的原型三角关系 + 本文的 new 操作符,共同构成了 JS 对象的完整创建机制

下一篇文章会进入 [3-3]:继承的血泪史(六种继承方式演进 + 寄生组合式继承手写)——这是整个板块最重的手写题部分。

返回总目录:戳这里