commonjs 是基于 node 的模块化标准。
当我们使用 nodejs 运行一个 JS 文件的时候,尤其是对于大型项目而言,一个 JS 文件肯定是不够的,肯定涉及到多个文件相互配合,这个时候就需要模块化,也就是文件间的相互引用。
首先,我们应该了解什么是模块,所谓的模块,就是实现了一些功能,但隐藏具体的实习细节,提供了一些接口供其他模块使用。实际上,这和我们函数的功能非常类似。
任何一个正常的模块化标准,都应该默认隐藏所有实现细节,仅通过某些语法或 API 调用来暴露部分接口。我们把暴露接口的过程称为模块导出。当然,别人引入你模块的时候,就可以用到该模块暴露出来的内容,这个过程其实就叫模块导入。
在 commonjs 中,使用 exports 导出模块,使用 require 导入模块
- 如果一个 JS 中存在 export 或者 require,这个 JS 文件就是一个模块
- 模块内部的代码默认全部隐藏,即只有模块内部可以使用
- exports 就是一个对象,给这个对象添加的任何属性都会导出到外部
- 使用 require 函数,函数内部填入一个模块路径,就可以获取到这个模块路径下的 exports 对象,也就完成了数据的导入
js
const a = 1;
exports.a = a;//导出了一个数据ajs
const test = require("填入JS文件路径");
console.log(test.a);//可以拿到a属性实际上,commonjs 的导入导出规则就已经 OK 了,接下来介绍一下其基本原理
首先,为了保证代码高效执行,nodejs 只有执行到 require 函数的时候才会加载并执行模块。也就是说,require 函数实际上干了两个步骤,第一步是同步执行指定路径下的 JS 代码,第二步是返回该 JS 代码的 exports 对象。
在 nodejs 中导入模块,使用相对路径的时候路径必须以
./或../开头,如果不以这俩开头,其实有特殊的含义
nodejs 模块中的代码不会污染全局变量,实际上我们大概率也能猜到,nodejs 是将模块中的代码放到了一个函数环境下执行,以保证执行完后不污染全局变量。
为了保证顺利导出内容,nodejs 做了这样的处理,在模块开始执行之前初始化 module.exports = {},同时为了方便我们使用,又声明变量 exports = module.exports。
最后导出的依然是
module.exports,exports只是一个别名,换句话说,我们导出的东西本质上就是module.exports这东西,这个东西可以是任何内容,不一定是对象,我们可以对他直接赋值完成导出操作。
为了避免反复加载一个模块,nodejs 默认开启了模块缓存,如果加载的模块已经被加载过了,会自动使用之前的导出结果。换句话说,多次导入同一个模块,该模块只会被执行一次,后续导入不会被执行,并且返回结果会使用第一次导入的结果。
nodejs 可以使用
require("文件路径")来直接导入一个 json 文件,也就是说如果 require 函数传入的路径中,文件是一个 JSON 格式的,我们可以直接拿到这个对象。