详解JavaScript中new操作符的解析和实现


Posted in Javascript onSeptember 04, 2020

前言

new 运算符是我们在用构造函数创建实例的时候使用的,本文来说一下 new 运算符的执行过程和如何自己实现一个类似 new 运算符的函数。

new 运算符的运行过程

new 运算符的主要目的就是为我们创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例(比如箭头函数就没有构造函数,所以是不能 new 的)。new 操作符的执行大概有以下几个步骤:

  1. 创建一个新的空对象
  2. 把新对象的 __proto__ 链接到构造函数的 prototype 对象(每一个用户定义函数都有一个 prototype 属性指向一个对象,该对象有一个 constructor 属性指向该函数),让我们的公共属性和方法可以从原型上继承,不用每个实例都创建一次。
  3. 将第一步创建的新的对象作为构造函数的 this 的上下文,执行构造函数,构造函数的执行让我们配置对象的私有属性和方法。
  4. 执行构造函数,如果构造函数没有返回值或者返回值不是一个对象,则返回 this

我么可以用代码简单表示上面的逻辑:

function new_ (constr, ...rests) {
 var obj = {};
 obj.__proto__ = constr.prototype;
 var ret = constr.apply(obj, rests);
 return isPrimitive(ret) ? obj : ret; //判断构造函数的返回值是否为对象,不是则直接返回创建的obj对象
}

new 的实现

上面讲了 new 运算符的执行过程,下面我们来自己动手实现一个 new 运算符。

function new_(constr, ...rests) {
 if (typeof constr !== "function") {
 throw "the first param must be a function";
 }
 new_.target = constr;
 var obj = Object.create(constr.prototype);
 var ret = constr.apply(obj, rests);
 var isObj = typeof ret !== null && typeof ret === "object";
 var isFun = typeof ret === "function";
 //var isObj = typeof ret === "function" || typeof ret === "object" && !!ret;
 if (isObj || isFun) {
 return ret;
 }
 return obj;
}

function Person(name, age) {
 this.name = name;
 this.age = age;
}
Person.prototype.say = function () {
 console.log(this.name);
};
var p1 = new_(Person, 'clloz', '28')
var p2 = 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 实现,判断是否为对象那里可能不是很严谨,不过没有想到更好的方法。

一个小补充,在 mdnFunction.prototype.apply() 词条中看到的直接把方法写到 Function.prototype 上,也是个不错的思路,Function.prototype 在所以函数的原型链上,所以这个方法可以在每个函数上调用,方法内部的 this 也是指向调用方法的函数的。

Function.prototype.construct = function (aArgs) {
 var oNew = Object.create(this.prototype);
 this.apply(oNew, aArgs);
 return oNew;
};

强制用 new 调用构造函数

function Clloz(...arguments) {
 if (!(this instanceof Clloz)) {
 return new Clloz(...arguments)
 }
}

Tips

补充两个关于 new 运算符的知识点。

  1. 上面提到 new 的执行过程的最后一步,如果构造函数没有返回值或者返回值不是一个对象,则返回 this。但是如果返回的是一个 null 的话,依然返回 this,虽然 null 也算是 object
  2. new 操作符后面的构造函数可以带括号也可以不带括号,除了带括号可以传递参数以外,还有一个重要的点是两种用法的运算符优先级不一样,在JS运算符优先级这篇文章中有提到,带参数的 new 操作符的优先级是比不带参数的要高的,new Foo() > Foo() > new Foo

一般不太会遇到,可能有些题目会问这些问题。

以上就是详解JavaScript中new操作符的解析和实现的详细内容,更多关于JavaScript new解析和实现的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
JavaScript操作XML实例代码(获取新闻标题并分页,并分页)
May 25 Javascript
javascript闭包的高级使用方法实例
Jul 04 Javascript
JS教程:window.location使用方法的区别介绍
Oct 04 Javascript
Js Jquery创建一个弹出层可加载一个页面
May 08 Javascript
JS解析XML文件和XML字符串详解
Apr 17 Javascript
jquery.qtip提示信息插件用法简单实例
Jun 17 Javascript
Bootstrap简单表单显示学习笔记
Nov 15 Javascript
javascript实现根据函数名称字符串动态执行函数的方法示例
Dec 28 Javascript
vue组件初学_弹射小球(实例讲解)
Sep 06 Javascript
使用puppeteer爬取网站并抓出404无效链接
Dec 20 Javascript
详解angular2 控制视图的封装模式
Dec 27 Javascript
layui动态加载多表头的实例
Sep 05 Javascript
我所理解的JavaScript中的this指向
Sep 04 #Javascript
JS运算符优先级与表达式示例详解
Sep 04 #Javascript
vue中的循环对象属性和属性值用法
Sep 04 #Javascript
JavaScript逻辑运算符相关总结
Sep 04 #Javascript
浅析JavaScript预编译和暗示全局变量
Sep 03 #Javascript
详解JavaScript作用域、作用域链和闭包的用法
Sep 03 #Javascript
JS变量提升及函数提升实例解析
Sep 03 #Javascript
You might like
PHP简洁函数小结
2011/08/12 PHP
php通过asort()给关联数组按照值排序的方法
2015/03/18 PHP
PHP+redis实现的悲观锁机制示例
2018/06/12 PHP
javascript 自动转到命名锚记
2009/01/10 Javascript
分享10篇优秀的jQuery幻灯片制作教程及应用案例
2011/04/16 Javascript
终于解决了IE8不支持数组的indexOf方法
2013/04/03 Javascript
JavaScript运行时库属性一览表
2014/03/14 Javascript
jquery实现人性化的有选择性禁用鼠标右键
2014/06/30 Javascript
使用Nodejs开发微信公众号后台服务实例
2014/09/03 NodeJs
js中函数声明与函数表达式
2015/06/03 Javascript
JavaScript实现下拉菜单的显示和隐藏
2016/01/05 Javascript
如何消除inline-block属性带来的标签间间隙
2016/03/31 Javascript
Vue入门之数据绑定(小结)
2018/01/08 Javascript
vue中实现methods一个方法调用另外一个方法
2018/02/08 Javascript
nuxt+axios实现打包后动态修改请求地址的方法
2020/04/22 Javascript
Vue elementui字体图标显示问题解决方案
2020/08/18 Javascript
H5 js点击按钮复制文本到粘贴板
2020/11/19 Javascript
[03:46]DOTA2英雄基础教程 维萨吉
2013/12/11 DOTA
[01:02:04]EG vs Liquid 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.23
2019/09/05 DOTA
python中使用正则表达式的后向搜索肯定模式(推荐)
2017/11/11 Python
Python编程实现从字典中提取子集的方法分析
2018/02/09 Python
python框架flask表单实现详解
2019/11/04 Python
python实现宿舍管理系统
2019/11/22 Python
在Python中使用turtle绘制多个同心圆示例
2019/11/23 Python
什么是python的列表推导式
2020/05/26 Python
Python内置函数及功能简介汇总
2020/10/13 Python
CSS3效果:自定义“W”形运行轨迹实例
2017/03/29 HTML / CSS
什么是SCM(软件配置管理)
2014/08/16 面试题
正规的求职信范文分享
2013/12/11 职场文书
《学会合作》教学反思
2014/04/12 职场文书
重阳节活动总结
2014/08/27 职场文书
2015年底工作总结范文
2015/05/15 职场文书
2015年信息宣传工作总结
2015/05/26 职场文书
Html分层的box-shadow效果的示例代码
2021/03/30 HTML / CSS
详细分析PHP7与PHP5区别
2021/06/26 PHP
Lombok的详细使用及优缺点总结
2021/07/15 Java/Android