浅析JS中NEW的实现原理及重写


Posted in Javascript onFebruary 20, 2020

提到new,肯定会和类和实例联系起来,如:

function Func() {
 let x = 100;
 this.num = x +
}
let f = new Func();

上面的代码,我们首先创建了一个函数,如果是用面向对象的说法就是创建了一个Function类的实例,如果直接执行这个函数,那它就是一个普通的函数,如果用new执行,则这个函数被称为一个自定义的类。

如果是一个普通函数执行,他会如下做几件事:

·形成一个全新的执行上下文EC(Execution Context 执行环境)

·形成一个AO(Activation Object 活动对象)变量对象,初始化arguments和形参赋值

·初始化作用域链

·代码执行

如果是new函数执行,它既有普通函数执行的一面,也有自己独有的东西:

·默认创建一个对象,而这个对象就是当前类的实例

·声明其this指向,让其指向这个新创建的实例

·不论其是否写return,都会把新创建的实例返回,这里有个特殊点,如果用户自己返回内容,且返回的是一个引用类型值,则会把默认返回的实例给覆盖掉,此时返回的值就不再是类的实例了

console.log(f); //=>{num:200}
//f是Func这个类的实例 
//相当于给创建的实例对象新增一个num的属性 obj.num=200 (因为具备普通函数执行的一面,所以只有this.xxx=xxx才和创建的实例有关系,此案例中的x只是AO中的私有变量)
console.log(f instanceof Func); //=>TRUE instanceof用来检测某一个实例是否属于这个类

每一次new出来的都是一个新的实例对象

console.log(f === f2); //=>false

既然知道了new都做了什么事情,我们重新一下new:

/* 
 * 内置NEW的实现原理 
 * @params
 *  Func:操作的那个类
 *  ARGS:NEW类的时候传递的实参集合
 * @return
 *  实例或者自己返回的对象
 */
function _new(Func, ...args) {
  //默认创建一个实例对象(而且是属于当前这个类的一个实例)
  let obj = {};

  //也会把类当做普通函数执行
  //执行的时候要保证函数中的this指向创建的实例
  let result = Func.call(obj, ...args);

  //若客户自己返回引用值,则以自己返回的为主,否则返回创建的实例
  if ((result !== null && typeof result === "object") || (typeof result === "function")) {
    return result;
  }
  return obj;
}

我们试一下:

let f3 = _new(Func);
console.log(f3); // =>{num: 200}

我们继续测试:

Func.prototype.log = function () {
  console.log('ok');
}
let f4 = _new(Func);
f4.log(); //=>Uncaught TypeError: f4.log is not a function

也就是说,Func原型上的方法其实例没法调用,我们还需要修改:

/* 
 * 内置NEW的实现原理 
 * @params
 *  Func:操作的那个类
 *  ARGS:NEW类的时候传递的实参集合
 * @return
 *  实例或者自己返回的对象
 */
function _new(Func, ...args) {
  //默认创建一个实例对象(而且是属于当前这个类的一个实例)
  // let obj = {};
  let obj = Object.create(Func.prototype);

  //也会把类当做普通函数执行
  //执行的时候要保证函数中的this指向创建的实例
  let result = Func.call(obj, ...args);

  //若客户自己返回引用值,则以自己返回的为主,否则返回创建的实例
  if ((result !== null && typeof result === "object") || (typeof result === "function")) {
    return result;
  }
  return obj;
}

这样应该就可以了。

let f6 = _new(Func);
f6.log(); //=>ok

总结

以上所述是小编给大家介绍的JS中NEW的实现原理及重写,希望对大家有所帮助,也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
filemanage功能中用到的common.js
Apr 08 Javascript
动态添加js事件实现代码
Mar 12 Javascript
js 函数的执行环境和作用域链的深入解析
Nov 01 Javascript
几个比较实用的JavaScript 测试及效验工具
Apr 18 Javascript
js DOM的学习笔记
Dec 22 Javascript
jquery列表拖动排列(由项目提取相当好用)
Jun 17 Javascript
jquery插件bootstrapValidator数据验证详解
Nov 09 Javascript
JavaScript实现二分查找实例代码
Feb 22 Javascript
JavaScript实现打地鼠小游戏
Apr 23 Javascript
基于Vue实现平滑过渡的拖拽排序功能
Jun 12 Javascript
简单了解Javscript中兄弟ifream的方法调用
Jun 17 Javascript
浅谈es6中的元编程
Dec 01 Javascript
JS通过识别id、value值对checkbox设置选中状态
Feb 19 #Javascript
Javascript实现html转pdf高清版(提高分辨率)
Feb 19 #Javascript
Vue组件模板的几种书写形式(3种)
Feb 19 #Javascript
详解Vue 单文件组件的三种写法
Feb 19 #Javascript
vue中 v-for循环的用法详解
Feb 19 #Javascript
vue 使用v-for进行循环的实例代码详解
Feb 19 #Javascript
JS操作Fckeditor的一些常用方法(获取、插入等)
Feb 19 #Javascript
You might like
PHP中的日期及时间
2006/11/23 PHP
php 将bmp图片转为jpg等其他任意格式的图片
2009/06/29 PHP
WampServer搭建php环境时遇到的问题汇总
2015/07/23 PHP
关于php 高并发解决的一点思路
2017/04/16 PHP
JS实现浏览器菜单命令
2006/09/05 Javascript
关于可运行代码无法正常执行的使用说明
2010/05/13 Javascript
AJAX异步从优酷专辑中采集所有视频及信息(JavaScript代码)
2010/11/20 Javascript
JavaScript 创建运动框架的实现代码
2013/05/08 Javascript
JAVA四种基本排序方法实例总结
2015/07/24 Javascript
JS模拟键盘打字效果的方法
2015/08/05 Javascript
jQuery+json实现的简易Ajax调用实例
2015/12/14 Javascript
详解jQuery Mobile自定义标签
2016/01/06 Javascript
jQuery常见的选择器及用法介绍
2016/12/20 Javascript
AngularJS的依赖注入实例分析(使用module和injector)
2017/01/19 Javascript
JavaScript在控件上添加倒计时功能的实现代码
2017/07/04 Javascript
nodeJS(express4.x)+vue(vue-cli)构建前后端分离实例(带跨域)
2017/07/05 NodeJs
JavaScript Date对象应用实例分享
2017/10/30 Javascript
详解关于webpack多入口热加载很慢的原因
2019/04/24 Javascript
详解Vscode中使用Eslint终极配置大全
2019/11/08 Javascript
[02:56]DOTA2上海特锦赛小组赛解说FreeAgain采访花絮
2016/02/27 DOTA
将Python的Django框架与认证系统整合的方法
2015/07/24 Python
在Python的一段程序中如何使用多次事件循环详解
2017/09/07 Python
Python内存读写操作示例
2018/07/18 Python
Python常见MongoDB数据库操作实例总结
2018/07/24 Python
浅谈python中频繁的print到底能浪费多长时间
2020/02/21 Python
python实现将字符串中的数字提取出来然后求和
2020/04/02 Python
基于Python的图像阈值化分割(迭代法)
2020/11/20 Python
python分布式爬虫中消息队列知识点详解
2020/11/26 Python
德国旅行、体验和活动的预订平台:Watado
2019/12/04 全球购物
加拿大户外探险购物网站:SAIL
2020/06/27 全球购物
护士自我鉴定范文
2013/10/06 职场文书
金融专业毕业生推荐信
2013/11/26 职场文书
文体活动总结
2015/02/04 职场文书
关于召开会议的通知
2015/04/15 职场文书
道士塔读书笔记
2015/06/30 职场文书
学习师德师风的心得体会(2篇)
2019/10/08 职场文书