JS require 命令

发布于 2024-10-27 07:18:18 字数 4603 浏览 4 评论 0

作用

读入并执行一个 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 命令去不同路径寻找模块文件。

  1. 如果参数字符串以 / ​开头,则表示加载的是一个位于绝对路径的模块文件。比如, require('/home/marco/foo.js') ​ 将加载 /home/marco/foo.js ​。
  2. 如果参数字符串以 ./ ​开头,则表示加载的是一个位于相对路径(跟当前执行脚本的位置相比)的模块文件。比如, require('./circle') ​将加载当前脚本同一目录的 circle.js。
  3. 如果参数字符串不以 ./ ​或 / ​开头,则表示加载的是一个默认提供的核心模块(位于 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)

  1. 如果参数字符串不以“./“或”/“开头,而且是一个路径,比如 require('example-module/path/to/file') ​,则将先找到 example-module 的位置,然后再以它为参数,找到后续路径。
  2. 如果指定的模块文件没有发现,Node 会尝试为文件名添加.js、.json、.node 后,再去搜索。.js 件会以文本格式的 JavaScript 脚本文件解析,.json 文件会以 JSON 格式的文本文件解析,.node 文件会以编译后的二进制文件解析。
  3. 如果想得到 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

淡紫姑娘!

暂无简介

0 文章
0 评论
23 人气
更多

推荐作者

qq_7J1imQ

文章 0 评论 0

《一串符号》

文章 0 评论 0

hls.

文章 0 评论 0

雅心素梦

文章 0 评论 0

塔塔猫

文章 0 评论 0

微信用户

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文