JavaScript模块化

无模块的缺点(传统写法)

当 .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


原文出处:/show_1IX3xPtu4lVi.html