在 JavaScript 中,new 运算符是面试和日常开发中都会频繁遇到的知识点。
很多人会用 new,但并不真正理解它背后到底发生了什么。
本文将通过 手写 new 的实现,一步步拆解 new 运算符的底层逻辑,帮助你真正掌握 JavaScript 对象创建机制。
一、new 运算符到底做了什么?
当我们执行下面这行代码时:
1 | const person = new Person('Alice', 25); |
JavaScript 实际上在背后做了 4 件事情:
- 创建一个新的空对象
- 将新对象的原型指向构造函数的
prototype - 执行构造函数,并将
this绑定到新对象 - 如果构造函数返回的是对象,则返回该对象;否则返回新对象
理解这 4 步,是理解 new 的关键。
二、为什么要手写 new?
手写 new 的好处有三点:
- 加深对 原型链 和 this 指向 的理解
- 几乎是 前端面试高频题
- 有助于理解框架中对象创建的底层逻辑
接下来我们直接上代码。
三、手写 new 的完整实现
1 | function myNew(constructor, ...args) { |
这段代码完整复现了 new 运算符的核心行为。
四、逐行拆解实现逻辑
1. Object.create 的作用
1 | const obj = Object.create(constructor.prototype); |
这一步等价于:
1 | obj.__proto__ === constructor.prototype |
也就是说:
- 新对象可以访问构造函数原型上的方法
- 原型链关系得以建立
2. constructor.apply(obj, args)
1 | const result = constructor.apply(obj, args); |
这一步做了两件事:
- 执行构造函数
- 将构造函数内部的
this指向新创建的对象
也就是:
1 | this.name = name; |
实际上是在给 obj 添加属性。
3. 为什么要判断返回值?
1 | return result instanceof Object ? result : obj; |
这是很多人容易忽略的一点。
来看一个例子:
1 | function Test() { |
如果构造函数 显式返回一个对象,new 会返回这个对象,而不是 this。
所以我们在 myNew 中必须处理这种情况。
五、测试手写的 myNew
1 | function Person(name, age) { |
结果完全符合原生 new 的行为。
六、myNew 与 new 的对比总结
| 行为 | new | myNew |
|---|---|---|
| 创建新对象 | ✅ | ✅ |
| 绑定原型 | ✅ | ✅ |
| 绑定 this | ✅ | ✅ |
| 处理返回对象 | ✅ | ✅ |
可以说,myNew 已经实现了 90% 的 new 运算符行为,足以应付面试和深入理解 JS 原理。
七、常见面试追问
Q1:为什么不能直接 const obj = {}?
因为 {} 创建的对象原型是 Object.prototype,
而 new 创建的对象原型必须是 构造函数的 prototype。
Q2:constructor.apply 能不能换成 call?
可以,只是参数形式不同:
1 | constructor.call(obj, ...args); |
Q3:instanceof 是如何工作的?
1 | p1 instanceof Person |
本质是沿着原型链查找:
1 | Person.prototype 是否在 p1 的原型链上 |
八、总结
new并不是魔法,而是一套明确的执行流程- 手写
new是理解 原型链 + this + 构造函数 的最佳方式 - 掌握这个知识点,对学习 Vue、React、Node.js 都有帮助