详解JavaScript中new操作符的解析和实现
前言
new运算符是我们在用构造函数创建实例的时候使用的,本文来说一下new运算符的执行过程和如何自己实现一个类似new运算符的函数。
new运算符的运行过程
new运算符的主要目的就是为我们创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例(比如箭头函数就没有构造函数,所以是不能new的)。new操作符的执行大概有以下几个步骤:
- 创建一个新的空对象
- 把新对象的__proto__链接到构造函数的prototype对象(每一个用户定义函数都有一个prototype属性指向一个对象,该对象有一个constructor属性指向该函数),让我们的公共属性和方法可以从原型上继承,不用每个实例都创建一次。
- 将第一步创建的新的对象作为构造函数的this的上下文,执行构造函数,构造函数的执行让我们配置对象的私有属性和方法。
- 执行构造函数,如果构造函数没有返回值或者返回值不是一个对象,则返回this。
我么可以用代码简单表示上面的逻辑:
functionnew_(constr,...rests){ varobj={}; obj.__proto__=constr.prototype; varret=constr.apply(obj,rests); returnisPrimitive(ret)?obj:ret;//判断构造函数的返回值是否为对象,不是则直接返回创建的obj对象 }
new的实现
上面讲了new运算符的执行过程,下面我们来自己动手实现一个new运算符。
functionnew_(constr,...rests){ if(typeofconstr!=="function"){ throw"thefirstparammustbeafunction"; } new_.target=constr; varobj=Object.create(constr.prototype); varret=constr.apply(obj,rests); varisObj=typeofret!==null&&typeofret==="object"; varisFun=typeofret==="function"; //varisObj=typeofret==="function"||typeofret==="object"&&!!ret; if(isObj||isFun){ returnret; } returnobj; } functionPerson(name,age){ this.name=name; this.age=age; } Person.prototype.say=function(){ console.log(this.name); }; varp1=new_(Person,'clloz','28') varp2=new_(Person,'csx','31') console.log(p1);//Person {name:"clloz",age:"28"} p1.say();//clloz console.log(p2);//Person {name:"csx",age:"31"} p2.say();//csx console.log(p1.__proto__===Person.prototype);//true console.log(p2.__proto__===Person.prototype);//true
以上就是一个简单的new实现,判断是否为对象那里可能不是很严谨,不过没有想到更好的方法。
一个小补充,在mdn的Function.prototype.apply()词条中看到的直接把方法写到Function.prototype上,也是个不错的思路,Function.prototype在所以函数的原型链上,所以这个方法可以在每个函数上调用,方法内部的this也是指向调用方法的函数的。
Function.prototype.construct=function(aArgs){ varoNew=Object.create(this.prototype); this.apply(oNew,aArgs); returnoNew; };
强制用new调用构造函数
functionClloz(...arguments){ if(!(thisinstanceofClloz)){ returnnewClloz(...arguments) } }
Tips
补充两个关于new运算符的知识点。
- 上面提到new的执行过程的最后一步,如果构造函数没有返回值或者返回值不是一个对象,则返回this。但是如果返回的是一个null的话,依然返回this,虽然null也算是object。
- new操作符后面的构造函数可以带括号也可以不带括号,除了带括号可以传递参数以外,还有一个重要的点是两种用法的运算符优先级不一样,在JS运算符优先级这篇文章中有提到,带参数的new操作符的优先级是比不带参数的要高的,newFoo()>Foo()>newFoo。
一般不太会遇到,可能有些题目会问这些问题。
以上就是详解JavaScript中new操作符的解析和实现的详细内容,更多关于JavaScriptnew解析和实现的资料请关注毛票票其它相关文章!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。