出处:掘金

原作者:金泽宸


为什么要手写 new

面试中经常问:

  • new 关键字到底做了什么?
  • 你能用代码模拟 new 的行为吗?

理解 new 的本质,才能真正理解:

  • 构造函数的运行机制
  • this 指向规则
  • 原型继承关系

new 做了哪些事?

const obj = new Foo(arg1, arg2);

等价于:

  1. 创建一个空对象 obj
  2. 将该对象的 __proto__ 指向 Foo.prototype
  3. this 绑定为该对象并执行 Foo 函数
  4. 如果构造函数 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