在回答这个问他之前,我们需要思考这些问题:
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下面有一张图;可以让我们理清楚他们之间的关系
好了,说了这么多。回到我们的提问:
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__=Person.prototype;
let result=Func.call(obj,...args)
if(result!=null&&/^(object|function)$/.test(typeof result)){
return result
}
return obj
}