模块,模块化开发,规范
- 模块化开发的目标是把程序拆分成一个个小结构
- 在当前的结构中可以编写自己的逻辑代码,他拥有自己的作用域,不会影响到其他结构
- 在某个结构中可以向外界暴露自己的变量、函数、对象等给其他结构进行使用
- 在其他结构中如果需要使用别的结构的数据,则需要进行导入
那么这些个结构就是模块
基于这种模式的开发就是模块化开发
这个导入导出则就是模块化规范
为什么需要模块化?
随着前端的发展,业务越来越复杂,特别是从 SPA 应用的出现后,前端所需要编写的代码量越来越大,所以为了方便管理项目,则需要对项目进行拆分,从而也就需要模块化
CommonJS 和 Node
- CJS实现了在非浏览器环境中运行js代码
- NodeJs就是CJS的经典实现
module.exports、exports 和 require
module.exports
// a.js
let obj = {
a: 1,
b: 2
}
module.exports = obj
// b.js
const obj = require('a.js')
console.log(obj) // { a: 1, b: 2 }
exports
// a.js
let obj = {
a: 1,
b: 2
}
exports = obj // 方式1 --- 错误写法
exports.obj = obj // 方式2 --- 固定用法
// b.js
const obj = require('a.js')
console.log(obj) // 方式1: {}
console.log(obj) // 方式2:{ obj: { a: 1, b: 2 } }
在 Node 的内部实现中, 有下面两行代码
module.exports = {}
exports = module.exports
由此可以看出,module.exports 是创建了一个对象,并指向了这个对象,exports = module.exports 操作就让exports同样指向了这个对象,但如果我们做了 exports = obj 这种操作, 相当于是对这个对象进行了重新赋值,指向了一个新对象,那就不对了。
require 规则
- require(‘fs’) 等
加载核心模块,直接去查找 - require(’./xxx’) 传入路径形式
- require(’./xxx.js’) 带后缀名
在对应目录查找对应文件 - require(’./xxx’) 传入路径形式,不带后缀的
先去查找 xxx 文件,没有会进行后缀补全,优先级:.js --> .json --> .node - 如果都没有找到,则会将 xxx 当作目录,查找当前目录下的 index 文件,没有则会继续进行后缀补全,index.js --> index.json --> index.node
- 如果上述全部都没有找到,则就会报错了
- require(’./xxx.js’) 带后缀名
- require(‘axios’) 非路径,非核心模块
- 会将其当作第三方模块进行查找
- 从当前文件所在目录一级一级向上查找 node_modules,一直找到根目录
- 当多次导入一个文件
// a.js
console.log('a')
module.exports = { name: '1234', age: 6 }
// b.js
require('./a') // a
require('./a')
当多次导入一个文件的时候,该文件内的代码只会执行一次,因为会被缓存下来
5. require() 是同步的加载模式
require('./a') // 在执行到这行时,会停住,直到这个文件内的代码走完以后才会去执行下面的代码
console.log('aaa')