new对象时,v8引擎都干了些什么?--手写new的实现过程
当我们创建实例对象时,会这样操作
let p = new Person();
也会说是new
了一个构造函数,有时候也会说用new关键字调用了函数,完成这个操作之后,实例对象就可以访问到Person上的方法和属性,那么new这个过程到底发生了什么,能让Person
心甘情愿的被访问,p
又是怎么准确的访问到Person
的方法与属性呢?接下来,让我们直接手写官方new关键字的实现过程。
一、原型链
在上面的例子中,我们知道p可以准确的访问到Person的属性与方法,它就是通过原型链,才能够锁定住Person,请让我介绍一下原型链。
1、概念
在每个对象中都会内置一个__proto__
属性访问器,它既不是标准的方法,也不是标准的属性,用来访问自己的prototype
原型对象属性,这个属性在每个对象创建时,会自动获得,它指向了自己的原型对象,v8引擎的查找,就是一次一次的顺着这个关系一层的查找,直到找到自己需要的属性,这个链状的查找过程称为原型链。
通过下面的代码,我们来体验一下它的查找方式。
function Person(){
// var this = {
// name:'tom'
// }
// this.__proto__ =Person.prototype
}
let p = new Person()
Person.prototype.lastName = '张' //在Person的原型对象上添加 //latsName属性,值为张
function Grand(){
this.name = '三'
}
function Father(){
this.age = 40
}
function Son(){
this.like = 'coding'
}
let son = new Son()
// {
// like : 'coding',
// __proto__:Son.prototype ==new Father:{
// __proto__ :Father.prototype ==new Grand:{
// __proto__:Grand.prototype ==new Object():{
// __proto__:Objetc.prototype:{
// __proto__:null}
// }
// }
// }
// }
暂时不懂的小伙伴们接着往下看。
二、new操作的核心,apply()方法
我们在上文中提到,每个对象中内置的
__proto__
属性访问器,会指向自己的prototype
属性,换句话说,这个属性访问器可以知道自己的原型对象,也就是说,当你能够把自己的__proto__
指向自己的原型对象,那么就可以说基本完成了一new操作,apply
方法就是实现这个操作的核心。
1、apply的使用
- 基本语法:
function.apply(thisArg, [argsArray])
- 这个方法可以允许你改变调用这个方法的function的this的指向,同时还可以接受function的参数,如下示例。
var obj ={
a:1
}
function foo(x,y){
console.log(this.a,x+y);
}
foo.apply(obj,[2,3]) //数组形式接收参数
foo未调用apply()方法时this指向全局或是window,当调用apply后,就指向了第一个参数对象,第二个参数以数组的方式接收foo的参数。
三、手写new的实现过程
现在我们已经知道了new操作会让实例对象拥有一些东西,也知道了它是怎么找到和使用这些东西(属性)的,当然
apply
方法,new实现的核心也被我们掌握了,接下来就可以手写new操作了。
function myNew(Fun,...args){
let obj = {}
Fun.apply(obj,args)
obj.__proto__ = Fun.prototype
return obj
}
function Person(p){
this.name = p
}
Person.prototype.mynew = function(){
console.log('我是Person的实例对象');
}
Person.prototype.myname = function(){
console.log(this.name)
}
let p = myNew(Person,'大黄')
p.mynew();
p.myname();
首先,这段代码的目的是创建Person的实例对象p,我们来看一下用new创建的效果会是和上面手写的myNew方法一样吗?
nice! 得到了一样的结果,说明我们已经完成了手写new的实现过程。
总结思路
-
首先我们在myNew中创建一个空对象。
-
让它的__proto__指向传入对象的prototype,这一步用到的是apply方法。
-
返回这个对象,此时该对象的__proto__已经指向了传入对象的prototype,也就完成了new操作的核心。
转载自:https://juejin.cn/post/7377691088154820623