详解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 相关文章推荐
网页图片延时加载的js代码
Apr 22 Javascript
js 文件引入实现代码
Apr 23 Javascript
jQuery学习笔记之jQuery的动画
Dec 22 Javascript
jQuery中jqGrid分页实现代码
Nov 04 Javascript
Javascript类定义语法,私有成员、受保护成员、静态成员等介绍
Dec 08 Javascript
zTree插件之多选下拉菜单实例代码
Nov 06 Javascript
javascript中验证大写字母、数字和中文
Jan 15 Javascript
了不起的node.js读书笔记之node的学习总结
Dec 22 Javascript
js实现漂浮回顶部按钮实例
May 06 Javascript
JS实现定时自动关闭DIV层提示框的方法
May 11 Javascript
react项目实践之webpack-dev-serve
Sep 14 Javascript
vue使用swiper实现中间大两边小的轮播图效果
Nov 24 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/12/08 PHP
ThinkPHP的Widget扩展实例
2014/06/19 PHP
php实现每天自动变换随机问候语的方法
2015/05/12 PHP
php数组分页实现方法
2016/04/30 PHP
ThinkPHP5.0框架使用build 自动生成模块操作示例
2019/04/11 PHP
HTML代码中标签的全部属性 中文注释说明
2009/03/26 Javascript
基于jquery的防止大图片撑破页面的实现代码(立即缩放)
2011/10/24 Javascript
js判断鼠标同时离开两个div的思路及代码
2013/05/31 Javascript
自己使用js/jquery写的一个定制对话框控件
2014/05/02 Javascript
express的中间件cookieParser详解
2014/12/04 Javascript
jQuery自动添加表单项的方法
2015/07/13 Javascript
vue-cli项目如何使用vue-resource获取本地的json数据(模拟服务端返回数据)
2017/08/04 Javascript
nodejs简单访问及操作mysql数据库的方法示例
2018/03/15 NodeJs
解决vue this.$forceUpdate() 处理页面刷新问题(v-for循环值刷新等)
2018/07/26 Javascript
layer.open 按钮的点击事件关闭方法
2018/08/17 Javascript
微信小程序搭建(mpvue+mpvue-weui+fly.js)的详细步骤
2018/09/18 Javascript
Node.js console控制台简单用法分析
2019/01/04 Javascript
JavaScript实现音乐导航效果
2020/11/19 Javascript
python使用装饰器和线程限制函数执行时间的方法
2015/04/18 Python
python发送告警邮件脚本
2018/09/17 Python
Python设计模式之工厂方法模式实例详解
2019/01/18 Python
python函数与方法的区别总结
2019/06/23 Python
centos7之Python3.74安装教程
2019/08/15 Python
Pytorch实现LSTM和GRU示例
2020/01/14 Python
英国第一的购买便宜玩具和游戏的在线购物网站:Bargain Max
2018/01/24 全球购物
Easy Spirit官网:美国休闲鞋履中的代表品牌
2019/04/12 全球购物
自我鉴定范文300字
2013/10/01 职场文书
自荐书模板
2013/12/15 职场文书
幼儿园中班教学反思
2014/02/10 职场文书
2015年个人自我剖析材料
2014/12/29 职场文书
寒假社会实践个人总结
2015/03/06 职场文书
学校通报表扬范文
2015/05/04 职场文书
金陵十三钗观后感
2015/06/04 职场文书
小学音乐课歌曲《堆雪人》教学反思
2016/02/18 职场文书
sql注入教程之类型以及提交注入
2021/08/02 MySQL
零基础学java之方法的定义与调用详解
2022/04/10 Java/Android