Node.js 中文文档 modules
《Node.js 实战》
流程图工具 processon
Node 功能的组织及重用
用目录和单独的文件组织起来的代码找起来要比整个程序代码都放在一个长文件中找起来更容易。
重用的问题
在某些语言中,例如
PHP
和Ruby
,整合另一个文件(我们称之为“include
”文件)中的逻辑,可能意味着在被引入文件中执行的逻辑会影响全局作用域。
也就是说被引入文件常见的任何变量,以及声明的任何函数都可能会覆盖包含它的应用程序所创建的变量和声明的函数。
在
PHP
中可以使用命名空间避免这个问题,Ruby
通过模块也提供了类似的功能。
Node的重用
Node
的做法不会让开发者有机会在不经意间污染全局命名空间。
Node.js
有一个简单的模块加载系统。 在 Node.js
中,文件和模块是一一对应的(每个文件被视为一个独立的模块)。
Node
模块允许你从被引入文件中选择要暴露给程序的函数和变量。如果模块返回的函数或变量不值一个,那么它通过设定 exports
对象的属性来指明它们。如果模块只返回一个函数或变量,则可以设定 module.exports
属性。
exports
假设有一个名为 foo.js
的文件:
1 | //foo.js |
在第一行中,foo.js
加载了同一目录下的 circle.js
模块。
circle.js
文件的内容为:
1 | //circle.js |
circle.js
模块导出了 area()
和 circumference()
两个函数。 通过在特殊的 exports
对象上指定额外的属性,函数和对象可以被添加到模块的根部。
模块内的本地变量是私有的,因为模块被 Node.js
包装在一个函数中。
module.exports
如下,bar.js
会用到 square
模块,square
导出一个构造函数:
1 | const square = require('./square.js'); |
square 模块定义在 square.js 中:
1 | // 赋值给 `exports` 不会修改模块,必须使用 `module.exports` |
使用场景
如果只需要从模块中得到一个函数,那么从 require
中返回一个函数的代码要比返回一个对象的代码更优雅。
实例,以下是一个货币转换函数:
1 | //test-currency.js |
1 | //currency.js |
另一个实例,搜索二叉树。
用 node_modules重用模块
Node
中有一个独特的模块引入机制,可以不必知道模块在文件系统中具体位置,这个机制就是 node_modules
目录。
例如前面的 var Currency = require('./currency');
,不写 ./, node
会遵照几个规则来寻找这个模块。
用环境变量 NODE_PATH
可以改变 Node
模块的默认路径。
注意事项
如果模块式目录,在木块目录中定义模块文件必须被命名为
index.js
,除非你在这个目录下packjson.json
文件里特别指明。Node
能把模块作为对象缓存起来。如果程序中两个文件引入了相同模块,第一个文件会把模块返回的数据存到程序的内存中,这样第二个文件就不用再去访问和计算模块的源文件了。require
是Node
中少数几个同步I/O
操作,在I/O
密集的地方尽量不要用require
, 所有同步调动都会阻塞Node
,直到调用完成才能做其他事情。所以通常只在程序最初加载时才使用require
和其他同步操作。