关于模块化开发,CMD和AMD
模块化
首先要理解的是什么是模块化,模块化这个词来源于研究工程设计中的《Design Rules》,是指可组成系统的、具有某种确定独立功能的半自律性的子系统。
模块化在编程中的意义是为了减少软件的复杂度,使软件不会因为不断的扩大而导致功能维护、添加变得十分困难。而通过模块的拼接,就可以组成一些列的复杂的系统,同时 模块与模块之间耦合度低。这种拼凑是灵活的,自由的
为什么要模块化
web前端不断发展,其中各种插件的代码量已经不是以前可比的了。而代码量的上升会暴露出许多问题:
首先是命名,即命名冲突问题。我们可能会对一个学生命名student1,当考虑到整个学校会有相同姓名的学生出现,就会把学生姓名放到特定空间下,即grade1.class1.student1,当然这时候你就会发现,好像还要考虑学校,于是最后就会变的极其长
1 // student1 学生 2 school1.grade1.class1.student1 3 4 // student1 学生的一个方法 5 school1.grade1.class1.student1.study()
这样看起来,似乎命名冲突的问题已经解决了,但是,每次为了调用一个普通的方法,就需要记住一长串的名字,似乎有点累
其次是复杂的依赖问题,我们经常会碰到以下的情况:
1 <script src="util.js"></script> 2 <script src='page.js'></script>
在page.js中依赖util.js,util中存放一些通用的方法,page专门用于翻页效果的制作。但是,不管你重申多少遍,总会有人忘记先引用util.js,然后和你说page.js中有bug。 这是十分让人无语的。这还是一个简单的例子,当page需要依赖十多个js文件时,这就会变得超级复杂,总会有人忘记引入部分js。
当然有人想到在page中注释依赖,或者比如国外的 YUI3 框架、国内的 KISSY 等类库,目前是通过配置的方式来解决。
YUI.add('my-module', function (Y) { // ... }, '0.0.1', { requires: ['node', 'event'] });
上面的代码,通过 requires 等方式来指定当前模块的依赖。这很大程度上可以解决依赖问题,但不够优雅。当模块很多,依赖很复杂时,烦琐的配置会带来不少隐患。
CMD和AMD
CMD和AMD的规范:
AMD规范:https://github.com/amdjs/amdjs-api/wiki/AMD
CMD规范:https://github.com/seajs/seajs/issues/242
AMD是requirejs在推广中对模块定义的规范
CMD是seajs在推广中对模块定义的规范
这两个规范都是为了javascript模块化开发的,特别是在浏览器端
这些模块化规范都能实现浏览器端的模块化开发
区别:
- 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行
- CMD 推崇依赖就近,AMD 推崇依赖前置
// 引用玉伯大大的示例代码 // CMD define(function(require, exports, module) { var a = require('./a') a.doSomething() // 此处略去 100 行 var b = require('./b') // 依赖可以就近书写 b.doSomething() // ... }) // AMD 默认推荐的是 define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好 a.doSomething() // 此处略去 100 行 b.doSomething() ... })
- AMD 的 API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。比如 AMD 里,require 分全局 require 和局部 require,都叫 require。CMD 里,没有全局 require,而是根据模块系统的完备性,提供 seajs.use 来实现模块系统的加载启动。CMD 里,每个 API 都简单纯粹。
另外的一些差异,可以看下在规范中的定义
具体的东西大家—SeaJS 和 RequireJS 的差异,可以参考:https://github.com/seajs/seajs/issues/277
===========================================================================
最后膜拜下玉伯大大