详解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中出现乱码的处理心得
Dec 24 Javascript
js select常用操作控制代码
Mar 16 Javascript
JQuery中each()的使用方法说明
Aug 19 Javascript
jQuery中的.bind()、.live()和.delegate()之间区别分析
Jun 08 Javascript
非常强大的 jQuery.AsyncBox 弹出对话框插件
Aug 29 Javascript
5分钟理解JavaScript中this用法分享
Nov 09 Javascript
原生js实现淘宝首页点击按钮缓慢回到顶部效果
Apr 06 Javascript
深入解读JavaScript中的Iterator和for-of循环
Jul 28 Javascript
12个非常有用的JavaScript技巧
May 17 Javascript
ajax+node+request爬取网络图片的实例(宅男福利)
Aug 28 Javascript
原生JS实现简单的倒计时功能示例
Aug 30 Javascript
使用 vue 实例更好的监听事件及vue实例的方法
Apr 22 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下删除字符串中HTML标签的函数
2008/08/27 PHP
PHP时间戳 strtotime()使用方法和技巧
2013/10/29 PHP
PHP使用内置dir类实现目录遍历删除
2015/03/31 PHP
php进行ip地址掩码运算处理的方法
2016/07/11 PHP
JQuery 动画卷页 返回顶部 动画特效(兼容Chrome)
2010/02/15 Javascript
javascript 模式设计之工厂模式详细说明
2010/05/10 Javascript
jquery.fileEveryWhere.js 一个跨浏览器的file显示插件
2011/10/24 Javascript
最简单的JavaScript验证整数、小数、实数、有效位小数正则表达式
2015/04/17 Javascript
深入浅析Node.js 事件循环
2015/12/20 Javascript
JavaScript字符串删除重复字符的方法
2015/12/25 Javascript
JavaScript+html5 canvas绘制渐变区域完整实例
2016/01/26 Javascript
jQuery Ajax 加载数据时异步显示加载动画
2016/08/01 Javascript
JavaScript中日常收集常见的10种错误(推荐)
2017/01/08 Javascript
Webpack 服务器端代码打包的示例代码
2017/09/19 Javascript
深入浅析javascript继承体系
2017/10/23 Javascript
nodeJs爬虫的技术点总结
2018/05/13 NodeJs
微信小程序仿美团城市选择
2018/06/06 Javascript
React优化子组件render的使用
2019/05/12 Javascript
js的新生代垃圾回收知识点总结
2019/08/22 Javascript
JavaScript代码异常监控实现过程详解
2020/02/17 Javascript
JS+CSS实现3D切割轮播图
2020/03/21 Javascript
JavaScript 双向链表操作实例分析【创建、增加、查找、删除等】
2020/04/28 Javascript
[03:42]2014DOTA2国际邀请赛 第三日比赛排位扑朔迷离
2014/07/12 DOTA
[23:18]Spirit vs Liquid Supermajor小组赛A组 BO3 第二场 6.2
2018/06/03 DOTA
python实现模拟按键,自动翻页看u17漫画
2015/03/17 Python
用实例详解Python中的Django框架中prefetch_related()函数对数据库查询的优化
2015/04/01 Python
python使用xslt提取网页数据的方法
2018/02/23 Python
浅析PyTorch中nn.Module的使用
2019/08/18 Python
python getopt模块使用实例解析
2019/12/18 Python
prAna官网:瑜伽、旅行和冒险服装
2019/03/10 全球购物
幼教个人求职信范文
2013/12/02 职场文书
护林防火标语
2014/06/27 职场文书
电力培训心得体会
2014/09/02 职场文书
银行求职信范文
2019/05/13 职场文书
JS实现简单控制视频播放倍速的实例代码
2021/04/18 Javascript
浅谈Python项目的服务器部署
2021/04/25 Python