深入出不来的nodejs

原创 年树先生 随笔 前端技术 13831阅读 22 天前 举报

事件绑定。这个东西贯穿了整个JS的学习过程,无论是刚开始的自己获取DOM手动绑,还是后期vue的直接@click,所有的交互都离不开这个东西。

同样,在node中,事件绑定也贯穿了整个框架。基本上大多数的内置模块以events为原型,下面的代码随处可见:

EventEmitter.call(this);

不同的是,页面上DOM的事件绑定是由浏览器来实现,触发也是一些操作'间接'触发,并不需要去主动emit对应事件,并且有冒泡和捕获这两特殊的性质。

深入出不来的nodejs

在node中,不存在dom,绑定的目标是一个对象(dom本质上也是对象),在内部node自己用纯JS实现了一个事件绑定与事件触发类。
首先看一下构造函数:

这里会调用一个init方法,this指向调用对象,初始化方法也很简单:

涉及的三个属性分别是:

1、_events => 一个挂载属性,空对象,负责收集所有类型的事件

2、_eventsCount => 记录目前绑定事件类型的数量

3、_maxListeners => 同类型事件listener数量限制

事件相关的主要操作有3个,依次来看。
绑定事件/on

虽然一般用的AP都是event.on,但是其实用addListener是一样的:

这个addListener跟DOM的addEventListener稍微有点不一样,前两个参数一致,分别代表类型、回调函数。

但是最后一个参数,这里代表的是否优先插入该事件,有一个方法就是做这个的:

最终都指向这个_addListener,分步解释:

这里首先会尝试获取指定对象的_events属性,即构造函数中初始化的挂载对象属性。

由于无论是任意构造函数中调用EventEmitter.call(this)或者new EventEmitter()都会在生成对象上挂载一个_events对象,所以这个判断暂时找不到反例。

当不存在就手动初始化一个,并添加一个记数属性重置为0。

当存在时,处理代码如下:

这个地方的注释主要讲的是,当绑定了type为newListener的事件时,每次都会触发一次这个事件,如果再次绑定该事件会出现递归问题。所以要判断是否存在newListener事件类型,如果有就先触发一次newListener事件。

先不管这个,最后会尝试获取指定类型的事件listener容器,下面就是对existing的处理。

这里的处理就能很清楚的看到events模块对于事件绑定的处理,_events相当于一个总对象,属性的key就是对应的事件类型type,而key对应的value就是对应的listener。只有一个时,就直接用该listener做值。重复绑定同类型的事件,这时值会转换为数组保存所有的listener。这里prepend就是之前的最后一个参数,允许函数插入到队列的前面,优先触发。

最后还有一个绑定事件的数量判断:

全栈开发交流群:864305860.png

一次绑定事件/once

有些时候希望事件只触发一次,原生的API目前不存在该功能,当初jquery也是封装了一个once方法,对应的这个events模块也有。

其实绑定的方法还是同一个,只是对应的listener变成了一个包装函数,来看看。

思路其实跟jquery的源码差不多,也是包装listener,当触发一次事件时,先解绑这个listener再触发事件。

需要注意的是,这里存在两个listener,一个是原生的,一个是包装后的。绑定的是包装的,所以解绑的第二个参数也要是包装的。其中原生的作为listener属性挂载到包装后的函数上,实际上触发包装listener后内部会隐式调用原生listener。

事件触发/emit

看完绑定,来看触发。

事件解绑/removeListener

同样分几步来看解绑的过程,首先是参数声明:

比较简单,每个参数的用处都很明显,错误判断后,下面有两种不同的情况。

当对应type的listener只有一个时:

两种情况,如果_eventsCount为0,即所有的type都被清完,会重置_events对象。

理论上来说,按照else分支的逻辑,当listener剩一个的时候都是直接delete对应的key,最后剩下的还是一个空对象,那这里的重重置似乎变得没有意义了。

我猜测估计是为了V8层面的优化,因为对象的属性在破坏性变动(添加属性、重复绑定同type事件导致函数变成函数数组)的时候,所需的内存会进行扩充,这个过程是不可逆的,就算最后只剩一个空壳对象,其实际占用也是相当大的。所以为了省空间,这里进行重置,用很小的空间初始化_events对象,原来的空间被回收。

当对应type的listener为多个时,就要遍历了。

原文出自:https://www.cnblogs.com/QH-Jimmy/p/9438769.html

本次给大家推荐一个免费的学习群,里面概括移动应用网站开发,css,html,webpack,vue node angular以及面试资源等。
对web开发技术感兴趣的同学,欢迎加入Q群:864305860,不管你是小白还是大牛我都欢迎,还有大牛整理的一套高效率学习路线和教程与您免费分享,同时每天更新视频资料。
最后,祝大家早日学有所成,拿到满意offer,快速升职加薪,走上人生巅峰。

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复