New操作原理与实现

161 阅读2分钟

工作原理

这里写的new操作原理并不是自己实验出来,而是在网上看了多个帖子得知的。

例子1:
function Student() {

}
const student1 = new Student()
const student2 = new Student()
console.log(student1)
const obj = new Object()
console.log(obj)
console.log(student1 === student2) //false

Image1.png

从这可以看到

new 出来的新对象,constructor会被指向构造

小结1:new操作符做了:创建了一个全新的对象(student1 != student2), 并且这个全新对象的_proto_会指向构建函数的prototype
例子2:
function Student(name) {
  this.name = name
  console.log(this)
}
function person(name) {
  this.name = name
}
const student1 = new Student('xjj')
console.log(Student('zlp'))

可以看到

Image2.png

我们通过对比new和直接函数调用来对比this的指向问题。

可以看到通过直接的函数调用,this指向会遵循默认绑定(非严格模式下),绑定到全局对象window上。

而通过new操作构造调用,则会自动绑定到new期间创建的对象上,在这里是student1

小结2: new操作会绑定this到小结1那种新对象上

例子3:

function Student(name) {
  this.name = name
  return {
    a'new'  //不一定是object,可以是Functoin, Array, Date, RegExg, Error引用类型
  }
}
function Person(name) {
  this.name = name
  return 'new'  //不一定是字符串,是包括字符串的七种基本类型
}
const student1 = new Student('zlp')
const person1 = new Person('zlp')
console.log(student1) //{a: 'new'}
console.log(person1)  // person{name: 'zlp'}

从这里我们可以看到,如果构造函数里面有返回的变量,如果变量是基本类型,则正常返回但如果是object类型都会被直接返回。

小结4:如果函数没有返回对象类型Object(包含Functoin, Array, Date, RegExg, Error),那么new表达式中的函数调用会自动返回this。

new操作总结:

  1. 创建全新的对象
  2. 该对象的_proto_会指向构造函数的原型prototype
  3. 将步骤1中创建的新对象作为this上下文
  4. 判断函数有没有返回对象类型的数据,(包含Functoin, Array, Date, RegExg, Error),那么new表达式中的函数调用会自动返回这个新的对象的this。

Image3.png

摘自MDN对new的解释

new模拟实现

按照上面的步骤,我们可以自己实现一个new操作:

function Student(name) {
    this.name = name
  }
  const student1 = new Student('xjj')
  function myNew(ctr, ...args) {
    //1. 创建全新的对象
    //2. 该对象的_proto_会指向构造函数的原型prototype
    //3. 将步骤1中创建的新对象作为this上下文
    //4. 判断函数有没有返回对象类型的数据,(包含Functoin, Array, Date, RegExg, Error),那么new表达式中的函数调用会自动返回这个新的对象的this。
    
    //第一二步,Object.create(Parent.prototype)创建了一个空的对象,并且这个对象的__proto__属性是指向Parent.prototype的 。
    const newObj = Object.create(ctr.prototype) //es6写法 性能更好
    Object.setPrototypeOf(obj, Con.prototype) //es5以前的写法
    //第三步,将这个对象作为this上下文,tips传参用args
    const result = ctr.apply(newObj, args)
    //第四步,判断函数有没有返回对象类型的数据
    return result instanceof Object ? result : newObj
  }
  console.log(myNew(Student'xjj'))
  console.log(student1)

结果:

Image4.png