JavaScript 规范(ECMAScript)没有定义一套完善的能适用于大多数程序的标准库。CommonJS 提供了一套 JavaScript 标准库规范。Node 实现了 CommonJS 规范。HMsHTML5中文学习网 - HTML5先行者学习网
模块基础HMsHTML5中文学习网 - HTML5先行者学习网
在 Node 中,模块和文件是一一对应的。我们定义一个模块:HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网
// circle.jsHMsHTML5中文学习网 - HTML5先行者学习网
var PI = Math.PI;HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网
// 导出函数 areaHMsHTML5中文学习网 - HTML5先行者学习网
exports.area = function(r) {HMsHTML5中文学习网 - HTML5先行者学习网
return PI * r * r;HMsHTML5中文学习网 - HTML5先行者学习网
}HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网
// 导出函数 circumferenceHMsHTML5中文学习网 - HTML5先行者学习网
exports.circumference = function(r) {HMsHTML5中文学习网 - HTML5先行者学习网
return 2 * PI * r;HMsHTML5中文学习网 - HTML5先行者学习网
};HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网这里将需要导出的函数加入到 exports 对象。模块的局部变量外部无法访问(例如,上例中的 PI 变量)。调用 require 载入模块 circle.js:
HMsHTML5中文学习网 - HTML5先行者学习网HMsHTML5中文学习网 - HTML5先行者学习网
var circle = require('./circle.js');HMsHTML5中文学习网 - HTML5先行者学习网
console.log('The area of a circle of radius 4 is 'HMsHTML5中文学习网 - HTML5先行者学习网
+ circle.area(4));HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网附带提及一下的是,模块中,存在一个 module 对象,表示模块本身,exports 则为 module 的属性。
HMsHTML5中文学习网 - HTML5先行者学习网模块的加载HMsHTML5中文学习网 - HTML5先行者学习网
Node 会对加载过的模块进行缓冲,避免再次加载的开销:HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网
// test.jsHMsHTML5中文学习网 - HTML5先行者学习网
console.log("I'm here");HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网多次加载模块 test.jsHMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网
// 仅仅输出一次 "I'm here"HMsHTML5中文学习网 - HTML5先行者学习网
require('./test');HMsHTML5中文学习网 - HTML5先行者学习网
require('./test');HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网当加载文件没有后缀时,Node 会尝试添加后缀并加载:HMsHTML5中文学习网 - HTML5先行者学习网
1..js(JavaScript 源文件)HMsHTML5中文学习网 - HTML5先行者学习网
2..node(C/C++ 扩展模块)HMsHTML5中文学习网 - HTML5先行者学习网
3..json(JSON 文件)HMsHTML5中文学习网 - HTML5先行者学习网
模块主要有几类:HMsHTML5中文学习网 - HTML5先行者学习网
1.核心模块。核心模块已经被编译到了 Node 中,我们在其源码中的 lib 目录可以找到这些核心模块。常见的核心模块:net、http、fs 模块等HMsHTML5中文学习网 - HTML5先行者学习网
2.文件模块。文件模块通过一个相对或者绝对路径加载,例如我们上面看到的 circle.jsHMsHTML5中文学习网 - HTML5先行者学习网
3.自定义模块。自定义模块位于 node_modules 目录中,我们通过 npm 安装的各种模块就放置在 node_modules 目录中HMsHTML5中文学习网 - HTML5先行者学习网
核心模块总是优先被加载,假如有一个自定义模块 http,那么加载时仍然会加载核心模块 http 而非自定义模块 http。在加载自定义模块时,首先查找当前目录下的 node_modules 目录,而后查找父目录下的 node_modules 目录,以此类推,直到根目录。HMsHTML5中文学习网 - HTML5先行者学习网
require 加载的模块不是一个文件,而是一个目录时,这样的目录被叫做包(package)。包中存在一个名为 package.json 的文件(包描述文件),例如:HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网
{ "name" : "some-library",HMsHTML5中文学习网 - HTML5先行者学习网
"main" : "./lib/some-library.js" }HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网其中 main 指出需要被加载的模块。如果包中不存在 package.json 或者 package.json 中未指定 main 模块,那么 Node 将会尝试加载 index.js、index.node、index.json。HMsHTML5中文学习网 - HTML5先行者学习网
在加载 JavaScript 模块时,被加载的模块被包裹在一个函数中:HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网
function(module, exports, __filename, __dirname, ...) {HMsHTML5中文学习网 - HTML5先行者学习网
JavaScript moduleHMsHTML5中文学习网 - HTML5先行者学习网
}HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网每个 JavaScript 模块访问到的 module、exports、__filename、__dirname 等实际上是通过函数参数传递进来的。由于这种包裹,才使得模块的局部变量外部无法访问。但有时候也会出现让人难以理解的问题,例如:HMsHTML5中文学习网 - HTML5先行者学习网
test1.jsHMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网
exports = {HMsHTML5中文学习网 - HTML5先行者学习网
name: 'Name5566',HMsHTML5中文学习网 - HTML5先行者学习网
}HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网test2.jsHMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网
module.exports = {HMsHTML5中文学习网 - HTML5先行者学习网
name: 'Name5566',HMsHTML5中文学习网 - HTML5先行者学习网
}HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网加载这两个模块:HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网
var test1 = require('./test1.js');HMsHTML5中文学习网 - HTML5先行者学习网
console.log(test1.name); // undefinedHMsHTML5中文学习网 - HTML5先行者学习网
var test2 = require('./test2.js');HMsHTML5中文学习网 - HTML5先行者学习网
console.log(test2.name); // Name5566HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网exports 作为参数传递给模块,我们通过 exports.x 自然可以给 exports 对象添加属性(或方法),但直接给 exports 赋值(例如,exports = x)仅仅是改变了形参而非实参的值,因此:HMsHTML5中文学习网 - HTML5先行者学习网
1.为 exports 添加属性时,使用 exportsHMsHTML5中文学习网 - HTML5先行者学习网
2.为 exports 赋值时,使用 module.exportsHMsHTML5中文学习网 - HTML5先行者学习网
包HMsHTML5中文学习网 - HTML5先行者学习网
按 CommonJS 的规范,一个完整的包应该包含有:HMsHTML5中文学习网 - HTML5先行者学习网
1.package.json 包描述文件HMsHTML5中文学习网 - HTML5先行者学习网
2.bin 二进制文件目录HMsHTML5中文学习网 - HTML5先行者学习网
3.lib JavaScript 代码目录HMsHTML5中文学习网 - HTML5先行者学习网
4.doc 文档目录HMsHTML5中文学习网 - HTML5先行者学习网
5.test 测试代码目录HMsHTML5中文学习网 - HTML5先行者学习网
NPM 是一个 Node 的一个包管理工具。常见用法:HMsHTML5中文学习网 - HTML5先行者学习网
查看命令的文档:HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网
npm help installHMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网查看命令 install 的文档。HMsHTML5中文学习网 - HTML5先行者学习网
安装一个包:HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网
npm install redisHMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网安装 redis 这个包。install 命令会将包安装在当前目录下的 node_modules 目录中。
HMsHTML5中文学习网 - HTML5先行者学习网移除一个包:HMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网
npm remove redisHMsHTML5中文学习网 - HTML5先行者学习网
HMsHTML5中文学习网 - HTML5先行者学习网移除 redis 这个包。remove 命令会将当前目录下的包移除掉。
HMsHTML5中文学习网 - HTML5先行者学习网