JavaScript | 手写new(面试篇)

274 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第17天,点击查看活动详情

手写new

一. 通过代码来分析一下new操作符

  //创建构造函数
  function Person(name, age) {
            this.name = name;
            this.age = age;
        }
    //添加方法
    Person.prototype.do = function () {
        console.log("hhhh");
    }
    //new操作符调用方法
     var p = new Person('lucky',18);
     console.log(p)
     console.log(p.do)

打印信息

CB0FCD6F-358C-45D9-9A31-A303AC05B4BF.png

由此可以得出

  1. new调用返回的是一个对象
  2. 把函数内部的this指向了这个对象
  3. 把对象的隐式原型指向了构造函数的显示原型

二.值的注意的点

如果构造函数没有返回值或者返回值是基本类型,则正常返回实例化对象,如果构造函数的返回值是对象类型,则不再返回实例化对象,而是返回该对象类型

  function Person(name, age) {
            this.name = name;
            this.age = age;
            //return 1; //返回基本类型会被实例替代
            return {obj:'哈哈哈'}; //返回对象类型会替代实例
        }
     var p = new Person('lucky',18); 
     console.log(p) 

验证如下

  1. return 1返回基本类型会被实例替代 7064FA89-6245-4405-873C-F75B349C94F5.png

  2. return {obj:'哈哈哈'}返回对象类型会替代实例 D8F31CE1-62D7-441D-BF3F-3CA690B0AB68.png

三. 通过以上分析,new运算符的执行过程大致是如下

  • 创建对象,开辟内存空间
  • 设置原型链
  • this指向该内存
  • 执行函数中的代码
  • 将地址返回

四.知道原理后,我们开始手写new

function Person(name, age) {
            this.name = name;
            this.age = age;
            //return 1; //返回基本类型会被实例替代
            return {obj:'哈哈哈'}; //返回对象类型会替代实例
        }
        Person.prototype.do = function () {
            console.log("hhhh");
        }
 /* 
    手写new:
        1.声明一个对象obj,作为new的返回值(实例化对象)
        2.调用构造函数,并且把构造函数的this指向obj
        3.修改obj的隐式原型为构造函数的显示原型
        4.判断构造函数的返回值类型,如果是基本类型则正常返回obj,否则返回构造函数的返回值
        
  */
function myNew(FN) {
        //声明一个对象obj,作为new的返回值(实例化对象)
        var obj = {};
        //调用构造函数,并且把构造函数的this指向obj
        var FNReturn = FN.apply(obj, Array.from(arguments).slice(1));
        //修改obj的隐式原型为构造函数的显示原型
        obj.__proto__ = FN.prototype;

        //判断类型是object 并且不是null
        if (typeof FNReturn === 'object' && FNReturn != 'null') {
            return FNReturn;
        }

        //判断是function
        if (typeof FNReturn === 'function') {
            return FNReturn;
        }
        //基本类型值
        return obj;
    }
   //打印验证
    var p = myNew(Person, "lucky", "18");
    console.log(p)
    console.log(p.constructor)

打印验证结果成功

  1. return 1返回基本类型会被实例替代,正常返回 59BFFFA5-3FDE-4C55-A1DD-1AD9373EB1B1.png

  2. return {obj:'哈哈哈'}返回对象类型会替代实例

20885B15-246C-420C-A6FC-0583B7D8AAF9.png

五.总结

除了考虑this指向和原型,最最重要的是构造函数的返回值,严重影响了new操作符的调用。

好了,以上就是本篇文章的分享,感谢阅读!