一、什么是模块化?
到底什么是模块化、模块化开发呢?
- 事实上模块化开发最终的目的是将程序划分成一个个小的结构;
- 这个结构中编写属于自己的逻辑代码,有自己的作用域,定义变量名词时不会影响到其他的结构;
- 这个结构可以将自己希望暴露的变量、函数、对象等导出给其结构使用;
- 也可以通过某种方式,导入另外结构中的变量、函数、对象等;
上面说提到的结构,就是模块;按照这种结构划分开发程序的过程,就是模块化开发的过程;
无论你多么喜欢JavaScript,以及它现在发展的有多好,它都有很多的缺陷:
- 比如var定义的变量作用域问题;
- 比如JavaScript的面向对象并不能像常规面向对象语言一样使用class;
- 比如JavaScript没有模块化的问题;
对于早期的JavaScript没有模块化来说,确确实实带来了很多的问题;
以前我们是怎么开发的?通过 <script src="aaa.js"></script> 直接引入进来。
但是这个方法引入的时候,我这个aaa.js文件本身有作用域吗?答案是:没有,我只是给他放到一个独立的文件里面,相当于还是在全局的。
那aaa.js文件里面有name,bbb.js文件里面也有name,这不会造成命名冲突了吗?
那怎么去避免这个命名冲突,有小伙伴们说用let。
我们假设aaa.js是张三开发的代码,bbb.js是李四开发的代码,那这个时候我们去运行index.html,会报错:name已经被声明过了。是不是已经被定义了。
所以用let也会有问题:李四想定义一个name变量,他连name这个名字都不能用了。
开发者A在文件中用了name这个名字,开发者B在文件中就不能用name这个名字吗?不应该是这样子的。
问:以前我们是怎么解决这个问题的?
答:立即执行函数
这样子确实能解决我们命名冲突的问题。因为用的函数,函数有自己的作用域。
那此时我们新建一个unil.js文件,在index.html中引入这个文件。
util.js文件中我想获取aaa文件中的name,能获取到吗?获取不到。
那我们怎么才能获取呢?答:在函数里面把他们返回出去。
但是现在这么用又暴露出来另外一个问题,你怎么知道aaa.js里面的变量名是moduleA呢? 别人必须去查看你的源码,而且你这个规范,如果公司新来一个职员,别人怎么知道用哪个规范呢?
早期,不同的公司不同的项目采用的模块化的方案也是不同的。
二、 模块化的历史
三、 没有模块化带来的问题
四、CommonJS规范和Node关系
五、 模块化案例
有2个js文件,我们通过 node main.js 能访问util.js文件里面的UTIL_NAME吗?
很明显不能,因为在Node里面,每一个文件都是一个独立的模块。每一个模块都是有自己的作用域的。
那我们该怎么去访问?因为Node里面帮我们实现了CommonJS的规范,CommonJS想要访问不同模块之间的变量该怎么去访问?是不是得把对应的标识符导出去?
// 1. 直接获取导出的对象,从对象中获取属性
// const util = require("./util.js")
// console.log(util.UTIL_NAME)
// console.log(util.formatCount())
// 2. 导入对象之后,直接对其进行结构
const { UTIL_NAME, formatCount, formatDate } = require("./util.js")
console.log(UTIL_NAME)
console.log(formatCount())
为了验证上述逻辑,我们来个案例:
bar.js:
let name = "bar"
exports.name = name
setTimeout(() => {
// name = "why"
exports.name = "why"
}, 2000)
main.js
// 3. 探讨require的本质
const bar = require("./bar.js")
console.log(bar.name)
// 4s之后重新获取name
setTimeout(() => {
console.log(bar.name)
}, 4000)
执行node main.js,打印结果:
bar
why
本质就是引用赋值,require和exports指向的对象是同一个对象。
六、exports导出、module.exports导出
(1)exports导出和module.exports的区别
代码发生了什么???
(2) require细节
七、模块的加载过程
八、CommonJS规范缺点
九、AMD规范
十、require.js的使用
十一、CMD规范
十二、SeaJS的使用
十三、ES Module
十四、案例代码结构组件
十五、exports关键字
十六、import关键字
十七、export和import结合使用
十八、default用法
十九、import函数
二十、import meta
二十一、ES Module的解析流程
(1)阶段一:构建阶段
(2)阶段二和三:实例化阶段 – 求值阶段