前言

什么是 CommonJS

维基百科:CommonJS 是一个项目,其目标是为 JavaScript 在网页浏览器之外创建模块约定。创建这个项目的主要原因是当时缺乏普遍可接受形式的 JavaScript 脚本模块单元,模块在与运行 JavaScript 脚本的常规网页浏览器所提供的不同的环境下可以重复使用。

可以说 CommonJS 是一种 JavaScript 环境中模块化编程的规范。它定义了一套模块化导入和导出的语法和机制,旨在解决 JavaScript 在模块化方面的缺陷。

如何使用 CommonJS

CJS 模块使用 requiremodule.exports 实现导入和导出。

下面将分别详细介绍导出和导入的用法。

1 导出模块

在 Node.js 中导出一个模块非常的简单,只需要使用 module.exportsexports 将模块中的内容导出即可。

1.1 module.exports

指定属性导出,

js // 定义一个使用 module.exports 导出的模块 // 定义了一个名为 hello 的函数,用于输出问候语 // 定义了一个名为 byebye 的函数,用于输出告别语 // 定义了一个名为 userInfo 的对象,包含姓名和年龄两个属性 module.exports.hello = function (name) { console.log(`Hello, ${name}!`) } module.exports.byebye = function (name) { console.log(`byebye, ${name}!`) } module.exports.userInfo = { name: 'forever', age: 18 }

统一的对象导出。

``js // 在模块中定义一个hello函数 function hello(name) { console.log(Hello, ${name}!`) }

// 在模块中定义一个byebye函数 function byebye(name) { console.log(byebye, ${name}!) }

// 定义了一个名为 userInfo 的对象,包含姓名和年龄两个属性 const userInfo = { name: 'forever', age: 18 }

// 将函数和对象统一导出到模块的外部 module.exports = { hello, byebye, userInfo }

```

1.2 exports

js // 定义一个模块,使用 exports 导出模块中的内容。 // 定义了一个名为 hello 的函数,用于输出问候语 // 定义了一个名为 byebye 的函数,用于输出告别语 // 定义了一个名为 userInfo 的对象,包含姓名和年龄两个属性 exports.hello = function (name) { console.log(`Hello, ${name}!`) } exports.byebye = function (name) { console.log(`byebye, ${name}!`) } exports.userInfo = { name: 'forever', age: 18 }

1.3 两者区别

在 Node.js 中,module.exportsexports 都可用于导出 Node.js 模块中的代码的对象。

通常情况下,我们只会使用 module.exportsexports 其中的一个导出模块代码,它们之间有一些微妙的区别。

exports 实际上是 module.exports 的一个引用,当我们使用 exports 导出模块代码时,实际上是在向 module.exports 添加属性,如下所示:

js // 导出一个名为 "hello" 的函数到 "exports" 对象中 // 函数中会将 "Hello World!" 的信息输出到控制台中 exports.hello = function() { console.log("Hello World!"); };

这等价于:

js // 导出一个名为 "hello" 的函数到 "exports" 对象中 // 函数中会将 "Hello World!" 的信息输出到控制台中 module.exports.hello = function() { console.log("Hello World!"); };

但是,如果我们对 exports 进行重新赋值,就会打破这个关系,如下所示:

js // 定义一个名为 "exports" 的函数 // 函数中将 "Hello World!" 的信息输出到控制台中 exports = function() { console.log("Hello World!"); };

这时 exports 就不再指向 module.exports,而是指向了一个新的对象,原来的 module.exports 对象将会被忽略,因此该模块将不会导出任何内容。

下面是运行示例,

因此,建议在写 Node.js 模块时,只使用 module.exports 导出模块代码,而不要使用 exports。如果你需要向外部导出多个函数或对象,可以将它们作为 module.exports 的属性导出,如下所示:

js module.exports = { hello: function() { console.log("Hello World!"); }, bye: function() { console.log("Goodbye World!"); } };

这样,外部就可以通过 require 方法导入该模块,并访问其中的 foobar 方法了。

2 引入模块

上面阐述了导出,那么引入也同样简单。

2.1 完整引入

```js // 导入模块 "./exports" 并将其赋值给变量 context const context = require('./exports')

// 调用 context 模块中的 hello 函数,并传入 context.userInfo.name 参数 context.hello(context.userInfo.name)

// 调用 context 模块中的 byebye 函数,并传入 context.userInfo.name 参数 context.byebye(context.userInfo.name) ```

2.2 解构引入

当导出内容是一个对象时,可以使用解构引入。

js // 导入模块 "./exports" 中的 hello, userInfo 和 byebye,并赋值给相应的变量 const { hello, userInfo, byebye } = require('./exports') // 调用 hello 函数,并传入 userInfo.name 参数 hello(userInfo.name) // 调用 byebye 函数,并传入 userInfo.name 参数 byebye(userInfo.name)

当然可以在导入的时候修改引入的模块名称。

js // 导入模块 "./exports" 中的 hello, userInfo 和 byebye,并赋值给相应的变量 const { hello, userInfo: user, byebye } = require('./exports') // 调用 hello 函数,并传入 userInfo.name 参数 hello(user.name) // 调用 byebye 函数,并传入 userInfo.name 参数 byebye(user.name)

上述代码执行结果都一样。

小结

本节主要介绍了 Node.js 中 CommonJS 规范的模块导入导出用法:

掌握这三个核心的 方法/对象 的用法,就掌握了 CJS 规范的模块导入导出用法。