详解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操作文本框readOnly
May 15 Javascript
解析javascript 实用函数的使用详解
May 10 Javascript
js判断数据类型如判断是否为数组是否为字符串等等
Jan 15 Javascript
JavaScript编程学习技巧汇总
Feb 21 Javascript
js实现上传图片及时预览
May 07 Javascript
浅谈JavaScript函数的四种存在形态
Jun 08 Javascript
详解Webpack DLL用法以及功能
Jul 11 Javascript
webpack 2.x配置reactjs基本开发环境详解
Aug 08 Javascript
Vue.js实现按钮的动态绑定效果及实现代码
Aug 21 Javascript
对于js垃圾回收机制的理解
Sep 14 Javascript
Vue多种方法实现表头和首列固定的示例代码
Feb 02 Javascript
Swiper.js实现移动端元素左右滑动
Sep 08 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使用smtp发送支持附件的邮件示例
2014/04/13 PHP
linux下编译安装memcached服务
2014/08/03 PHP
如何使用纯PHP实现定时器任务(Timer)
2015/07/31 PHP
php无限分类使用concat如何实现
2015/11/05 PHP
关于PHP通用返回值设置方法
2017/03/31 PHP
PHP实现基于图的深度优先遍历输出1,2,3...n的全排列功能
2017/11/10 PHP
50个优秀经典PHP算法大集合 附源码
2020/08/26 PHP
简单的jquery拖拽排序效果实现代码
2011/09/20 Javascript
浅析JavaScript原型继承的陷阱
2013/12/03 Javascript
多个jquery.datatable共存,checkbox全选异常的快速解决方法
2013/12/10 Javascript
javascript 按键事件(兼容各浏览器)
2013/12/20 Javascript
js 调用百度地图api并在地图上进行打点添加标注
2014/05/13 Javascript
jQuery 中国省市两级联动选择附图
2014/05/14 Javascript
jquery实现Ctrl+Enter提交表单的方法
2015/07/21 Javascript
使用canvas实现仿新浪微博头像截取上传功能
2015/09/02 Javascript
js removeChild 方法深入理解
2016/08/16 Javascript
JS添加或修改控件的样式(Class)实现方法
2016/10/15 Javascript
Express框架之connect-flash详解
2017/05/31 Javascript
原生js 封装get ,post, delete 请求的实例
2017/08/11 Javascript
在微信小程序里使用watch和computed的方法
2018/08/02 Javascript
新手必须知的Node.js 4个JavaScript基本概念
2018/09/16 Javascript
详解在IDEA中将Echarts引入web两种方式(使用js文件和maven的依赖导入)
2020/07/11 Javascript
[02:49]2018DOTA2亚洲邀请赛主赛事决赛日战况回顾 Mineski鏖战5局夺得辉耀
2018/04/10 DOTA
Python黑魔法Descriptor描述符的实例解析
2016/06/02 Python
python 利用浏览器 Cookie 模拟登录的用户访问知乎的方法
2019/07/11 Python
python的json中方法及jsonpath模块用法分析
2019/12/06 Python
美国知名的女性服饰品牌:LOFT(洛芙特)
2016/08/05 全球购物
法国娇韵诗官方旗舰店:Clarins是来自法国的天然护肤品牌
2018/06/30 全球购物
暑期社会实践方案
2014/02/05 职场文书
畜牧兽医本科生的自我评价
2014/03/03 职场文书
竞选团支书演讲稿
2014/04/28 职场文书
农村党员对照检查材料
2014/09/24 职场文书
员工辞职信怎么写
2015/02/27 职场文书
辣妈辣妹观后感
2015/06/10 职场文书
钓鱼岛事件感想
2015/08/11 职场文书
Python中X[:,0]和X[:,1]的用法
2021/05/10 Python