JS require 命令
作用
读入并执行一个 JavaScript 文件,然后返回该模块的 exports 属性 Node 使用 CommonJS 模块规范,内置的 require 命令用于加载模块文件。
// example.js
var invisible = function () {
console.log("invisible")
}
exports.message = "hi"
exports.say = function () {
console.log(message)
}
var example = require('./example.js')
example
// {
// message: "hi",
// say: [Function]
// }
加载规则
require 命令用于加载文件,后缀名默认为.js。
var foo = require('foo')
// 等同于
var foo = require('foo.js')
根据参数的不同格式,require 命令去不同路径寻找模块文件。
- 如果参数字符串以
/
开头,则表示加载的是一个位于绝对路径的模块文件。比如,require('/home/marco/foo.js')
将加载/home/marco/foo.js
。 - 如果参数字符串以
./
开头,则表示加载的是一个位于相对路径(跟当前执行脚本的位置相比)的模块文件。比如,require('./circle')
将加载当前脚本同一目录的 circle.js。 - 如果参数字符串不以
./
或/
开头,则表示加载的是一个默认提供的核心模块(位于 Node 的系统安装目录中),或者一个位于各级 node_modules 目录的已安装模块(全局安装或局部安装)。
/home/user/projects/foo.js 执行了 require('bar.js') 命令,Node 会依次搜索以下文件。 /usr/local/lib/node/bar.js (核心)
/home/user/projects/node_modules/bar.js (当前目录 node_modules)
/home/user/node_modules/bar.js (上级目录 node_modules)
/home/node_modules/bar.js (上上级目录 node_modules)
/node_modules/bar.js (上上上级目录 node_modules)
- 如果参数字符串不以“./“或”/“开头,而且是一个路径,比如
require('example-module/path/to/file')
,则将先找到 example-module 的位置,然后再以它为参数,找到后续路径。 - 如果指定的模块文件没有发现,Node 会尝试为文件名添加.js、.json、.node 后,再去搜索。.js 件会以文本格式的 JavaScript 脚本文件解析,.json 文件会以 JSON 格式的文本文件解析,.node 文件会以编译后的二进制文件解析。
- 如果想得到 require 命令加载的确切文件名,使用 require.resolve() 方法。
目录的加载规则
通常,我们会把相关的文件会放在一个目录里面,便于组织。这时,最好为该目录设置一个入口文件,让 require 方法可以通过这个入口文件,加载整个目录。
在目录中放置一个 package.json 文件,并且将入口文件写入 main 字段。
// package.json
{
"name" : "some-library",
"main" : "./lib/some-library.js"
}
require 发现参数字符串指向一个目录以后,会自动查看该目录的 package.json 文件,然后加载 main 字段指定的入口文件。
如果 package.json 文件没有 main 字段,或者根本就没有 package.json 文件,则会加载该目录下的 index.js 文件或 index.node 文件。
模块的缓存
第一次加载某个模块时,Node 会缓存该模块。以后再加载该模块,就直接从缓存取出该模块的 module.exports 属性。
require('./example.js')
require('./example.js').message = "hello"
require('./example.js').message //并没有重新获取 example.js
// "hello"
如果想要多次执行某个模块,可以让该模块输出一个函数,然后每次 require 这个模块的时候,重新执行一下输出的函数。
删除缓存
所有缓存的模块保存在 require.cache 之中
// 删除指定模块的缓存
delete require.cache[moduleName]
// 删除所有模块的缓存
Object.keys(require.cache).forEach(function(key) {
delete require.cache[key]
})
缓存是根据绝对路径识别模块的,如果同样的模块名,但是保存在不同的路径,require 命令还是会重新加载该模块。
环境变量 NODE_PATH
Node 执行一个脚本时,会先查看环境变量 NODE_PATH
它是一组以冒号分隔的绝对路径。在其他位置找不到指定模块时,Node 会去这些路径查找。(上面不是说优先来这里找么?)
可以将 NODE_PATH 添加到.bashrc。
export NODE_PATH="/usr/local/lib/node"
如果遇到复杂的相对路径
var myModule = require('../../../../lib/myModule')
一是将该文件加入 node_modules 目录
二是修改 NODE_PATH 环境变量,package.json 文件可以采用下面的写法。
{
"name": "node_path",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "NODE_PATH=lib node index.js"
},
"author": "",
"license": "ISC"
}
模块的循环加载
如果发生模块的循环加载,即 A 加载 B,B 又加载 A,则 B 将加载 A 的不完整版本。
// a.js
exports.x = 'a1'
console.log('a.js ', require('./b.js').x)
exports.x = 'a2'
// b.js
exports.x = 'b1'
console.log('b.js ', require('./a.js').x)
exports.x = 'b2'
// main.js
console.log('main.js ', require('./a.js').x)
console.log('main.js ', require('./b.js').x)
$ node main.js
b.js a1
a.js b2
main.js a2
main.js b2
// 修改 main.js
console.log('main.js ', require('./a.js').x)
console.log('main.js ', require('./b.js').x)
console.log('main.js ', require('./a.js').x)
console.log('main.js ', require('./b.js').x)
$ node main.js
b.js a1
a.js b2
main.js a2
main.js b2
main.js a2 //缓存中读取
main.js b2 //缓存中读取
require.main
用来判断模块是直接执行,还是被调用执行 直接执行的时候(node module.js),require.main 属性指向模块本身。
require.main === module
// true
调用执行的时候(通过 require 加载该脚本执行),上面的表达式返回 false。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
下一篇: TypeScript 常见问题
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论