手写new的实现,说一说new过程中都发生里什么?

737 阅读3分钟

在回答这个问他之前,我们需要思考这些问题:

1 new 关键词是用来干什么的?什么场景下会用到new?

2 new 出来的对象和之前的对象有什么关系?

3 new出来的对象有什么特点?

只有彻底缕清这些关系,才能让我们了解new的过程中到底发生了什么?

首先我们思考第一个问题:

1 new 关键词是用来干什么的?

new关键词是用来实例化一个对象的。new出来的对象,也就是实例化的对象,继承了构造函数的属性和方法,也就是new出来的对象,一出生就继承了父级对象(构造函数)的某些特征。那问题来了。为啥?它是怎么做到的?

这就不得不提到js中的原型和原型链。

js中每一个对象,都会隐式有一个__proto__对象,而对于每个函数,都会有叫prototype的对象,我们通过new 实例化的对象,它的__proto__就默认指向了它父级(构造函数)的prototype,而它父级本身的prototype,因为也是一个对象,所以它的__proto__也指向了它的父级(构造函数)的prototype

function Person(name){
    this.name=name
}

let p=new Person("小虎")

console.log(p.__proto__==Person.prototype)  //true
console.log(Person.prototype.__proto__==Object.prototype)  //true

`` 到这就截止了。,由实例对象---》构造函数(父级)---》Object(顶级)构成了这是一条链路,我们称之为原型链。但是再想想,这条链路由底层往上回溯能一步步找到对应关系,那由顶层往下能否找到对应关系呢?答案是:能。

那通过什么能形成   Object(顶级)----》构造函数(父级)---》实例对象的对应关系呢?那就是父级(构造函数)本身的construct属性。

好家伙,有点双向链表的意思啊。

但是这里有第一个地方需要注意:那就是函数。

函数比较特殊。因为函数在typeof里被解析为object,所以。它既有函数本身的特征,也有对象的某些特征,那我们不禁会问:既然每个对象都有__proto__属性,那Person它有__proto__吗?

当然有,Person.proto==Function.prototype下面有一张图;可以让我们理清楚他们之间的关系

微信图片_20211125164613.jpg ` 好了,说了这么多。回到我们的提问:

new 过程中到底发生了什么?

总结一下

1 首先要创建一个对象。这是保证__proto__ =====》prototype关系的基础

2 new的时候,new出来的对象必须要保持和它的构造函数保持一定的关系

也就是 p.proto=Person.prototye,同时Person.prototye.constructor=function person(){xxx}

需要建立双方的关系

3 new 出来的实例。其里面传入的参数,或者执行方法,this指向就是这个new出来的实例本身。(回答了第三个问题)

4 当然构造函数执行的时候可能会有返回值,如果有则要返回出来,没有则直接返回obj本身

这就是new实例化时发生的过程。接下来我们用代码模拟一下`

//Func===>构造函数类

function _new (Func,...args){
  let obj={}

  obj.__proto__=Func.prototype;
  let result=Func.call(obj,...args)
  if(result!=null&&/^(object|function)$/.test(typeof result)){
    return result
  }
  return obj
}