模块化
一、模块化的基本概念
1、概念
模块化
是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。对于整个系统而言,模块是可组合、分解和更换
的单元。
列举一个生活实例:比如录音机,机体和磁带是可分离的两部分,当我们更换磁带就可以听不同的音乐,这就是模块化的思想。
编程领域的模块化,就是遵守固定的规则
,把一个大文件拆成独立并互相依赖的多个小模块
。
将代码进行模块化拆分的好处:
- 提高了代码的复用性
- 提高了代码的可维护性
- 可以实现按需加载
2、模块化规范
模块化规范就是对代码进行模块化的拆分和组合时,需要遵守的规则。
例如:
模块规范化的好处:大家都遵守同样的模块化规范写代码,降低了沟通的成本,极大方便了各个模块之间的相互调用。
二、Node.js模块的分类
1、分类
Node.js中根据模块来源的不同,将模块分为了3大类,分别是:
- 内置模块(内置模块是由官方提供的,例如fs,path,http)
- 自定义模块(用户创建的每个.js文件,都是自定义模块)
- 第三方模块(由第三方开发出来的模块,并非官方提供的内置模块,也不是由用户创建的自定义模块,
使用前需要先下载
)
2、加载模块
使用强大的require()方法
,可以加载需要的内置模块、用户定义模块、第三方模块进行使用
//1.加载内置的fs模块
const fs = require('fs');
//2.加载用户的自定义模块
const custom = require('./custom.js'); //给一个相对路径
//3.加载第三方模块
const moment = require('moment');
注意:当使用require()方法
加载其他模块时,会执行被加载模块中的代码。
举个例子
在nn.js
中写入文件
在mm.js文件中加载模块
const nn =require('./nn.js')
console.log(nn)
得到最后的打印结果如图:
可以看出nn
的代码内容在调用了出来。
三、node.js中的模块作用域
1、什么是模块作用域
和函数作用域相似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问
,这种模块级别的访问限制
,叫做模块作用域。
2、模块作用域的好处
下面我们做一个示例
先编写一个mm,js文件,里面声明uername常量,定义一个函数
const username = 'anni'
function sayHello(){
console.log('hello,my name is'+username)
}// An highlighted block
var foo = 'bar';
再编写一个nn.js文件,导入mm.js文件来获取里面的内容
const custom = require('./mm.js')
console.log(custom)
最终打印的结果是一个空对象,从而证明了默认情况下node具有作用域
,在模块内定义的成员无法被外界访问,只能自己访问自己。
四、向外共享模块作用域中的成员
1、moudle对象
在每个.js自定义模块中都有一个module对象,它里面存储了和当前模块
相关的信息,打印如下:
2、module.exports对象
在自定义模块中,可以使用module.export对象,将模块内的成员共享出去,供外界使用,外界用require()
方法导入自定义模块时,得到的就是module.exports所指向的对象。
在自定义模块中,默认情况下,module.exports = { }
下面看个示例:
在nn.js文件中写入以下代码
//向mouble.exports对象上挂载 username 属性
module.exports.username = 'anni'
//向mouble.exports对象上挂载 sayhello 方法
module.exports.sayHello = function (){
console.log('hi~')
}
在mm.js中导入自定义模块nn.js,
const nn = require('./nn')
console.log(nn)
最终的打印结果如下:
3、向外共享成员的注意点
使用require()方法导入模块时,导入的结果,永远以 module.exports 指向的对象为准。
我们在上面的例子中继续添加一个新的module.exports对象,示例如下:
//向mouble.exports对象上挂载 username 属性
module.exports.username = 'anni'
//向mouble.exports对象上挂载 sayhello 方法
module.exports.sayHello = function (){
console.log('hi~')
}
//添加一个module.exports 对象
module.exports = {
nickname : 'tony',
sayhi(){
console.log('hi')
}
}
const nn = require('./nn')
console.log(nn)
在mm.js中导入自定义模块nn.js后打印结果如下:
4、exports对象
默认情况下,exports 和 module.exports
指向同一个对象,最终共享的结果,还是以 module.exports 指向的对象为准。使用exports写法更加简单。
console.log(exports === module.exports) //结果为true
5、exports和module.exports 的使用误区
案例1:
exports.username = 'anni';
module.exports = {
nickname : 'tony',
age: 22
}
分析
:开始,exports 和 module.exports 都指向空对象,然后通过引用关系了username这个属性,之后又为module.exports 赋值了新的对象,新对象里有两个属性nickname 和 age 属性,所以module.exports再次指向新的对象。
案例2:
module.exports.username = 'tony';
exports = {
nickname : 'anni',
age: 18
}
分析
:开始,exports 和 module.exports 都指向空对象,然后通过引用关系挂载了username这个属性,之后 exports 赋值了新的对象,新对象里有两个属性nickname 和 age 属性,结果得到的永远是module.exports
指向的对象。
案例3:
exports.username = 'tony';
module.exports.gender = '男' ;
分析
:开始,exports 和 module.exports 都指向空对象,然后给exports 引用一个对象,属性为username,同时给module.exports 也挂载了username这个属性,最终结果如上图所示
案例4:
exports = {
username : 'tony',
age: 22
}
module.exports = exports
module.exports.gender = '男';
分析
:开始,exports 和 module.exports 都指向空对象, exports 赋值了新的对象,新对象里有两个属性username 和 age 属性,后又将export赋值给module.exports,之后 给module.exports 挂载了gender属性,最终结果如图所示。四个实例都验证了调用required()模块时,得到的永远时module.exports
指向的对象。