JS 操作符优先级及new

JavaScript024

JS 操作符优先级及new,第1张

基于segmentfault上的一道题

由此可以知道new 的优先级带参数的比不带的高

在第三种解析中我们要计算 new (foo.prototype.getName)() 的值,首先要明白new到底做了什么,其实就做了3件事

第一步:创建一个空对象

第二步:绑定该对象的原型

第三部:调用构造函数 // 执行了构造函数的内容

所以在 new (foo.prototype.getName)() 也就会返回foo.prototype.getName的一个实例,并且执行一次构造函数,也就是执行 console.log(3) ,打印3这个结果

手写new操作符的流程:

 // 1.定义一个空对象

 // 2.隐式原型指向构造函数的显式原型

// 3.执行构造函数,this指向空对象

 // 4.返回对象

function myNew(fn,...args){

        // 1.定义一个空对象

          const obj={}

         // 2.隐式原型指向构造函数的显式原型

         obj._proto_=fn.prototype

         // 3.执行构造函数,this指向空对象

        fn.apply(obj,args)

          // 4.返回对象

        return obj

        }

[toc]

new 操作符通过执行自定义构造函数或者js内置构造函数,从而生成一个实例对象。

mdn 上把内部操作大概分为4步:

通过一个简单的demo感受下上面的步骤

可以看到new操作符执行Person构造函数后,返回了一个内部创建的新对象, 并且以这个对象为上线文环境执行了一遍Person函数 ,最后将其返回,同时对象p的原型属性指向构造函数的原型, 这样也就保证了实例能够访问在构造函数原型中定义的属性和方法

上面的demo中构造函数是没有返回值的,如果说构造函数有返回值呢,如下

如果构造函数最后返回了一个对象,就会直接将其返回,而不是内部创建的新对象。

经过测试发现,除了返回对象,如果返回其他类型,只要最后返回的类型为引用类型 object 或者 function ( Function , Object , Array , Date , Error , Regexp ,要排除 null ,因为 typeof null === 'object' )就会直接将其返回,而其他基本类型都会返回内部新创建的对象。

这里我们尝试通过封装一个 myNew 方法模拟new操作符的主要功能:接受若干参数,第一个参数为构造函数 ctr ,其余为构造器所需参数, myNew(ctr, arg1, arg2,...)

这里的第一步把mdn中的1、2步放在了一起:创建一个新对象,并将其 __proto__ 属性指向构造函数的 prototype 属性

也可以使用如下方法

获取到参数之后,以内部新创建的对象 obj 为上线文执行构造函数,作用是为 obj 赋值

上面的 const args = [].slice.call(arguments, 1)用于将 arguments 类数组转为数组并获取参数,也可以通过 Array.form(arguments).slice(1) 或者 [...arguments].slice(1) 实现。

对执行构造函数后的返回值 result 做兼容处理。

如果构造函数最终返回对象、函数、数组、日期等其他引用类型及Symbol,会将其直接返回,其他基本类型及 null 、 undefined 会返回内部新创建的对象实例。

最后,简单测试一下

没有返回值

有返回值

面试官问:能否模拟实现JS的new操作符

手动实现一个new操作符理解