出处:掘金
原作者:金泽宸
为什么要手写 new
?
面试中经常问:
new
关键字到底做了什么?- 你能用代码模拟
new
的行为吗?
理解 new
的本质,才能真正理解:
- 构造函数的运行机制
this
指向规则- 原型继承关系
new
做了哪些事?
const obj = new Foo(arg1, arg2);
等价于:
- 创建一个空对象
obj
- 将该对象的
__proto__
指向Foo.prototype
- 将
this
绑定为该对象并执行Foo
函数 - 如果构造函数
return
一个对象类型,则new
表达式的结果就是这个对象,否则返回步骤 1 创建的对象
手写 new
function myNew(Constructor, ...args) {
// 1. 创建一个空对象,设置原型指向构造函数的 prototype
const obj = Object.create(Constructor.prototype);
// 2. 执行构造函数,将 this 指向这个新对象
const result = Constructor.apply(obj, args);
// 3. 返回结果:如果构造函数返回的是对象,则返回该对象,否则返回 obj
return (typeof result === 'object' && result !== null) || typeof result === 'function'
? result
: obj;
}
用例验证
function Person(name, age) {
this.name = name;
this.age = age;
}
const p = myNew(Person, '小明', 18);
console.log(p.name); // 小明
console.log(p.__proto__ === Person.prototype); // true
// 特殊情况验证
function Animal() {
return { type: 'cat' };
}
const a = myNew(Animal);
console.log(a.type); // cat
常见易错点
错误点 | 正确处理 |
---|---|
忘记绑定原型 | Object.create(Constructor.prototype) |
忘记处理返回对象的情况 | 判断 return 是否为对象/函数 |
Object.setPrototypeOf | 不建议直接用,面试常让用 Object.create |
扩展问题
- 如果
Constructor.prototype = null
怎么办? - 如果构造函数是箭头函数呢?(箭头函数没有
prototype
,不可new
)