详解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 16 Javascript
JavaScript中实现继承的三种方式和实例
Jan 29 Javascript
每天一篇javascript学习小结(Boolean对象)
Nov 12 Javascript
js创建对象的方法汇总
Jan 07 Javascript
Jquery元素追加和删除的实现方法
May 24 Javascript
JS实现密码框的显示密码和隐藏密码功能示例
Dec 26 Javascript
微信小程序 九宫格实例代码
Jan 21 Javascript
jquery实现全选、全不选以及单选功能
Mar 23 jQuery
关于HTTP传输中gzip压缩的秘密探索分析
Jan 12 Javascript
使用use注册Vue全局组件和全局指令的方法
Mar 08 Javascript
微信小程序API—获取定位的详解
Apr 30 Javascript
js基于div丝滑实现贝塞尔曲线
Sep 23 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中的时间处理
2006/10/09 PHP
require(),include(),require_once()和include_once()的异同
2007/01/02 PHP
php 远程关机操作的代码
2008/12/05 PHP
win7系统配置php+Apache+mysql环境的方法
2015/08/21 PHP
PHP面向对象之领域模型+数据映射器实例(分析)
2017/06/21 PHP
tp5实现微信小程序多图片上传到服务器功能
2018/07/16 PHP
thinkPHP5框架分页样式类完整示例
2018/09/01 PHP
PHP+mysql实现的三级联动菜单功能示例
2019/02/15 PHP
YII2框架中behavior行为的理解与使用方法示例
2020/03/13 PHP
JQuery 获得绝对,相对位置的坐标方法
2010/02/09 Javascript
『JavaScript』限制Input只能输入数字实现思路及代码
2013/04/22 Javascript
2014 HTML5/CSS3热门动画特效TOP10
2014/12/07 Javascript
javascript文本框内输入文字倒计数的方法
2015/02/24 Javascript
javascript实现漂亮的拖动层,窗口拖拽特效
2015/04/24 Javascript
jquery实现两个图片渐变切换效果的方法
2015/06/25 Javascript
谈谈AngularJs中的隐藏和显示
2015/12/09 Javascript
JS获取屏幕高度的简单实现代码
2016/05/24 Javascript
深入理解JavaScript内置函数
2016/06/03 Javascript
微信小程序实现点击文字页面跳转功能【附源码下载】
2017/12/12 Javascript
Vue 页面跳转不用router-link的实现代码
2018/04/12 Javascript
手把手教你vue-cli单页到多页应用的方法
2018/05/31 Javascript
VUE预渲染及遇到的坑
2018/09/03 Javascript
JavaScript函数式编程(Functional Programming)声明式与命令式实例分析
2019/05/21 Javascript
[02:51]DOTA2 Supermajor小组分组对阵抽签仪式
2018/06/01 DOTA
Python3 适合初学者学习的银行账户登录系统实例
2017/08/08 Python
python pygame实现五子棋小游戏
2020/10/26 Python
Python递归调用实现数字累加的代码
2020/02/25 Python
Myprotein中国网站:欧洲畅销运动营养品牌
2021/02/11 全球购物
日本语毕业生自荐信
2014/02/01 职场文书
电工工作职责范本
2014/02/22 职场文书
中职毕业生自我鉴定范文(3篇)
2014/09/28 职场文书
朋友聚会祝酒词
2015/08/10 职场文书
教师理论学习心得体会
2016/01/21 职场文书
《七月的天山》教学反思
2016/02/19 职场文书
Python 类,对象,数据分类,函数参数传递详解
2021/09/25 Python
Redis中key的过期删除策略和内存淘汰机制
2022/04/12 Redis