详解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 27 Javascript
JS仿百度搜索自动提示框匹配查询功能
Nov 21 Javascript
window.location.href的用法(动态输出跳转)
Aug 09 Javascript
JQuery判断radio是否选中并获取选中值的示例代码
Oct 17 Javascript
超精准的javascript验证身份证号的具体实现方法
Nov 18 Javascript
jQuery插件Validation快速完成表单验证的方式
Jul 28 Javascript
纯JS实现弹性导航条效果
Mar 06 Javascript
JS验证input输入框(字母,数字,符号,中文)
Mar 23 Javascript
VsCode插件整理(小结)
Sep 14 Javascript
jQuery实现图片上传预览效果功能完整实例【测试可用】
May 28 jQuery
vue+element实现打印页面功能
May 20 Javascript
vue组件冲突之引用另一个组件出现组件不显示的问题
Apr 13 Vue.js
我所理解的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 fputcsv命令 写csv文件遇到的小问题(多维数组连接符)
2011/05/24 PHP
thinkphp验证码显示不出来的解决方法
2014/03/29 PHP
利用PHP判断是手机移动端还是PC端访问的函数示例
2017/12/14 PHP
PHP 图片合成、仿微信群头像的方法示例
2019/10/25 PHP
JavaScript类和继承 this属性使用说明
2010/09/03 Javascript
js模拟点击事件实现代码
2012/11/06 Javascript
thinkphp 表名 大小写 窍门
2015/02/01 Javascript
JavaScript Date对象详解
2016/03/01 Javascript
JS构造函数与原型prototype的区别介绍
2016/07/04 Javascript
webpack+vue.js快速入门教程
2016/10/12 Javascript
零基础轻松学JavaScript闭包
2016/12/30 Javascript
jquery将标签元素的高设为屏幕的百分比
2017/04/19 jQuery
JS实现延迟隐藏功能的方法(类似QQ头像鼠标放上展示信息)
2017/12/28 Javascript
JavaScript中使用import 和require打包后实现原理分析
2018/03/07 Javascript
electron-vue开发环境内存泄漏问题汇总
2019/10/10 Javascript
JavaScript数组排序小程序实现解析
2020/01/13 Javascript
Angular短信模板校验代码
2020/09/23 Javascript
Python2.7编程中SQLite3基本操作方法示例
2017/08/09 Python
浅谈python中requests模块导入的问题
2018/05/18 Python
解决python明明pip安装成功却找不到包的问题
2019/08/28 Python
pytorch 自定义参数不更新方式
2020/01/06 Python
python 画条形图(柱状图)实例
2020/04/24 Python
用Python实现职工信息管理系统
2020/12/30 Python
Python实现一个论文下载器的过程
2021/01/18 Python
html5本地存储 localStorage操作使用详解
2016/09/20 HTML / CSS
大学校庆策划书
2014/01/31 职场文书
公司员工检讨书
2014/02/08 职场文书
个人委托书格式
2014/04/04 职场文书
2014年志愿者工作总结
2014/11/20 职场文书
幼儿园园长个人总结
2015/03/02 职场文书
忠诚与背叛观后感
2015/06/04 职场文书
《活见鬼》教学反思
2016/02/24 职场文书
晚会开幕词范文
2016/03/04 职场文书
商业计划书之服装
2019/09/09 职场文书
七年级作文之雪景
2019/11/18 职场文书
php修改word的实例方法
2021/11/17 PHP