JavaScript模块化思想之入门篇

在写正文以前先写一点废话,从我大三下学期正式接触前端到如今,已经六个月了。本身从HTML,CSS,简单的JS验证开始,一点点开始走入前端的世界。愈加的感受前端这一领域散发着无穷的魅力,也许这和我真心喜好前端分不开。有些人总爱说前端技术迭代快,认为这是前端的一个缺点,但我偏偏认为这正是前端的魅力所在,充满着朝气和活力。html


 

小小感慨一下,如今开启个人JavaScript模块化入门之旅,以前本身作的都是小项目,简单的写写JS验证,给按钮添加一些绑定事件等等。随着本身对JS学习和使用的深刻,渐渐的发现两个问题:
    (1)我以前写的JS代码重用性很低
    (2)功能分散,举个栗子,我要获取当前日期,也要获取当前日期加1也就是明天的日期,以前我做为两个独立互不相干的函数去写,但如今想一想,其实他们均可以归为一个日期对象的两个方法,把它们绑定在一个对象上,做为它的两个方法,不是更好么?

若是想好好了解一下JavaScript模块化,推荐阮一峰老师的文章。

 
1. 首先,咱们须要明白为何要用模块化?

功能都是为了解决需求的。模块化能够带来的优势有如下几点:
(1) 可维护性。举个例子,若是咱们把未使用模块化的代码比做油和水混合在了一块儿,模块化以后的代码就好像油和水的分层,油就是油,水就是水,这样的代码层次清晰,功能分明。彷佛用油和水必然分层的现象来指代JS模块化的大势所趋也很合适。
(2) 命名空间。这里须要谈到JS的做用域。又涉及到了做用域链。若是对做用域链不熟悉的同窗能够移步个人另外一篇文章“ 理解JavaScript中的做用域链”。JS中是靠函数来区分做用域的。每一个函数都有一个做用域链。若是咱们把全部的代码都揉到一块儿,代码行数少还行,多了就不免会形成“命名空间污染”。
(3) 可复用性。当咱们明白了命名空间,借助命名空间咱们就能够实现对模块代码的封装,这样咱们就能够在任何咱们须要这个功能的时候直接去引用这个功能模块。

接下来,用个人JS代码之路演示一下如何使代码模块化:
 
(1)原始时代:把全部的要用到的JS代码都堆砌在该页面的一对<script>标签中。
1 function f1(){
2      //函数体
3 }
4 function f2(){
5      //函数体
6 }
这样写的缺点:代码基本没有什么复用性能够,应该还会存在和页面隅合度过高的问题。还须要去考虑各类做用域的问题。
 
(2)古时代:思路就是把模块写成一个对象。好比咱们要写一个能控制页面音乐播放,中止,下一首,上一首的功能。就能够封装一个musicPlayer对象
 1 // 将基本的方法封装起来
 2             var musicPlayer = {
 3 
 4                 var musicDom = null, //播放器对象
 5                 var musicList = [], //存放歌曲列表
 6 
 7                 // 初始化音乐播放器
 8                 var init =  function(){
 9                     
10                 },
11 
12                 // 添加一首歌曲
13                 var add = function(src){
14                    
15                 },
16 
17                 // 根据数组下标决定播放哪一首,索引index从0开始
18                 var play = function(index){
19                     
20                 },
21 
22                 // 暂停播放
23                 var stop = function(){
24                     
25                 },
26 
27                 // 下一首
28                 var next = function(){
29 
30                 },
31 
32                 // 上一首
33                 var prev = function(){
34 
35                 }
36             };
这时候,就已经能够称之为一个模块了,在全局做用域中,咱们只向window对象上绑定了一个musicPlayer对象,以后咱们就可使用musicPlayer加'.'的形式来调用里面的方法。如“musicPlayer.init();”
这种方式也有一个缺点,就是咱们不能去控制咱们想暴露的内容,而且在外部能够改写musicPlayer对象的内部方法和变量。
 
(3)现代。包含IIFE(当即执行函数),放大模式,宽放大模式,输入全局变量
  
  除了IIFE,其余的三种我以前都没有接触过,在这里简单谈谈个人理解。
 
- IIFE(Immediately-Invoked Function Expression)
 1 // 建立一个当即执行的匿名函数
 2 // 该函数返回一个对象,包含你要暴露的属性
 3 // 以下代码若是不使用当即执行函数,就会多一个属性i
 4 // 若是有了属性i,咱们就能调用counter.i改变i的值
 5 // 对咱们来讲这种不肯定的因素越少越好
 6 
 7 var counter = (function(){
 8   var i = 0;
 9 
10   return {
11     get: function(){
12       return i;
13     },
14     set: function( val ){
15       i = val;
16     },
17     increment: function() {
18       return ++i;
19     }
20   };
21 }());
22 
23 // counter实际上是一个对象
24 
25 counter.get(); // 0
26 counter.set( 3 );
27 counter.increment(); // 4
28 counter.increment(); // 5
29 
30 counter.i; // undefined i并非counter的属性
31 i; // ReferenceError: i is not defined (函数内部的是局部变量)

从以上的代码能够看出,counter中其中并无i这个属性,它只有return 中暴露出来的内容。这样咱们就对i实现了私有。前端

 
- 放大模式
我对放大模式的理解就是把原函数看成参数传递到IIFE中,而后给原函数添加新的扩展方法,把扩展后的函数返回。就实现了对原函数的“放大”。
1 var module1 = (function (mod){
2   mod.m3 = function () {
3     //...
4   };
5   return mod;
6 })(module1);

在这个例子中,就给module1添加了一个新的方法m3并返回。数组

 

- 宽放大模式
宽放大模式就是在放大模式的基础上新增了一个特性:IIFE的参数能够是空对象。
1 var module1 = ( function (mod){
2   //...
3   return mod;
4 })(window.module1 || {});

IIFE传入的参数:若是window.module1有定义,就传入该参数,若是为undefined就传入一个空对象。模块化

 

- 输入全局变量
若是咱们要在IIFE内使用全局变量,最好把全局变量经过参数传递进去。
1 var module1 = (function ($, YAHOO) {
2   //...
3 })(jQuery, YAHOO);

如上所示的代码将jQuery和YUI两个库的全局变量看成参数传入了module1。函数

相关文章
相关标签/搜索