浅析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 相关文章推荐
用js解决数字不能换行问题
Aug 10 Javascript
基于jquery点击自以外任意处,关闭自身的代码
Feb 10 Javascript
jquery 插件学习(五)
Aug 06 Javascript
javascript时间自动刷新实现原理与步骤
Jan 06 Javascript
jquery 页面滚动到指定DIV实现代码
Sep 25 Javascript
全面解析bootstrap格子布局
May 22 Javascript
JS在onclientclick里如何控制onclick的执行
May 30 Javascript
JavaScript实现点击文本自动定位到下拉框选中操作
Jun 15 Javascript
JSON字符串和对象相互转换实例分析
Jun 16 Javascript
javascript循环链表之约瑟夫环的实现方法
Jan 16 Javascript
JavaScript实现与使用发布/订阅模式详解
Jan 19 Javascript
在layui下对元素进行事件绑定的实例
Sep 06 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
yii框架源码分析之创建controller代码
2011/06/28 PHP
centos+php+coreseek+sphinx+mysql之一coreseek安装篇
2016/10/25 PHP
YII2自动登录Cookie总是失效的解决方法
2017/06/28 PHP
js 分栏效果实现代码
2009/08/29 Javascript
js 学习笔记(三)
2009/12/29 Javascript
js中获取事件对象的方法小结
2011/03/13 Javascript
js将long日期格式转换为标准日期格式实现思路
2013/04/07 Javascript
Jquery实现点击按钮,连续地向textarea中添加值的实例代码
2014/03/08 Javascript
深入理解JavaScript系列(44):设计模式之桥接模式详解
2015/03/04 Javascript
jQuery时间轴插件使用详解
2015/07/16 Javascript
javascript基本语法
2016/05/31 Javascript
JavaScript6 let 新语法优势介绍
2016/07/15 Javascript
微信小程序 触控事件详细介绍
2016/10/17 Javascript
vue组件实例解析
2017/01/10 Javascript
JS及JQuery对Html内容编码,Html转义
2017/02/17 Javascript
jquery 手势密码插件
2017/03/17 Javascript
JavaScript使用indexOf()实现数组去重的方法分析
2018/09/04 Javascript
深入学习js函数的隐式参数 arguments 和 this
2019/06/24 Javascript
[47:31]完美世界DOTA2联赛PWL S3 INK ICE vs DLG 第一场 12.12
2020/12/16 DOTA
Python实现Windows上气泡提醒效果的方法
2015/06/03 Python
python解决网站的反爬虫策略总结
2016/10/26 Python
Python基础练习之用户登录实现代码分享
2017/11/08 Python
Python中单、双下划线的区别总结
2017/12/01 Python
基于Python3.6+splinter实现自动抢火车票
2018/09/25 Python
Python进程,多进程,获取进程id,给子进程传递参数操作示例
2019/10/11 Python
python入门之井字棋小游戏
2020/03/05 Python
在Python中用GDAL实现矢量对栅格的切割实例
2020/03/11 Python
学会python自动收发邮件 代替你问候女友
2020/05/20 Python
python中数字是否为可变类型
2020/07/08 Python
ProBikeKit英国:在线公路自行车之家
2017/02/10 全球购物
澳大利亚运动鞋零售商:The Athlete’s Foot
2018/11/04 全球购物
澳大利亚最受欢迎的美发用品目的地:AMR
2019/08/28 全球购物
俄罗斯园林植物网上商店:Garshinka
2020/07/16 全球购物
2015年毕业实习工作总结
2014/12/12 职场文书
Golang 实现获取当前函数名称和文件行号等操作
2021/05/08 Golang
Django框架中视图的用法
2022/06/10 Python