无模块的缺点(传统写法)
当 .js 文件中的代码较多时,需要根据功能拆分成多个文件
1.js
如下:
let name = '李雷'
function add(i,j){
return i + j
}
function mianji(r){
return Math.PI * r * r
}
2.js
如下(需要调用 1.js 的 add() 函数 ):
let name = '韩梅梅'
function test(){
const res = add(5,11)
console.log("res:",res)
}
// 求正方形面积
function mianji(len){
return len * len
}
html代码
代码如下:
<script src="js/1.js"></script>
<script src="js/2.js"></script>
<script>
test()
console.log("边长是5的正方形面积:",mianji(5))
console.log("半径是5的圆面积:",mianji(5))
</script>
缺点
全局变量污染
因为两个 js 文件中都有变量 name ,所以引入两个 js文件 会报错:
<script src="js/1.js"></script>
<script src="js/2.js"></script>
错误如下:
文件依赖顺序
下面顺序会报错
<script src="js/2.js"></script>
<script>
test()
console.log("边长是5的正方形面积:",mianji(5))
console.log("半径是5的圆面积:",mianji(5))
</script>
<script src="js/1.js"></script>
函数命名冲突
<script src="js/1.js"></script>
<script src="js/2.js"></script>
<script>
test()
console.log("边长是5的正方形面积:",mianji(5))
console.log("半径是5的圆面积:",mianji(5))
</script>
执行结果:
25
25
1.js 和 2.js 都有 mianji() 函数,后引入 2.js,所以 2.js 的 mianji() 会覆盖 1.js 的 mianji(),上面函数都会调用 2.js 文件的 mianji()
什么是模块化
将一个复杂的程序,依据一定的规则(规范)封装成一个或多个模块(文件), 并进行组合在一起
模块中的变量 与 方法是私有的,只是向外部暴露一些接口(方法),供其他程序调用、或 与其它模块通信
模块化的发展
CommonJS
2009年Nodejs发布,采用 CommonJS 模块规范。
特点:
- 每个文件都是一个模块实例,代码运行在模块作用域,不会污染全局作用域。
- 文件内通过require对象引入指定模块,通过exports对象来向往暴漏API,文件内定义的变量、函数,都是私有的,对其他文件不可见。
- 每个模块加载一次之后就会被缓存。
- 所有文件加载均是同步完成,加载的顺序,按照其在代码中出现的顺序。
- 模块输出的是一个值的拷贝,模块内部的变化不会影响该值。
缺点: 基于Node原生api在服务端可以实现模块同步加载,但是仅仅 局限于服务端,客户端(浏览器)如果同步加载依赖的话时间消耗非常大
AMD/RequireJS
为了解决 CommonJS 在客户端(浏览器)上的缺点,于是AMD规范诞生了。
AMD是 Asynchronous Module Definition 的缩写,意思就是”异步模块定义”。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到所有依赖加载完成之后(依赖前置),这个回调函数才会运行。
RequireJS 是一个工具库,主要用于客户端的模块管理。它的模块管理遵守AMD规范,RequireJS的基本思想是,通过define方法将代码定义为模块,通过require方法实现代码的模块加载。
特点:浏览器直接运行无需编译,异步加载,依赖关系清晰
CMD/SeaJS
CMD规范专门用于浏览器端,同样是受到Commonjs的启发,国内(阿里)诞生了一个CMD(Common Module Definition)规范。该规范借鉴了Commonjs的规范与AMD规范,在两者基础上做了改进。
与AMD相比非常类似,CMD规范(2011)具有以下特点:
- define定义模块,require加载模块,exports暴露变量。
- 不同于AMD的依赖前置,CMD推崇依赖就近(需要的时候再加载)
- 推崇api功能单一,一个模块干一件事。
- SeaJs是CMD规范的实现,跟RequireJs类似,CMD是SeaJs推广过程中诞生的规范。CMD借鉴了很多AMD和Commonjs优点。
AMD、CMD区别
AMD 推崇依赖前置
CMD 推崇依赖就近
ES6
2015年,ES6规范中,终于将模块化纳入JavaScript标准,从此js模块化被ECMA官方扶正,也是后来js的标准。
ES6中的模块化在CommonJS的基础上有所不同,关键字有 import,export,default,as,from。
总结
- CommonJS规范主要用于 服务端编程,加载模块是同步的,不适合在浏览器环境,存在阻塞加载,浏览器资源是异步加载的,因此有了AMD、CMD解决方案。
- AMD规范在 浏览器 环境中异步加载模块,而且可以并行加载多个模块。
- CMD规范与AMD规范很相似,都用于 浏览器编程,依赖就近,代码更简单。
- ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
参考:
https://blog.csdn.net/jianren0518/article/details/106099103
