写React三年,遇到手写
new
,就像让厨师现场炼铁造锅。
在 JavaScript 中,new
关键字扮演着非常重要的角色,它是构造函数与实例对象之间的桥梁,常用于创建对象的实例。
那么new
到底做了什么?如果不使用new
,会发生什么变化?我们又该如何手动实现它的机制?本文将带你一步步深入了解。
一、new
到底做了哪些事?
当你使用 new
调用一个构造函数时,实际上发生了以下几步操作:
- 创建一个空对象 ,并将该对象的
__proto__
指向构造函数的prototype
。 - 将构造函数内部的
this
绑定到这个新创建的对象上。 - 执行构造函数的代码(即给这个对象添加属性、方法等)。
- 判断构造函数的返回值 :
- 如果构造函数显式返回的是一个对象类型 (如
Object
、Array
、Function
等),那么这个返回的对象会成为new
表达式的结果。 - 如果没有返回值,或者返回的是一个非对象类型(如字符串、数字、布尔值),则返回第一步中创建的新对象。
- 如果构造函数显式返回的是一个对象类型 (如
示例:
js
function Person() {
this.name = 'Jack';
}
const p = new Person();
console.log(p.name); // Jack
二、如果不使用 new
会怎样?
我们来改写上面的代码,去掉 new
:
js
function Person() {
this.name = 'Jack';
}
const p = Person(); // 没有用 new
console.log(p); // undefined
console.log(name); // Jack(污染了全局作用域)
解释:
this
被绑定到全局对象(非严格模式下),name
成为了全局变量。- 函数没有返回值,
p
是undefined
。
三、构造函数中有返回值的特殊情况
返回一个对象:
js
function Person() {
this.name = 'Jack';
return { age: 18 };
}
const p = new Person();
console.log(p); // { age: 18 }
console.log(p.name); // undefined
如果构造函数返回一个对象类型,new
会直接返回该对象。
返回基本类型:
js
function Person() {
this.name = 'Jack';
return 'Tom';
}
const p = new Person();
console.log(p); // { name: 'Jack' }
console.log(p.name); // Jack
如果返回值不是对象(如字符串),则忽略,仍然返回新创建的实例。
四、手写 new
的实现
下面是手写版 new
函数的实现:
js
function create(fn, ...args) {
if (typeof fn !== 'function') {
throw new Error('fn must be a function');
}
// 1. 创建一个新对象,并链接原型
const obj = Object.create(fn.prototype);
// 2. 执行构造函数,将 this 指向新对象
const result = fn.apply(obj, args);
// 3. 判断返回值
return result instanceof Object ? result : obj;
}
使用示例:
js
function Person(name) {
this.name = name;
return { age: 18 };
}
const p1 = new Person('Lucas');
const p2 = create(Person, 'Lucas');
console.log(p1); // { age: 18 }
console.log(p2); // { age: 18 }
五、总结
- ✅
new
关键字执行时会完成四步:创建对象 、绑定原型 、绑定 this 并执行函数 、根据返回值决定返回结果。 - ✅ 如果构造函数显式返回对象,则该对象会覆盖原本实例。
- ✅ 如果不使用
new
,构造函数中的this
会指向全局对象(非严格模式)。 - ✅ 我们可以使用
Object.create
+apply
模拟new
的行为。
📌 面试小技巧:
面试官问你 "
new
关键字干了什么?" 你可以说:"
new
创建了一个对象,并把构造函数的原型赋值给这个对象的__proto__
,然后用构造函数执行并绑定this
,最后根据返回值来判断是返回这个新对象还是构造函数中返回的对象。"
如果觉得有帮助,欢迎点赞、收藏、评论支持一下 🙌