在做项目的过程中通常会有一些可复用的通用性功能,之前的做法是把这个功能抽取出来独立为一个函数统一放到commonFunctions.js里面(捂脸),实现类似于snippets的代码片段收集。
function sub(){
//...
}
function sum(){
//...
}
在理想情况下,开发者只需要实现核心的业务逻辑,其他通用功能可以加载已经实现的模块。
然而,这样的做法并不是最佳实践,在实际的运用中。业务代码时常会与应用的通用代码中的命名出现冲突。这让我想起了cSharp,当初学习cSharp的时候,一些有经验的学长就指点说,做.Net方向的一定要有自己的类库,这样在以后的开发中直接应用对应的命名空间,调用相关函数即可。于是乎琢磨起在目前尚没有命名空间的Javascript中,是不是可以用对象模拟命名空间作为替代方案呢?恰好与前辈想法暗合Why SeaJS
var FocusTech = {};
FocusTech.print = function(str){
// code!
}
然而其中的弊端文中也已给出。即通过命名空间,也只是降低函数命名冲突的概率。
命名冲突和文件依赖,面对前端开发过程中的这两个经典问题。或许前端模块化开发是一个解决方案。
模块规范
异步模块定义AMD:(Asynchronous Module Definition)是 RequireJS 在推广过程中对模块定义的规范化产出。通用模块定义CMD:(Common Module Definition)是Sea.js在推广过程中对模块定义的规范化产出的。
- AMD 运行时核心思想是「Early Executing」,也就是提前执行依赖。EX:
define(['a', 'b'], function(A, B) {
//运行至此,a.js 和 b.js 已下载完成(运行于浏览器的 Loader 必须如此);
//A、B 两个模块已经执行完,直接可用(这是 AMD 的特性);
return function () {};
});
CMD 推崇 as lazy as possible.
在 CMD 规范中,一个模块就是一个文件。代码的书写格式如下:define(factory);
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()
...
})
对象模拟命名空间
Javascript模块化编程(二):AMD规范
Javascript模块化编程(一):模块的写法
SeaJS与RequireJS最大的区别
让我们再聊聊浏览器资源加载优化
SeaJS 和 RequireJS 的异同