likes
comments
collection
share

new对象时,v8引擎都干了些什么?--手写new的实现过程

作者站长头像
站长
· 阅读数 48

当我们创建实例对象时,会这样操作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();

new对象时,v8引擎都干了些什么?--手写new的实现过程

首先,这段代码的目的是创建Person的实例对象p,我们来看一下用new创建的效果会是和上面手写的myNew方法一样吗?

new对象时,v8引擎都干了些什么?--手写new的实现过程

nice! 得到了一样的结果,说明我们已经完成了手写new的实现过程。

总结思路

  • 首先我们在myNew中创建一个空对象。

  • 让它的__proto__指向传入对象的prototype,这一步用到的是apply方法。

  • 返回这个对象,此时该对象的__proto__已经指向了传入对象的prototype,也就完成了new操作的核心。

转载自:https://juejin.cn/post/7377691088154820623
评论
请登录