CommonJS、AMD、CMD、ES6模块化区别详细总结

一、CommonJS、AMD、CMD、ES6知识点简单概述

(1)CommonJS

NodeJS是CommonJS规范服务器端的实现,webpack也是CommonJS的形式书写。同步加载,服务器端从磁盘中读取速度快,运行在服务器端没有问题。

(2)AMD

AMD是Asynchronous Module Definition异步模块定义。

基于CommonJS规范的node.JS是服务端模块化的实现。实现浏览器端的模块化就是AMD,且能与服务器端兼容最好。同一个模块在服务器端和浏览器端都可以维护运行,简单方便很多,效率也提高了不少。

浏览器不能兼容CommonJS,于是AMD就出现了。浏览器不能兼容CommonJS的根本原因在于缺少node.JS的四个环境变量:module、exports、requrie、global。

为什么服务器端可以同步加载,浏览器端不能同步加载,需要异步加载

var math = require('math');
math.add(2,3)

解析:第二行代码在第一行之后运行,必须等到math.js加载完成后运行,如果加载时间特别特别长,整个程序就会卡顿。这里的这里的requrie是同步加载的。浏览器的模块都在服务器端,等待时间取决于网络速度的快慢,等待的时间越长,浏览器响应的时间越长,甚至造成“假死”的状态。服务器端的模块放在本地硬盘中,同步加载读取的时间很快,几乎不会产生什么影响。

(3)CMD

AMD推崇依赖前置,CMD推崇依赖就近,延迟加载。

(4)ES6模块化

ES6模块化采用静态编译,在编译的时候就能确定依赖关系,以及输入和输出的变量。

CommonJS和AMD模块只能运行时确定。

二、AMD规范与CMD规范的区别

①CMD推崇依赖就近,AMD推崇依赖前置

②CMD延迟执行,AMD是提前执行

扫描二维码关注公众号,回复: 14632064 查看本文章

③CMD性能好,按需加载,当用户有需要在执行。AMD用户体验好,不延迟执行,依赖模块提前加载完毕

    //AMD默认推荐的是
    define(['./a', './b'], function (a, b) {
    
     //依赖前置,必须一开始就写好
        a.doSomething()
        b.doSomething()
    })
    //CMD默认推荐的是
    define(function (require, exports, module) {
    
    
        var a = require('./a')
        a.doSomething()
        var b = require('./b') //依赖就近,按需加载,需要哪个写哪个
        b.doSomething()
    })

AMD和CMD最大的区别是对依赖模块的执行时机处理不同注意不是加载的时机或者方式不同

①AMD和CMD都是异步加载模块。AMD依赖前置,js可以提前知道所有的依赖模块,立即加载。CMD就近依赖,模块解析为字符串后才能知道依赖哪些模块。CMD性能好,按需加载,用户需要才加载。AMD用户体验好,模块全部提前加载好。

②AMD加载完模块之后就会立即执行它,所有模块加载完之后进入require回调函数,执行主逻辑。依赖模块的执行顺序和开发人员写的不一样,哪一个模块网速好先下载哪个就先执行,但是主逻辑一定是所有模块加载完成后才执行。

③CMD加载完某个模块后并不执行,只是下载,在所有模块加载完成后进入主逻辑,遇到require语句的时候才执行对应的模块。依赖模块的执行顺序和开发人员写的一样。

三、ES6模块和CommonJS规范区别

①CommonJS支持动态导入,ES6不支持,是静态编译。

②CommonJS同步加载,用于服务端,文件放在本地磁盘,读取速度快。同步导入卡住主线程也并无影响。ES6是异步加载,用于浏览器端,不能同步加载,会导致页面渲染,用户体验差。

③CommonJS模块输出的是值拷贝,内部的变化影响不到值的变化。ES6模块输出的是值引用,原始值变化,加载的值也会跟着变化,ES6模块是动态引用,并且不会缓存值。

④CommonJS模块是运行时加载,ES6模块是编译时输出接口。CommonJS模块就是对象,输入时先加载整个模块,生成一个对象,然后从对象读取方法。ES6模块不是对象,export输出指定代码,import导入加载某个值,而不是整个模块。

⑤关于模块顶层的this指向问题,在CommonJS顶层,this指向当前模块;而在ES6模块中,this指向undefined。

⑥ES6模块当中,是支持加载CommonJS模块的。但是反过来,CommonJS并不能requireES6模块,在NodeJS中,两种模块方案是分开处理的。

四、加载模式的总结

(1)CommonJS加载模式—同步/运行时加载

CommonJS加载模块是同步的。输入的时候加载整个模块,生成一个对象,从这个对象上读取方法。子模块完成加载,才能执行后面的操作。输入的值是被输出的值的拷贝,父模块引入子模块,引入的是子模块的值拷贝,模块的内部变化无法影响这个值。

(2)AMD加载模式—异步加载、依赖前置

AMD在浏览器端异步加载,AMD推崇依赖前置,加载完模块之后就会立即执行它。

(3)CMD加载模式—异步加载、依赖就近

CMD在浏览器端异步加载,CMD推崇依赖就近,加载完模块不会立即执行,只是加载,等到需要的时候才会执行。

(4)ES6加载模式—静态编译

ES6静态编译,在编译的时候就能确定依赖,编译的时候输出接口。export输出指定代码,import某个值不是整个模块。

五、ES6、CommonJS循环引用问题

什么是循环引用?循环加载指的是a脚本的执行依赖b脚本,b脚本的执行依赖a脚本。
①CommonJS模块是加载时执行。一旦出现某个模块被“循环加载”,就只输出已经执行的部分,没有执行的部分不会输出。
②ES6模块对导出模块,变量,对象是动态引用,遇到模块加载命令import时不会去执行模块,只是生成一个指向被加载模块的引用

猜你喜欢

转载自blog.csdn.net/weixin_45709829/article/details/124138115
今日推荐