详解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 29 Javascript
一个符号插入器 中用到的js代码
Sep 04 Javascript
javascript IE中的DOM ready应用技巧
Jul 23 Javascript
input+select(multiple) 实现下拉框输入值
May 21 Javascript
js hover 定时器(实例代码)
Nov 12 Javascript
JavaScript中的anchor()方法使用详解
Jun 08 Javascript
关于jQuery里prev()的简单操作代码
Oct 27 jQuery
详解Vue组件实现tips的总结
Nov 01 Javascript
vue.js2.0点击获取自己的属性和jquery方法
Feb 23 jQuery
JS学习笔记之贪吃蛇小游戏demo实例详解
May 29 Javascript
jQuery设置下拉框显示与隐藏效果的方法分析
Sep 15 jQuery
在js文件中引入(调用)另一个js文件的三种方法
Sep 11 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获取本周,上周,本月,上月,本季度日期的代码
2009/08/05 PHP
php动态实现表格跨行跨列实现代码
2012/11/06 PHP
解析PHP将对象转换成数组的方法(兼容多维数组类型)
2013/06/21 PHP
php小经验:解析preg_match与preg_match_all 函数
2013/06/29 PHP
利用Javascript判断操作系统的类型实现不同操作系统下的兼容性
2013/01/29 Javascript
js中的preventDefault与stopPropagation详解
2014/01/29 Javascript
深入解析JavaScript中的arguments对象
2016/06/12 Javascript
js创建对象几种方式的优缺点对比
2016/09/28 Javascript
jQuery+json实现动态创建复杂表格table的方法
2016/10/25 Javascript
解析Vue2.0双向绑定实现原理
2017/02/23 Javascript
详解vue与后端数据交互(ajax):vue-resource
2017/03/16 Javascript
nodejs个人博客开发第六步 数据分页
2017/04/12 NodeJs
详解基于node的前端项目编译时内存溢出问题
2017/08/01 Javascript
使用vue-cli打包过程中的步骤以及问题的解决
2018/05/08 Javascript
详解vuex中action何时完成以及如何正确调用dispatch的思考
2019/01/21 Javascript
vue 单页应用和多页应用的优劣
2020/10/22 Javascript
简单谈谈Python流程控制语句
2016/12/04 Python
itchat-python搭建微信机器人(附示例)
2019/06/11 Python
python3多线程知识点总结
2019/09/26 Python
Python下应用opencv 实现人脸检测功能
2019/10/24 Python
django中url映射规则和服务端响应顺序的实现
2020/04/02 Python
python爬虫破解字体加密案例详解
2021/03/02 Python
详解使用postMessage解决iframe跨域通信问题
2019/11/01 HTML / CSS
最好的商品表达自己:Cafepress
2019/09/04 全球购物
Shopbop中文官网:美国亚马逊旗下时尚购物网站
2020/12/15 全球购物
保安员岗位职责
2013/11/17 职场文书
优秀求职信范文分享
2014/01/26 职场文书
致标枪运动员加油稿
2014/02/15 职场文书
研究生简历自我评价范文
2014/09/13 职场文书
2015年元旦晚会活动总结(学生会)
2014/11/28 职场文书
自我检讨书怎么写
2015/05/07 职场文书
给校长的建议书范文
2015/09/14 职场文书
银行求职信怎么写
2019/06/20 职场文书
详解MySQL 用户权限管理
2021/04/20 MySQL
Golang 实现超大文件读取的两种方法
2021/04/27 Golang
MySQL系列之十五 MySQL常用配置和性能压力测试
2021/07/02 MySQL