new 操作符干了什么

首先说 new,new 是创建实例,常规如下:

function a(x){
    this.x = x
}
// 实例化
let b = new a(3)  // { x: 3}

b.__proto__ === a.prototype  // true
b.__proto__ === Object.prototype  // false

new 有另一种情况,函数有返回值且是对象,此时:

function a(x){
    this.x = x
    return { x: 2 }
}
// 实例化
let b = new a(3)  // { x: 2}

b.__proto__ === a.prototype  // false
b.__proto__ === Object.prototype  // true

很容易理解其实,正常函数实例化后,原型指向构造函数的 prototype

而有对象返回值的函数实例化后,其实就是指向了这个返回的对象,而通过字面量创建的对象,其原型指向的是Object构造函数的prototype属性,所以会出想上述情况。

================================================================================================================

再说new的执行过程,我们直接上代码

// new 一个对象的过程

function myNew() {
  // 1.创建一个空对象
  let obj = {}
  // 2.取出参数中的第一个参数,获得构造函数
// 此处请理解 call 的作用,并非真正的在 [] 上执行,而是在 arguments 这个数组中执行,删除了 arguments 中的构造函数,并将此构造函数返回
let constructor = [].shift.call(arguments) // 3.连接原型,将 obj 的原型指向构造函数的 prototype obj._proto_ = constructor.prototype // 4.执行构造函数,但 this 使用的是 obj 对象的this,其实到这一步,正常情况下 obj 这个对象就已经彻底构造完毕,成为实例了
let res = constructor.apply(obj, arguments) // 5.返回新对象
// 正常来讲,直接返回 obj 即可,但上面解释了,万一这个构造函数本身就返回一个对象呢?所以作此判断。如果是,那其实上面指来指去的都白干了
return typeof res === 'object' ? res : obj } function People(name, age) { this.name = name this.age = age } function School(name) { this.name = name return { name: "学校" } } const xiaozhang = myNew(People, 'xiaozhang', 19) console.log(xiaozhang.name) // xiaozhang console.log(xiaozhang.age) // 19 const newSchool = myNew(School, '大学') console.log(newSchool.name) // 大学

 

posted @ 2022-12-27 13:00  邢韬  阅读(56)  评论(0编辑  收藏  举报