浅析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 相关文章推荐
创建一个复制UBB软件信息的链接或按钮的js代码
Jan 06 Javascript
javascript OFFICE控件测试代码
Dec 08 Javascript
Uglifyjs(JS代码优化工具)入门 安装使用
Apr 13 Javascript
在浏览器窗口上添加遮罩层的方法
Nov 12 Javascript
JS复制内容到剪切板的实例代码(兼容IE与火狐)
Nov 19 Javascript
使用JavaScript刷新网页的方法
Jun 04 Javascript
ExtJs动态生成treepanel的Json格式
Jul 19 Javascript
js+html5操作sqlite数据库的方法
Feb 02 Javascript
AngularJS深入探讨scope,继承结构,事件系统和生命周期
Nov 02 Javascript
AngularJs实现聊天列表实时刷新功能
Jun 15 Javascript
通过JavaScript下载文件到本地的方法(单文件)
Mar 17 Javascript
jQuery插件实现图片轮播效果
Oct 19 jQuery
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
比特率,大家看看这个就不用收音机音质去比MP3音质了
2021/03/01 无线电
PHP调用三种数据库的方法(3)
2006/10/09 PHP
PHP获取客户端真实IP地址的5种情况分析和实现代码
2014/07/08 PHP
jquery获取css中的选择器(实例讲解)
2013/12/02 Javascript
捕获和分析JavaScript Error的方法
2014/03/25 Javascript
Javascript检查图片大小不要让大图片撑破页面
2014/11/04 Javascript
JS实现日期时间动态显示的方法
2015/12/07 Javascript
js与jquery分别实现tab标签页功能的方法
2016/11/18 Javascript
Angular 2.x学习教程之结构指令详解
2017/05/25 Javascript
AngularJS中ng-class用法实例分析
2017/07/06 Javascript
微信小程序之绑定点击事件实例详解
2017/07/07 Javascript
jQuery EasyUI的TreeGrid查询功能实现方法
2017/08/08 jQuery
详解layui中的树形关于取值传值问题
2018/01/16 Javascript
微信小程序scroll-view组件实现滚动动画
2018/01/31 Javascript
JavaScript JMap类定义与使用方法示例
2019/01/22 Javascript
js form表单input框限制20个字符,10个汉字代码实例
2019/04/12 Javascript
python BeautifulSoup使用方法详解
2013/11/21 Python
举例讲解Python的lambda语句声明匿名函数的用法
2016/07/01 Python
django ORM之values和annotate使用详解
2020/05/19 Python
Python单元测试及unittest框架用法实例解析
2020/07/09 Python
python一些性能分析的技巧
2020/08/30 Python
多个版本的python共存时使用pip的正确做法
2020/10/26 Python
利用python制作拼图小游戏的全过程
2020/12/04 Python
html5音频_动力节点Java学院整理
2018/08/22 HTML / CSS
Michael Kors美国官网:美式奢侈生活风格的代表
2016/11/25 全球购物
美国复古街头服饰精品店:Need Supply Co.
2017/02/22 全球购物
英国最大的化装舞会服装网站:Fancydress.com
2017/08/15 全球购物
台湾网购生鲜第一品牌:i3Fresh爱上新鲜
2017/10/26 全球购物
澳大利亚香水在线:Price Rite Mart
2017/12/28 全球购物
英国豪华文具和皮具配件经典老品牌:Smythson(斯迈森)
2018/04/19 全球购物
this关键字的作用
2016/01/30 面试题
企业管理部经理岗位职责
2013/12/24 职场文书
六年级语文下册教学计划
2015/01/22 职场文书
2015年学校党支部工作总结
2015/04/01 职场文书
2015年街道办事处工作总结
2015/05/22 职场文书
付款证明格式范文
2015/06/19 职场文书