随着互联网的快速发展,人们不单单只是需要一个网页了,功能更复杂、交互更丰富的 WebAPP 成为开发者需要面对的日常工作内容。随之而来的是更加庞大与更加复杂的 JavaScript 代码,如此而来,仅仅依靠着我们之前面向对象的 JavaScript 进行代码封装已很难满足生产需求,特别是在团队协作的复杂项目中,JavaScript 模块化已成为一个迫切的需求。
原始社会的生产
开始的开始 Music ..♫.♪.♫.♪...我们都是...咳咳,我们都会使用如下的方式写代码,将独立通用的的功能独立成一个个函数:
function bar(){
//do something
}
function log(){
//do something
}
这都是最初得美好,那些习以为常的习惯,回忆ing...这是最原始的模块,需要使用调用就好。但是但是,使用过就会知道这样会污染全局变量,并且很容易造成 命名冲突,好吧,它属于最初的美好。
后来,为了解决上面青春期的问题,我们选择了面向对象写法,引入 Namespace (命名空间),将代码进行简单封装:
var myModule = {
bar: function(){
//do something
},
log: function(){
//do something
}
}
//调用
myMoudle.bar();
这种方式看似还可以,减少了全局变量,能缓解严峻的问题。但是这并不安全,因为实质上是对象,会暴露所有的模块成员,内部状态可以被外部读写。
没办法,出了问题继续解决,我们采用匿名闭包的写法(Immediately-Invoked Function Expression,IIFE):
var myModule = (function(){
var _log = "hello world";
var log = function(){
console.log(_log);
};
return {
log: log
}
})();
//引用
myModule.log();//hello world
myModule._log;//undefined
如此,外部就无法读写到内部的成员(_log
)。这时候需求又改变了,你的模块不再是简单的一个模块,而是一个功能很大的模块,需要分成几个部分,这些部分存在相互之间的 依赖关系。好吧,我们来引入依赖:
var myModule = (function($){
var $log = $('.log');
var log = function(){
console.log($log);
};
return {
log: log
}
})(jQuery);
//引用
myModule.log();
这样我们在代码中引入了jQuery,方法间存在依赖关系;
至此,我们用简陋的工具,和无比勤劳的双手为子孙们搭建了发展的架子,为后续社会发展出更先进好用的模块化工具打下了基石,感谢祖辈们的探索!
文明社会的探索
飞速变化的年代里,人们总是不满足于现状。有了前人的封装性还不够,我们引入 JS 文件时是靠不断追加 <script src=""></script>
标签得以实现,每个标签引入顺序是有要求的。
当我们引入的文件增多,除了看起来比较累赘,还会出现比较多的依赖关系,而这种写法是无法突出这种关系的,我们需要 依赖管理,也让 后续维护 基本上变得无法进行。
<script src="jquery.js"><script>
<script src="dialog.js"><script>
<script src="tooltip.js"><script>
<script src="toast.js"><script>
<script src="handlebar.js"><script>
......
很多时候可能就是由于之前没有引入一个依赖的 js 文件而导致后面 js 的功能失效,浏览器报错。大型项目中,一些通用组件往往因此不能轻易地引入到业务代码中去,生产效率低下。还有一个问题就是 请求过多,不利于性能优化。
时代的进步是注定需要出现伟人的,积累下的诉求注定是需要人来响应的,一些规范横空出世,诸如 CommonJS规范、AMD规范、CMD规范 等一帮豪杰之辈,怀揣济世为民之心,度前端开发者于混沌之境。欲知其如何演绎,请看下篇 《前端模块化之旅(二):CommonJS、AMD和CMD》。
网友评论