前端模块化,AMD,CMD 面试总结

commonJS,CMD/AMD对应类似的实现是 noedJs(webpack)/RequireJs/SeaJs

 AMD/CMD主要针对浏览器端。

模块化
一个模块化实现特定功能,组织JS中的业务逻辑,都可以称为模块化。这种模块化类似于 java中的包 直接引入,即插即用,不会产生变量冲突,就是如此便捷。

commonJS
commonJS运行于服务器端,node.js的模块系统,就是参照CommonJS规范实现的,每个模块都是一个单独的作用域。
模块只有一个出口,module.exports对象,我们需要把模块希望输出的内容放入该对象。

服务器端一般采用同步加载文件,也就是说需要某个模块,服务器端便停下来,等待它加载再执行。而浏览器端要保证效率,需要采用异步加载,这就需要一个预处理,提前将所需要的模块文件并行加载好。

AMD

AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块 

同样都是异步加载模块,AMD在加载模块完成后就会执行改模块,所有模块都加载执行完后会进入require的回调函数,执行主逻辑,这样的效果就是依赖模块的执行顺序和书写顺序不一定一致,看网络速度,哪个先下载下来,哪个先执行,但是主逻辑一定在所有依赖加载完成后才执行.

requireJS主要解决两个问题

1、多个js文件可能有依赖关系,被依赖的文件需要早于依赖它的文件加载到浏览器 
2、js加载的时候浏览器会停止页面渲染,加载文件越多,页面失去响应时间越长 

 

require()函数在加载依赖的函数的时候是异步加载的,这样浏览器不会失去响应,它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题。

CMD

CMD推崇就近依赖,只有在用到某个模块的时候再去require 

CMD规范是国内发展出来的,就像AMD有个requireJS,CMD有个浏览器的实现SeaJS,SeaJS要解决的问题和requireJS一样,只不过在模块定义方式和模块加载(可以说运行、解析)时机上有所不同 

1.Sea.js 推崇一个模块一个文件,遵循统一的写法 

2.CMD加载完某个模块后没有立即执行而是等到遇到require语句的时再执行。

 

CMD加载完某个依赖模块后并不执行,只是下载而已,在所有依赖模块加载完成后进入主逻辑,遇到require语句的时候才执行对应的模块,这样模块的执行顺序和书写顺序是完全一致的

 

AMD在加载模块完成后就会执行改模块,所有模块都加载执行完后会进入require的回调函数,执行主逻辑,这样的效果就是依赖模块的执行顺序和书写顺序不一定一致,看网络速度,哪个先下载下来,哪个先执行,但是主逻辑一定在所有依赖加载完成后才执行

这也是很多人说AMD用户体验好,因为没有延迟,依赖模块提前执行了,CMD性能好,因为只有用户需要的时候才执行的原因

ES6 模块与 CommonJS 模块的差异

来自阮一峰ES6教程

CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
CommonJS 模块是运行时加载,ES6 模块是编译时输出接口
ES6 模块的运行机制与 CommonJS 不一样。JS 引擎对脚本静态分析的时候,遇到模块加载命令import,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。换句话说,ES6 的import有点像 Unix 系统的“符号连接”,原始值变了,import加载的值也会跟着变。因此,ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块

模块化方案总结

  ESM CommonJS AMD CMD UMD
加载机制 编译时 运行时 提前预加载 编译时 & 运行时按需加载 -
同步/异步 异步 同步 异步 异步,有延迟执行的情况 -
适用场合 浏览器、服务端 服务端 浏览器 浏览器 浏览器、服务端
是否常见 ☆☆☆ ☆☆☆

ESM 在语言标准的层面上,成为浏览器和服务端通用的模块解决方案。

模块化的好处

  1. 避免命名冲突,每个模块内的变量仅对自己可见,外部获取依赖模块输出
  2. 按需加载
  3. 解耦、复用、高可维护性



你可能感兴趣的:(前端模块化,AMD,CMD 面试总结)