查看“Node.js:模块系统”的源代码
←
Node.js:模块系统
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
[[category:Node.js教程]] == 关于 == <pre> 为了让 Node.js 的文件可以相互调用,Node.js 提供了一个简单的模块系统。 </pre> '''模块'''(module)是 Node.js 应用程序的基本组成部分,'''文件和模块是一一对应的'''。 : 换言之,'''一个 Node.js 文件就是一个模块''',这个文件可能是 JavaScript 代码、JSON 或者编译过的C/C++ 扩展。 === 引入模块:exports require === Node.js 提供了两个对象: # '''exports''' 是模块公开的接口,(一个模块可不可以有多个接口?) # '''require''' 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。 示例: # 创建 hello.js 文件: #: <syntaxhighlight lang="JavaScript" highlight=""> exports.world = function() { console.log('Hello World'); } </syntaxhighlight> # 创建一个 main.js 文件并引入 hello 模块: #: <syntaxhighlight lang="JavaScript" highlight=""> var hello = require('./hello'); hello.world(); </syntaxhighlight> 在以上示例中,hello.js 通过 exports 对象把 world 作为模块的访问接口,在 main.js 中通过 require('./hello') 加载这个模块,然后就可以直接访 问 hello.js 中 exports 对象的成员函数了。 * '''node.js 默认后缀为 js'''; === module.exports === 有时候我们只是想把一个对象封装到模块中,格式如下: <syntaxhighlight lang="JavaScript" highlight=""> module.exports = function() { // ... } </syntaxhighlight> 示例: # 创建 hello.js 文件: #: <syntaxhighlight lang="JavaScript" highlight="11"> // hello.js function Hello() { var name; this.setName = function(thyName) { name = thyName; }; this.sayHello = function() { console.log('Hello ' + name); }; }; module.exports = Hello; </syntaxhighlight> # 获得这个对象: #: <syntaxhighlight lang="JavaScript" highlight=""> //main.js var Hello = require('./hello'); hello = new Hello(); hello.setName('BYVoid'); hello.sayHello(); </syntaxhighlight> 模块接口的唯一变化是使用 module.exports = Hello 代替了 exports.world = function(){}:在外部引用该模块时,其接口对象就是要输出的 Hello 对象本身,而不是原先的 exports。 === exports 和 module.exports 的使用 === 如果要对外: # '''暴露属性或方法''',使用 exports; # '''暴露对象'''(类似class,包含了很多属性和方法),使用 module.exports。 '''不建议同时使用 exports 和 module.exports''': : 如果先使用 exports 对外暴露属性或方法,再使用 module.exports 暴露对象,会使得 exports 上暴露的属性或者方法失效。 * 原因在于:'''exports 仅仅是 module.exports 的一个引用''': <syntaxhighlight lang="JavaScript" highlight=""> function require(...){ var module = {exports: {}}; ((module, exports) => { function myfn () {} // 这个myfn就是我们自己的代码 exports.myfn = myfn; // 这里是在原本的对象上添加了一个myfn方法。 module.exports = myfn;// 这个直接把当初的对象进行覆盖。 })(module,module.exports) return module.exports; } </syntaxhighlight> == 服务端的模块放在哪里 == Node.js 中自带了一个叫做 '''http''' 的模块,我们在代码中请求它并把返回值赋给一个本地变量: <syntaxhighlight lang="JavaScript" highlight=""> var http = require("http"); ... http.createServer(...); </syntaxhighlight> 这把我们的本地变量变成了一个拥有所有 http 模块所提供的公共方法的对象。 Node.js 的 require 方法中的'''文件查找策略'''如下: : [[File:Node.js:文件查找策略.png|400px]] * 尽管 require 方法极其简单,但由于 Node.js 中存在 4 类模块('''原生模块''' 和 '''3 种文件模块'''),所以内部的加载却是十分复杂的,其加载优先级也各自不同。 === 从“文件模块缓存”中加载 === 尽管原生模块与文件模块的优先级不同,但是都会'''优先从文件模块的缓存中加载已经存在的模块'''。 === 从“原生模块”加载 === 原生模块的优先级仅次于文件模块缓存的优先级。 : require 方法在解析文件名之后,优先检查模块是否在原生模块列表中。 以 http 模块为例,尽管在目录下存在一个 http/http.js/http.node/http.json 文件,require("http") 都不会从这些文件中加载,而是从原生模块中加载。 * 原生模块也有一个缓存区,同样也是优先从缓存区加载。如果缓存区没有被加载过,则调用原生模块的加载方式进行加载和执行。 === 从“文件”加载 === 当文件模块缓存中不存在,而且不是原生模块的时候,Node.js 会解析 require 方法传入的参数,并从文件系统中加载实际的文件。 require 方法接受以下几种参数的传递: * http、fs、path 等,原生模块。 * ./mod 或 ../mod,相对路径的文件模块。 * /pathtomodule/mod,绝对路径的文件模块。 * mod,非原生模块的文件模块。 在路径 Y 下执行 require(X) 语句执行顺序: <syntaxhighlight lang="bash" highlight=""> 1. 如果 X 是内置模块 a. 返回内置模块 b. 停止执行 2. 如果 X 以 '/' 开头 a. 设置 Y 为文件根路径 3. 如果 X 以 './' 或 '/' or '../' 开头 a. LOAD_AS_FILE(Y + X) b. LOAD_AS_DIRECTORY(Y + X) 4. LOAD_NODE_MODULES(X, dirname(Y)) 5. 抛出异常 "not found" LOAD_AS_FILE(X) 1. 如果 X 是一个文件, 将 X 作为 JavaScript 【文本】载入并停止执行。 2. 如果 X.js 是一个文件, 将 X.js 作为 JavaScript 【文本】载入并停止执行。 3. 如果 X.json 是一个文件, 解析 X.json 为 JavaScript 【对象】并停止执行。 4. 如果 X.node 是一个文件, 将 X.node 作为【二进制插件】载入并停止执行。 LOAD_AS_DIRECTORY(X) 1. 如果 X/package.json 是一个文件, a. 解析 X/package.json, 并查找 "main" 字段。 b. let M = X + (json main 字段) c. LOAD_AS_FILE(M) d. LOAD_INDEX(M) 2. LOAD_INDEX(X) LOAD_INDEX(X) 1. 如果 X/index.js 是一个文件, 将 X/index.js 作为 JavaScript 文本载入并停止执行。 2. 如果 X/index.json 是一个文件, 解析 X/index.json 为 JavaScript 对象并停止执行。 3. 如果 X/index.node 是一个文件, 将 X/index.node 作为二进制插件载入并停止执行。 LOAD_NODE_MODULES(X, START) 1. let DIRS=NODE_MODULES_PATHS(START) 2. for each DIR in DIRS: a. LOAD_AS_FILE(DIR/X) b. LOAD_AS_DIRECTORY(DIR/X) NODE_MODULES_PATHS(START) 1. let PARTS = path split(START) 2. let I = count of PARTS - 1 3. let DIRS = [] 4. while I >= 0, a. if PARTS[I] = "node_modules" CONTINUE b. DIR = path join(PARTS[0 .. I] + "node_modules") c. DIRS = DIRS + DIR d. let I = I - 1 5. return DIRS </syntaxhighlight>
返回至“
Node.js:模块系统
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
大陆简体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
笔记
服务器
数据库
后端
前端
工具
《To do list》
日常
阅读
电影
摄影
其他
Software
Windows
WIKIOE
所有分类
所有页面
侧边栏
站点日志
工具
链入页面
相关更改
特殊页面
页面信息