1. node 的特点
特点: 事件驱动、异步I/O、单线程。
应用场景: 在处理异步I/O密集、CPU密集场景性能优势明显。
I/O密集的优势:主要在于node利用事件循环的处理能力,而不是启动每一个线程为每一个请求服务,资源占用极少。
事件循环:TODO
CPU密集型业务:node优秀的运算能力主要来自V8的深度性能优化。但是由于js单线程,需要适当调整和分解大型运算任务为多个小任务,使得运算能够适时释放,不阻塞I/O调用的发起。
- node 子进程:child_process
- html5 创建工作线程: Web Works
2. node 的模块机制
- CommonJS:模块引用、模块定义和模块标识3个部分
- 模块引用:
var math = require('math');
- 模块定义:在模块中,存在一个module对象,代表模块自身,而exports是module的属性。
- 模块标识:即传递给require()方法的参数,必须符合小驼峰命名的字符串,或者相对/绝对路径。
- 模块引用:
- 模块实现
node模块分为两类:核心模块(Node提供的模块)、文件模块(用户编写的模块)
核心模块: 部分在Node 源码编译过程中,编译进二进制执行文件。在node进程启动时,部分核心模块就直接被加载进内存中。
文件模块:运行时动态加载,需要完整的路径分析、文件定位、编译执行过程。
- 文件定位:require() 中不包含文件拓展名的情况下,会按.js、.json、.node的次序补足拓展名(因为node是单线程,所以调用fs模块同步阻塞式地判断文件是否存在会引起性能问题,带上拓展名会加快一点速度)
- js模块编译
- node对获取的JavaScript文件内容进行了头尾包装,如下所示:
(function(exports, require, module, __filename, __dirname) { 文件内容 })
这样每个模块文件都进行了作用域隔离,返回一个具体的function对象,exports
只能使用.语法向外暴露内部变量, 例 exports.test = 100;module.exports
既可以通过点语法,也可以直接赋值一个对象 例 module.exports.test = 100; module.exports = { test: 100}
原因:exports
: 对象是通过形参的方式传入的,直接赋值形参会改变形参的应用,但不能改变作用域外的值。
同理:
CommonJS、AMD、CMD、ES6 模块规范讲解
- 核心模块
核心模块分为C/C++编写的和JavaScript编写的两部分,其中C/C++文件存放在Node项目的src目录下,JavaScript文件存放在lib目录下。