为什么要使用模块化?
当我们一个项目越做越大的时候,维护起来肯定没那么方便,且多人协作的去进行开发,当中肯定会遇到很多的问题,例如:
- 方法的覆盖: 很有可能你定义的一些函数会覆盖公共类中同名的函数,因为你可能根本就不知道公共类中有哪些函数,也不知道是如何命名的。
- 这些公共的组件: 但是你又不知道这些组件又会依赖哪些模块,同时在维护这些公共方法的时候,会新增一些依赖或者删除一些依赖,那么每个引入这些公共方法的地方都需要去对应的新增或者删除。等等,还会存在很多的问题。
我们使用模块化就是为了让各个模块之间相对独立,可能每个文件就是一个功能块,能满足于某项特定的功能,这样我们在引用某项功能的时候就会很方便。
CommonJS
Node 应用由模块组成,采用 CommonJS 模块规范。
每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见,CommonJS规范加载模块是同步的,也就是说,加载完成才可以执行后面的操作,Node.js主要用于服务器编程,模块一般都是存在本地硬盘中,加载比较快,所以Node.js采用CommonJS规范。且CommonJS模块输出的是值的缓存, 运行时加载。
CommonJS规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。
// tools.ts
const add = (a: number, b: number) =>{
return a + b
}
const reduce = (a: number, b: number) => {
return a - b
}
const multy = (a: number, b: number) => {
return a * b
}
exports.add = add
exports.reduce = reduce
export default multy
// 等价于
module.exports = {
add,
reduce
}
// app.ts
const tools = require('./tools.ts')
tools.add(2, 3) // 5
tools.reduce(3, 2) // 1
Node内部提供一个Module构建函数。所有模块都是Module的实例。
// Module 构造函数
function Module(id, parent) {
this.id = id //模块的识别符,通常是带有绝对路径的模块文件名
this.exports = {
} //表示模块对外输出的值
this.parent = parent //返回一个对象,表示调用该模块的模块
...
}
// tools.ts
const add = (a: number, b: number) =>{
return a + b
}
exports.add = add
console.log(module)
// 输出
Module {
id: '.',
exports: {
add