浅析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模拟多线程
Feb 07 Javascript
使用AngularJS 应用访问 Android 手机的图片库
Mar 24 Javascript
JavaScript中的Math.LN2属性用法详解
Jun 12 Javascript
js获取新浪天气接口的实现代码
Jun 06 Javascript
获取input标签的所有属性的方法
Jun 28 Javascript
AngularJS中directive指令使用之事件绑定与指令交互用法示例
Nov 22 Javascript
jQuery-mobile事件监听与用法详解
Nov 23 Javascript
JS搜狐面试题分析
Dec 16 Javascript
Vue中计算属性computed的示例解读
Jul 26 Javascript
addeventlistener监听scroll跟touch(实例讲解)
Aug 04 Javascript
vue父组件给子组件的组件传值provide inject的方法
Oct 23 Javascript
jQuery HTML设置内容和属性操作实例分析
May 20 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
延长phpmyadmin登录时间的方法
2011/02/06 PHP
解析如何屏蔽php中的phpinfo()函数
2013/06/06 PHP
php异常处理方法实例汇总
2015/06/24 PHP
PHP实现模拟http请求的方法分析
2017/12/20 PHP
php操作mongodb封装类与用法实例
2018/09/01 PHP
PHP7 安装event扩展的实现方法
2019/10/08 PHP
7款风格新颖的jQuery/CSS3菜单导航分享
2013/04/23 Javascript
方便实用的jQuery checkbox复选框全选功能简单实例
2013/10/09 Javascript
JS清空多文本框、文本域示例代码
2014/02/24 Javascript
js获取图片宽高的方法
2015/11/25 Javascript
基于jquery编写分页插件
2016/03/07 Javascript
JS代码实现百度地图 画圆 删除标注
2016/10/12 Javascript
angular实现form验证实例代码
2017/01/17 Javascript
Vue2路由动画效果的实现代码
2017/07/10 Javascript
react-redux中connect的装饰器用法@connect详解
2018/01/13 Javascript
AngularJS 事件发布机制
2018/08/28 Javascript
node使用Mongoose类库实现简单的增删改查
2018/11/08 Javascript
关于vue利用postcss-pxtorem进行移动端适配的问题
2019/11/20 Javascript
element表格翻页第2页从1开始编号(后端从0开始分页)
2019/12/10 Javascript
uni-app 自定义底部导航栏的实现
2020/12/11 Javascript
[03:48]显微镜下的DOTA2第四期——TP动作
2014/06/20 DOTA
python判断字符串是否是json格式方法分享
2017/11/07 Python
使用python3+xlrd解析Excel的实例
2018/05/04 Python
解决python爬虫中有中文的url问题
2018/05/11 Python
解决python通过cx_Oracle模块连接Oracle乱码的问题
2018/10/18 Python
解决pyttsx3无法封装的问题
2018/12/24 Python
python爬取百度贴吧前1000页内容(requests库面向对象思想实现)
2019/08/10 Python
Python的PIL库中getpixel方法的使用
2020/04/09 Python
详解用 python-docx 创建浮动图片
2021/01/24 Python
HTML5 DeviceOrientation实现手机网站摇一摇功能代码实例
2015/04/24 HTML / CSS
美国市场上最实惠的送餐服务:Dinnerly
2018/03/18 全球购物
关于雷锋的演讲稿
2014/05/10 职场文书
保险公司演讲稿
2014/09/02 职场文书
教师节座谈会主持词
2015/07/03 职场文书
2019旅游导游工作总结
2019/06/27 职场文书
Docker下安装Oracle19c
2022/04/13 Servers