浅析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 相关文章推荐
jquery中$.post()方法的简单实例
Feb 04 Javascript
jquery单行文字向上滚动效果示例
Mar 06 Javascript
jQuery移除元素自动解绑事件实现思路及代码
May 31 Javascript
删除javascript中注释语句的正则表达式
Jun 11 Javascript
jquery序列化表单以及回调函数的使用示例
Jul 02 Javascript
JavaScript学习心得之概述
Jan 20 Javascript
jQuery使用fadein方法实现渐出效果实例
Mar 27 Javascript
js操作table元素实现表格行列新增、删除技巧总结
Nov 18 Javascript
关于AngularJS中ng-repeat不更新视图的解决方法
Sep 30 Javascript
微信小程序搭建自己的Https服务器
May 02 Javascript
微信小程序webview与h5通过postMessage实现实时通讯的实现
Aug 20 Javascript
vue利用全局导航守卫作登录后跳转到未登录前指定页面的实例代码
May 19 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
一个程序下载的管理程序(二)
2006/10/09 PHP
PHP异常处理浅析
2015/05/12 PHP
php基于openssl的rsa加密解密示例
2016/07/11 PHP
PHP GD库相关图像生成和处理函数小结
2016/09/30 PHP
用javascript获取textarea中的光标位置
2008/05/06 Javascript
checkbox全选/取消全选以及checkbox遍历jQuery实现代码
2009/12/02 Javascript
Extjs学习笔记之四 工具栏和菜单
2010/01/07 Javascript
JavaScript类型转换方法及需要注意的问题小结(挺全面)
2010/11/11 Javascript
jQuery.extend 函数及用法详细
2015/09/06 Javascript
基于javascript实现按圆形排列DIV元素(二)
2016/12/02 Javascript
微信小程序 欢迎页面的制作(源码下载)
2017/01/09 Javascript
使用vue.js实现checkbox的全选和多个的删除功能
2017/02/17 Javascript
Angular实现的自定义模糊查询、排序及三角箭头标注功能示例
2017/12/28 Javascript
vue 下列表侧滑操作实例代码详解
2018/07/24 Javascript
解决vue router组件状态刷新消失的问题
2018/08/01 Javascript
JavaScript实现页面中录音功能的方法
2019/06/04 Javascript
使用vue-router在Vue页面之间传递数据的方法
2019/07/15 Javascript
Node.js从字符串生成文件流的实现方法
2019/08/18 Javascript
python中stdout输出不缓存的设置方法
2014/05/29 Python
python实现TF-IDF算法解析
2018/01/02 Python
Python实现Kmeans聚类算法
2020/06/10 Python
Pandas 合并多个Dataframe(merge,concat)的方法
2018/06/08 Python
windows下 兼容Python2和Python3的解决方法
2018/12/05 Python
用Python逐行分析文件方法
2019/01/28 Python
详解python爬虫系列之初识爬虫
2019/04/06 Python
Python初学者常见错误详解
2019/07/02 Python
python实现PCA降维的示例详解
2020/02/24 Python
python 合并多个excel中同名的sheet
2021/01/22 Python
canvas 下载二维码和图片加水印的方法
2018/03/21 HTML / CSS
PUMA澳大利亚官方网站:德国运动品牌
2018/10/19 全球购物
英国电信商店:BT Shop
2019/12/17 全球购物
语文教学随笔感言
2014/02/18 职场文书
社会体育专业大学生职业生涯规划书
2014/09/17 职场文书
乡镇党建工作汇报材料
2014/10/27 职场文书
2016大学生暑期三下乡心得体会
2016/01/23 职场文书
Android studio 简单计算器的编写
2022/05/20 Java/Android