手动实现一个new

224 阅读3分钟

先说说new是做什么,怎么用的? 看代码,我们一一解释

//构造函数
    function Animal(type){
        this.type = type
    }
    Animal.prototype.say = function(){
        //为了区分我们打印一个哺乳
        console.log("say")
    }
    //实例化
    let animal = new Animal('哺乳动物')

    console.log(animal)//
    console.log(animal.type)//打印结果是 哺乳动物
    animal.say() //打印结果是 哺乳

实例对象

1、首先构造函数是一个对象,证明new 返回一个对象,根据我们的测试我们暂时先这么定义 2、实例化对象可以拿到构造函数的属性 3、实例对象也可以拥有构造函数的原型上的方法和属性

下面我们根据构造函数->实例化后的一些特性来模拟new的实现。


    function mockNew(){
        //参数不定的情况下我们用arguments来操作,顺便用下es6的解构
        //上边我们解释过,参数有两部分组成,构造函数(也就是所谓的类),参数
        let [Fn,options] = [[...arguments][0],[...arguments].slice(1)]
        console.log(Fn,options)//打印结果 Animal构造函数,和 tom/2

        //返回一个对象,那我们就定义一个对象
        let obj = {}
        //下面我们实现对象的功能
        // 怎么获得构造函数的属性 也就是让obj拿到构造函数的属性(属性都在options里面)
        Fn.apply(obj,options)//执行构造函数,并把this指向obj,这样是不是就搞定了
        
        // 接下来我们实现obj拥有构造函数原型上的方法
        // 这就用到原型链了,每一个对象都有__proto__属性,每个函数都有prototype原型
        // 为了能详细说明  我们再画一下
        obj.__proto__ = Fn.prototype
        return obj
    }

image.png

    //构造函数
    function Animal(type){
        this.type = type
    }
    Animal.prototype.say = function(){
        //为了区分我们打印一个哺乳
        console.log("我是构造函数的say方法")
    }
    //实例化
    // let animal = new Animal('哺乳动物')
    let animal = mockNew(Animal,'mock哺乳动物')

    console.log('实例对象:', animal)//
    console.log('实例的type属性:'+animal.type)//打印结果是 哺乳动物
    animal.say() //打印结果是 哺乳

测试一下效果:

测试mockNew

貌似没毛病!

//还有一种情况 如果构造函数有返回值 我们先测试原生new是怎么做的

    function Animal1(type){
        this.type = type
        // return {name:"xd"} //如果是对象 new执行完 返回此对象
        return type //如果是非引用类型,new的返回结果不变
    }

    let animal1 = new Animal1('哺乳动物1')

    console.log(animal1,animal1.type)

既然是模拟 我们要做到一样的效果

 function mockNew(){
        //参数不定的情况下我们用arguments来操作,顺便用下es6的解构
        //上边我们解释过,参数有两部分组成,构造函数(也就是所谓的类),参数
        let [Fn,options] = [[...arguments][0],[...arguments].slice(1)]
        console.log(Fn,options)//打印结果 Animal构造函数,和 tom/2

        //返回一个对象,那我们就定义一个对象
        let obj = {}
        //下面我们实现对象的功能
        // 怎么获得构造函数的属性 也就是让obj拿到构造函数的属性(属性都在options里面)
        let result = Fn.apply(obj,options)//执行构造函数,并把this指向obj,这样是不是就搞定了

        // 接下来我们实现obj拥有构造函数原型上的方法
        // 这就用到原型链了,每一个对象都有__proto__属性,每个函数都有prototype原型
        // 为了能详细说明  我们再画一下
        obj.__proto__ = Fn.prototype

        //定义result就是构造函数返回值,判断返回值是不是引用类型,如果是返回构造函数返回值,如果不是返回我们定义的obj

        return result instanceof Object? result: obj
    }

模拟new 操作聊完了 欢迎吐槽!