现如今,web项目越做越大,前端的各种文件也愈发膨胀,随便一个js文件都可能写到1000多行,其中的方法数十个,变量甚至几十个,由于javascript中没有java、c中的块级作用域的概念,如果没有合理的方式编写,都将其写成全局变量,万一一个页面要是引用了多个js文件,而且不是一个人写的,那乐子可大了去了,变量名重复是必不可少的,经常导致一些莫名的bug出现。而且后期的维护也是要人老命的,如果你需要修改或者添加一些变量或者方法,你得十分小心。
针对上面的困境,我们希望能有有一种方式可以结构化管理所有变量和方法,同时轻松实现代码扩展与维护, 蓦然发现合理的编写js代码是多么的重要。
解决思路
一、原来的方式
1 var count = 25; 2 var price = 3.4; 3 var hasMoney = 100; 4 function cost(count, price){ 5 return count*price; 6 }; 7 8 function giveChange(){ 9 return hasMoney-cost(count, price);10 }
上面的方式是最直观最便捷的写法,但是这种写法的代价上面说了,是我们所不愿承受的。我们希望所有变量都能有个统一的管理者,这时候“命名空间”就闪亮登场了。
二、对象写法
var calculateMoney = { count : 25, prices : 3.4, hasMoney : 100, cost : function(count, price){ return count*price; }, giveChange : function(){ return this.hasMoney-this.cost(this.count, this.prices) } }
看到这,是不是有些小激动,写法方式很简单,就可以大大的避免了变量的全局污染。不过这种方式还是有些缺陷:暴露了对象中所有的变量和方法。我们更希望只有我们愿意给别人看到的那部分,别人才能看得到。这个要实现也很简单,请看接着看。
三、立即执行函数写法
1 var calculateMoney = (function(){ 2 var _count = 25; 3 var _prices = 3.4; 4 var _hasMoney= 100; 5 6 function _cost(_count , _prices ){ 7 return _count*_prices; 8 } 9 10 function _giveChange(){11 return this.hasMoney-_cost(_count, _prices);12 } 13 return {14 hasMoney: _hasMoney,15 giveChange : _giveChange16 } 17 })();
上面的写法就很完美的解决了隐藏不想给别看的变量和方法,看上去,我们的工作已经很完美的,只是向外提供了hasMoney变量和giveChange方法,而_cost方法是外界所无法接触到的。但是,如果是一个很大的模块,我们要分成很多个小的模块编写,这些模块又该如何做到继承和扩展呢?如果模块这些模块的加载顺序不一,你无法确定上面的模块是否创建,你又该如何扩展? 某个模块都需要引用一个变量又该怎么办?突然感觉到自己的渺小,太多的问题等待着我们来解决,但是一旦我们深入的研究得到一份完美的解决方案时,这将为我们的项目带来多少便利,节省我们许多的时间,可以不用加班,回家陪陪女朋友或者老婆小孩那该是多好。废话补多少了,我们来看看下面这种方式
四、Module模式
1 var calculateMoney1 = (function(){...})(); 2 var calculateMoney2 = (function(cal, hasMoney){ 3 var _count = 25; 4 var _prices = 3.4; 5 6 function _cost(_count , _prices ){ 7 return _count*_prices; 8 } 9 10 cal.giveChange = function(){11 return hasMoney-_cost(_count, _prices);12 } 13 return cal;14 })(calculateMoney1 || {}, 100);
这种Module模式(module模式详见:)的好处显而易见:
- 模块化,可重用
- 封装了变量和function,和全局的namaspace不接触,松耦合
- 只暴露可用public的方法,其它私有方法全部隐藏
Module模式是目前我个人比较推荐,我在实际工作中,没有人教过我,我慢慢摸索到“对象写法”,后来看到大叔博客中提到的Moduel模式,欣喜若狂,感觉自己真是太菜了。
至于javascript的模块化编程,上面只是提到一部分,还有些更加高级些的我也正在摸索,如:如果js文件存在依赖,如果确定需要依赖的模块已被加载?如何动态加载模块?等等。