模块系统是什么?简单来说,其实就是我们在一个文件里写代码,声明一些可以导出的字段,然后另一个文件可以将其导入并使用。
模块化的优点:
- 文件里声明的变量会被隔离,不会暴露到全局,可以有效解决以往变量污染全局空间的问题;
- 更容易看出代码之间的依赖关系,看文件头的的导入代码就知道;
- 方便多人协作,各自开发自己的模块,而不冲突;
- 不用担心文件引入的顺序;
- 方便以文件为单位做单元测试;
模块化解决了变量污染、代码维护、依赖顺序问题。
CommonJS
CommonJS,或者叫 CJS,是 nodejs 选择的模块化标准。
导出模块的写法:
每个文件都可以访问到一个 module 对象,其下的 exports 属性是一个空对象,你可以给它加上属性,module.exports 将作为可以导出的代码部分。
exports 是一个别名,它指向 module.exports,用它能够少打一点字。
然后是导入模块的写法:
require 方法能够找到对应模块文件,提取出它的 module.exports 对象,引入到当前模块中。关于 require 怎么找到模块的过程,也是一篇长篇大论,有机会另开一篇文章再讲解了。
nodejs 现在最新版也支持用 ES Modules 的方式了,需要在 package.json 上加上
"type": "module"
。
ES Modules
ES Modules,或者叫 ESM,是 ES6 引入的新特性,是模块系统的真正标准。
在 script 标签下设置 type="module",可以开启模块化加载。
当然实际上生产环境我们是不会这么做的,只是用 ES Modules 写代码,然后打包,用传统的模式运行。
导出模块的写法:
ES Modules 中,export 不是一个对象,准确来说都不是变量,而是新引入的关键字,用于指定要导出的变量。
然后是导入模块的写法:
根据标准,导入的模块名是要提供 .js
后缀名的,因为实际上的 ES Module 是会请求一个 url 的,url 必须精准。
不过我们通常会使用打包工具,可以配置一下将其省略。比如 webpack,我们可以设置 resolve.extensions 配置项来设置后缀不存在时,拼上什么后缀去查找。
AMD和CMD都是过时内容,这篇文章这里就不讲了。