手写实现 new 操作符

191 阅读1分钟

首先我们来回顾一下 new 操作符的作用。new 操作符用来调用构造函数,并返回一个对象,该对象可以访问构造函数内部的属性和方法,也可以访问构造函数的原型对象的属性和方法。 那么,调用 new Foo() 的时候,new 到底做了什么呢?

  1. 在内存中创建一个新的对象;
  2. 构造函数内部的 this 被赋值为这个新对象(继承实例属性);
  3. 将新对象的 proto 指针指向 Foo 的原型对象(继承原型属性);
  4. 执行构造函数内部的代码(给新对象添加属性);
  5. 如果构造函数返回非空对象,则返回该对象,否则,返回新创建的对象。
let myNew = function () {
  // 注意:箭头函数没有自己的 this,arguments,super 和 new.target
  // 所以这里不能使用箭头函数
  let obj = new Object()
  // 获取构造函数
  let arg = Array.prototype.shift.call(arguments)
  // 将 obj 对象的 __proto__ 指针指向构造函数的原型对象,参考原型继承
  obj.__proto__ = arg.prototype
  // 改变构造函数的作用域,使其指向新对象
  const res = arg.apply(obj, arguments) 
  // 如果构造函数返回对象,则返回该对象,否则,返回新创建的对象,即obj
  return typeof res === 'object' ? res : obj
}

// test
let Animals = function (name, age) {
  this.name = name
  this.age = age
  // return {
  //   name: 'hhh'
  // }
}
const res = myNew(Animals, 'Sugary', 12)
console.log(res.name) //  'Sugary'