深入浅出nodejs
Commonjs
每个模块都有 require exports module __filename __dirname变量
事实上,在编译的过程中,Node对获取的JavaScript文件内容进行头尾包装。 头部 (function (exports, require, module, __filename, __dirname) {, 尾部 });
(function (exports,require, module,__filename,__dirname){ |
此外,许多初学者都曾经纠结过为何存在exports的情况下,还存在module.exports。理想情 况下,只要赋值给exports即可: 但是通常都会得到一个失败的结果。其原因在于,exports对象是通过形参的方式传入的, 直接赋值形参会改变形参的引用,但并不能改变作用域外的值。测试代码如下: 如果要达到require引入一个类的效果,请赋值给module.exports对象。这个迁回的方案不改 变形参的引用。
轮巡
- read
- select 1024 数组
- poll 链表
- epoll 事件和回调
事件循环
setTimeout()和setInterval()与浏览器中的API是一致的,分别用于单次和多次定时执行任务。它们的实现原理与异步1/0比较类似,只是不需要1/0线程池的参与。调用setTimeout()或者setInterval()创建的定时器会被插入到定时器观察者内部的一个红黑树中。每次Tick执行时,会从该红黑树中迭代取出定时器对象,检查是否超过定时时间,如果超过,就形成一个事件,它的回调函数将立即执行。 因此不能完全信任setTimeout()和setInterval()
nexttick(), setImmeidate()
Node在处理异常上形成了一种约定,将异常作为回调函数的第一个实参传回,如果为空值, 则表明异步调用没有异常抛出:
nodejs 事件, 订阅者发布者模式 Promise/Deferred模式? 中间件 next async parallel() waterfall() step 库 eval()
v8 垃圾回收
在V8中,所有的JavaScript对象都是通过堆来进行分配的。 主要将内存分新生代和老生代两代。
在分代的基础上,新生代中的对象主要通过Scavenge算法进行垃圾回收。在Scavenge的具体实现中,主要采用了Cheney算法, 先是在From空间中进行分配。当开始进行垃圾回收时,会检查From空间中的存活对象,这些存活对象将被复制到To空间中,而非存活对象占用的空间将会被释放。
V8在老生代中主要采用了Mark-Sweep和Mark-Compact相结合的方式进行垃圾回收。 Mark-Sweep是标记清除的意思,它分标记和清除两个阶段。Mark-Sweep在标记阶段遍历堆中的所有对象,并标记活着的对象,在随后的清除阶段中,只清除没有被标记的对象。 没有被标记的对象。
Mark-Compact是在Mark-Sweep的基础上演变而来的。它们的差别在于对象在标记死亡后,在整理的过程中,将活着的对象往一端移动,移动完成后,直接清理掉边界外的内存。
所以在取舍上,V8主要使用Mark-Sweep,在空间不足以对从新生代中晋升过来的对象进行分配时才使用Mark-Compact。