概述
本来是想着学学node.js试试的,后来发现node.js才是真正的js啊,它里面用到了很多我们平时没用过的js特性,而且还非常优雅,比如它里面的异步编程思想,总之,《深入浅出node.js》绝对值得一看。
下面是我的读书笔记。
单线程
单线程node有如下弱点:
- 无法利用多核CPU。
- 错误会引起整个应用退出(因为异步编程任何一个错误会导致事件循环失败),应用的健壮性值得考验。
- 大量计算占用CPU导致无法继续调用异步I/O。
- 不擅长处理CPU密集型业务。
对于1和2,node采用了与Web Workers相同的思路来解决单线程中大计算量的问题:child_process。通过把计算分发到各个子进程,可以将大量计算分解掉。这也解决了问题3,大量计算占用CPU的问题。
对于问题4,node可以通过编写C/C++扩展的方式更高效地利用CPU,甚至可以通过子进程的方式,将一部分node进程当做常驻服务进程用于计算,然后利用进程间的消息来传递结果。所以,CPU密集不可怕,如何合理调度是诀窍。
生态系统
- W3C: BOM,DOM
- 浏览器: BOM,DOM,ECMAScript
- CommonJS: FS,TCP,Stream,Buffer等等。
- Node: ECMAScript,FS,TCP,Stream,Buffer等等。
Node模块
1.Node中引入模块需要经历3个步骤:路径分析,文件定位,编译执行。
2.require()在分析标识符的过程中,会出现标识符不包含文件扩展名的情况,这种情况下,Node会按.js、.json、.node的次序补足扩展名,依次尝试。
3.require()在分析文件扩展名之后,可能会得到一个目录,这时Node会将目录当做一个包来处理。Node会在当前目录下查找package.json文件,通过JSON.parse()解析出包描述对象,从中取出main属性指定的文件名进行定位。
4.在node中用下面方式可以知道系统中已有的扩展加载方式:
console.log(require.extensions);
//{ '.js': [Function], '.json': [Function], '.node': [Function] }
5.Node会对获取的js文件内容进行头尾包装,如下所示。所以我们不能直接用exports来导出模块,而应该用module.exports把模块挂载到module下面。
//添加头部
(function(exports, require, module, __filename, __dirname) {
//文件内容开始
var math = require('math');
exports.area = function(radius) {
return Math.PI * radius * radius;
};
//文件内容结束
//添加尾部
});
6.js的一个典型弱点就是位运算,js的位运算是参照java的位运算实现的,但是java位运算是在int型数字的基础上进行的,而js中只有double型的数据类型,在进行位运算的过程中,需要将double型转换为int型,然后再进行。所以在js层面上做位运算的效率不高。
7.Node的原生模块一定程度上是可以跨平台的,在*nix
下通过gcc等编译为动态链接共享对象文件(.so),在Windows下则需要通过Visual C++的编译器编译为动态链接库文件(.dll)。
8.在gpy工具的帮助下,可以很简单的编译C/C++模块。
9.符合CommonJS规范的包目录应该包含如下这些文件:
package.json: 包描述文件。
bin: 用于存放可执行二进制文件的目录。
lib: 用于存放js代码的目录。
doc: 用于存放文档的目录。
test: 用于存放单元测试用例的代码。
10.利用下面的命令可以分析出当前路径下能够通过模块路径找到的所有包,并生成依赖树。
$ npm ls
11.AMD模块需要用define来明确定义一个模块,并需要利用return来返回内容。
12.能够兼容Node、AMD、CMD以及常见浏览器环境的代码:
;(function (name, definition) {
// 检测上?文环境是否为AMD?CMD
var hasDefine = typeof define === 'function',
// 检查上?文环境是否为Node
hasExports = typeof module !== 'undefined' && module.exports;
if (hasDefine) {
// AMD环境?CMD环境
define(definition);
} else if (hasExports) {
// 定义为?通Node模块
module.exports = definition();
} else {
// 将模块的执行结??在window?量中?在??器中this??window对象
this[name] = definition();
}
})('hello', function () {
var hello = function () {};
return hello;
});