0%

手写 new:彻底搞懂 JavaScript new 运算符的实现原理

在 JavaScript 中,new 运算符是面试和日常开发中都会频繁遇到的知识点。
很多人会用 new,但并不真正理解它背后到底发生了什么

本文将通过 手写 new 的实现,一步步拆解 new 运算符的底层逻辑,帮助你真正掌握 JavaScript 对象创建机制。

一、new 运算符到底做了什么?

当我们执行下面这行代码时:

1
const person = new Person('Alice', 25);

JavaScript 实际上在背后做了 4 件事情:

  1. 创建一个新的空对象
  2. 将新对象的原型指向构造函数的 prototype
  3. 执行构造函数,并将 this 绑定到新对象
  4. 如果构造函数返回的是对象,则返回该对象;否则返回新对象

理解这 4 步,是理解 new 的关键。

二、为什么要手写 new?

手写 new 的好处有三点:

  • 加深对 原型链this 指向 的理解
  • 几乎是 前端面试高频题
  • 有助于理解框架中对象创建的底层逻辑

接下来我们直接上代码。

三、手写 new 的完整实现

1
2
3
4
5
6
7
8
9
10
11
function myNew(constructor, ...args) {
// 1. 创建一个新对象,并将其原型指向构造函数的 prototype
const obj = Object.create(constructor.prototype);

// 2. 执行构造函数,将 this 绑定到新对象
const result = constructor.apply(obj, args);

// 3. 如果构造函数返回的是对象,则返回该对象
// 否则返回我们创建的新对象
return result instanceof Object ? result : obj;
}

这段代码完整复现了 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
2
this.name = name;
this.age = age;

实际上是在给 obj 添加属性。

3. 为什么要判断返回值?

1
return result instanceof Object ? result : obj;

这是很多人容易忽略的一点。

来看一个例子:

1
2
3
4
5
6
7
function Test() {
this.a = 1;
return { b: 2 };
}

const t = new Test();
console.log(t); // { b: 2 }

如果构造函数 显式返回一个对象new 会返回这个对象,而不是 this

所以我们在 myNew 中必须处理这种情况。

五、测试手写的 myNew

1
2
3
4
5
6
7
8
9
10
function Person(name, age) {
this.name = name;
this.age = age;
}

const p1 = myNew(Person, 'Alice', 25);

console.log(p1.name); // Alice
console.log(p1.age); // 25
console.log(p1 instanceof Person); // true

结果完全符合原生 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 都有帮助
-------------本文结束感谢您的阅读-------------