qiuhongbingo / blog

Writing something in Issues.
https://github.com/qiuhongbingo/blog/issues
3 stars 0 forks source link

实现 new 没有那么容易 #14

Open qiuhongbingo opened 4 years ago

qiuhongbingo commented 4 years ago
/**
 * new 关键字到底做了什么事情。
 * step 1:首先创建一个空对象,这个对象将会作为执行 new 构造函数() 之后,返回的对象实例
 * step 2:将上面创建的空对象的原型(__proto__),指向构造函数的 prototype 属性
 * step 3:将这个空对象赋值给构造函数内部的 this,并执行构造函数逻辑
 * step 4:根据构造函数执行逻辑,返回第一步创建的对象或者构造函数的显式返回值
 */

function newFunc(...args) {
  // 取出 args 数组第一个参数,即目标构造函数
  const constructor = args.shift() // Person

  // 创建一个空对象,且这个空对象继承构造函数的 prototype 属性
  // 即实现 obj.__proto__ === constructor.prototype
  const obj = Object.create(constructor.prototype)

  // 执行构造函数,得到构造函数返回结果
  // 注意这里我们使用 apply,将构造函数内的 this 指向为 obj
  const result = constructor.apply(obj, args) // Person()

  // 如果函数执行后,返回结果是对象类型,就直接返回,否则返回 obj 对象
  // 针对 call 2 构造函数如果有显式返回值,且返回值为对象类型,那么构造函数返回结果不再是目标实例
  return typeof result === 'object' && result !== null ? result : obj
}

// call 1
// function Person(name) {
//   this.name = name
// }

// const person = new newFunc(Person, 'bingo')

// console.log(person) // { name: 'bingo' }

// call 2
function Person(name) {
  this.name = name
  return { 1: 1 }
}

const person = new newFunc(Person, 'bingo')

console.log(person) // { 1: 1 }