模块化:是一种处理复杂系统分解为代码结构更合理,可维护性更高的可管理的模块的方式。前端
在理想状态下咱们只须要完成本身部分的核心业务逻辑代码,其余方面的依赖能够经过直接加载被人已经写好模块进行使用便可。jquery
无模块es6
<script src="jquery.js"></script> <script src="jquery_scroller.js"></script> <script src="main.js"></script> <script src="other1.js"></script> <script src="other2.js"></script> <script src="other3.js"></script>
优势:
相比于使用一个js文件,这种多个js文件实现最简单的模块化的思想是进步的。 编程
缺点:
污染全局做用域。 由于每个模块都是暴露在全局的,简单的使用,会致使全局变量命名冲突,固然,咱们也可使用命名空间的方式来解决。
对于大型项目,各类js不少,开发人员必须手动解决模块和代码库的依赖关系,后期维护成本较高。
依赖关系不明显,不利于维护。 好比main.js须要使用jquery,可是,从上面的文件中,咱们是看不出来的,若是jquery忘记了,那么就会报错。api
CommonJs 是服务器端模块的规范,Node.js采用了这个规范
根据CommonJS规范,一个单独的文件就是一个模块。加载模块使用require方法,该方法读取一个文件并执行,最后返回文件内部的exports对象。数组
var math = require('math'); math.add(2, 3);
第二行math.add(2, 3),在第一行require('math')以后运行,所以必须等math.js加载完成。也就是说,若是加载时间很长,整个应用就会停在那里等。您会注意到 require 是同步的。
CommonJS 加载模块是同步的,因此只有加载完成才能执行后面的操做。像Node.js主要用于服务器的编程,加载的模块文件通常都已经存在本地硬盘,因此加载起来比较快,不用考虑异步加载的方式,因此CommonJS规范比较适用。但若是是浏览器环境,要从服务器加载模块,这是就必须采用异步模式。因此就有了 AMD CMD 解决方案。浏览器
AMD 即 Asynchronous Module Definition,中文名是异步模块定义的意思。它是一个在浏览器端模块化开发的规范缓存
AMD也采用require()语句加载模块,可是不一样于CommonJS,它要求两个参数:服务器
require([module], callback);
第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功以后的回调函数。若是将前面的代码改写成AMD形式,就是下面这样:curl
require(['math'], function (math) { math.add(2, 3); });
math.add()与math模块加载不是同步的,浏览器不会发生假死。因此很显然,AMD比较适合浏览器环境。目前,主要有两个Javascript库实现了AMD规范:require.js和curl.js。
与 RequireJS
AMD 是 RequireJS 在推广过程当中对模块定义的规范化产出
AMD异步加载模块。它的模块支持对象 函数 构造器 字符串 JSON等各类类型的模块。
//经过数组引入依赖 ,回调函数经过形参传入依赖
define(['Module1', ‘Module2’], function (Module1, Module2) { function foo () { /// someing Module1.test(); } return {foo: foo} });
第一个参数 id 为字符串类型,表示了模块标识,为可选参数。若不存在则模块标识应该默认定义为在加载器中被请求脚本的标识。若是存在,那么模块标识必须为顶层的或者一个绝对的标识。
第二个参数,dependencies ,是一个当前模块依赖的,已被模块定义的模块标识的数组字面量。
第三个参数,factory,是一个须要进行实例化的函数或者一个对象。
建立模块标识为 Module1 的模块,依赖于 require, export,和标识为 beta 的模块
AMD规范容许输出模块兼容CommonJS规范,这时define方法以下:
define(function (require, exports, module) { var reqModule = require("./someModule"); requModule.test(); exports.asplode = function () { //someing } });
优势:
适合在浏览器环境中异步加载模块。能够并行加载多个模块。 缺点:
提升了开发成本,而且不能按需加载,而是必须提早加载全部的依赖。
CMD是SeaJS 在推广过程当中对模块定义的规范化产出
CMD和AMD的区别有如下几点:
1.对于依赖的模块AMD是提早执行,CMD是延迟执行。不过RequireJS从2.0开始,也改为能够延迟执行(根据写法不一样,处理方式不经过)。
2.AMD推崇依赖前置(在定义模块的时候就要声明其依赖的模块),CMD推崇依赖就近(只有在用到某个模块的时候再去require——按需加载)。
//AMD define(['./a','./b'], function (a, b) { //依赖一开始就写好 a.test(); b.test(); });
//CMD define(function (requie, exports, module) { //依赖能够就近书写 var a = require('./a'); a.test(); ... //软依赖 if (status) { var b = requie('./b'); b.test(); } });
3.AMD的api默认是一个当多个用,CMD严格的区分推崇职责单一。例如:AMD里require分全局的和局部的。CMD里面没有全局的 require,提供 seajs.use()来实现模块系统的加载启动。CMD里每一个API都简单纯粹。
AMD 是 RequireJS 在推广过程当中对模块定义的规范化产出,CMD是SeaJS 在推广过程当中被普遍认知。RequireJs出自dojo加载器的做者James Burke,SeaJs出自国内前端大师玉伯。两者的区别,玉伯在12年如是说:
RequireJS 和 SeaJS 都是很不错的模块加载器,二者区别以下:
二者的插件机制有差别。RequireJS 采起的是在源码中预留接口的形式,源码中留有为插件而写的代码。SeaJS 采起的插件机制则与 Node 的方式一致开放自身,让插件开发者可直接访问或修改,从而很是灵活,能够实现各类类型的插件。
优势: 一样实现了浏览器端的模块化加载。 能够按需加载,依赖就近。
缺点: 依赖SPM打包,模块的加载逻辑偏重。
CommonJS
对于基本数据类型,属于复制。即会被模块缓存。同时,在另外一个模块能够对该模块输出的变量从新赋值。
对于复杂数据类型,属于浅拷贝。因为两个模块引用的对象指向同一个内存空间,所以对该模块的值作修改时会影响另外一个模块。
当使用require命令加载某个模块时,就会运行整个模块的代码。
当使用require命令加载同一个模块时,不会再执行该模块,而是取到缓存之中的值。也就是说,CommonJS模块不管加载多少次,都只会在第一次加载时运行一次,之后再加载,就返回第一次运行的结果,除非手动清除系统缓存。
循环加载时,属于加载时执行。即脚本代码在require的时候,就会所有执行。一旦出现某个模块被"循环加载",就只输出已经执行的部分,还未执行的部分不会输出。
ES6模块
ES6模块中的值属于【动态只读引用】。
对于只读来讲,即不容许修改引入变量的值,import的变量是只读的,不管是基本数据类型仍是复杂数据类型。当模块遇到import命令时,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。
对于动态来讲,原始值发生变化,import加载的值也会发生变化。不管是基本数据类型仍是复杂数据类型。
循环加载时,ES6模块是动态引用。只要两个模块之间存在某个引用,代码就可以执行
原文连接: https://cloud.tencent.com/developer/article/1177217