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


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

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

 
1. 首先,我们需要明白为什么要用模块化?

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

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

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

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

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

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

IIFE传入的参数:如果window.module1有定义,就传入该参数,如果为undefined就传入一个空对象。

- 输入全局变量
如果我们要在IIFE内使用全局变量,最好把全局变量通过参数传递进去。
 var module1 = (function ($, YAHOO) {
  //...
})(jQuery, YAHOO);

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

 

JavaScript模块化思想之入门篇的更多相关文章

  1. javascript模块化编程 从入门到实战

    <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8& ...

  2. JavaScript模块化思想

    1. 首先,我们需要明白为什么要用模块化? 功能都是为了解决需求的.模块化可以带来的优点有以下几点: (1)可维护性.举个例子,如果我们把未使用模块化的代码比作油和水混合在了一起,模块化之后的代码就好 ...

  3. JavaScript模块化思想requireJS的使用

    1. 使用require.js的意义   (1)实现JS文件的异步加载,避免网页因为加载JS文件缓慢造成网页未响应 (2)管理模块之间的依赖性,便于代码的编写和维护.页面中只需要引入require.j ...

  4. JavaScript模块化思想之CommonJS、AMD、CMD、UMD

    前一篇文章了解了什么是模块,这一篇就简单介绍一下如何定义并加载一个模块. 我所了解的三种模块加载方式分别是CommonJS.AMD和CMD 网上关于这三种模块加载方式讲解的文章很多,我就简单的做个介绍 ...

  5. 造轮子和用轮子:快速入门JavaScript模块化

    造轮子和用轮子:快速入门JavaScript模块化 前言 都说“不重复造轮子”,就像iPhone——它除了打电话还可以播放音乐——但是工程师不用从零开始做一个音乐播放功能,也许只要在iPhone的系统 ...

  6. JavaScript入门篇 编程练习

    编程挑战 一.定义"改变颜色"的函数 提示: obj.style.color obj.style.backgroundColor 二.定义"改变宽高"的函数 提 ...

  7. 慕课网JavaScript入门篇课程笔记

    1.js注释很重要 单行注释,在注释内容前加符号 “//”. <script type="text/javascript"> document.write(" ...

  8. 开心菜鸟系列----函数作用域(javascript入门篇)

      1 <!DOCTYPE html>   2 <html>   3 <script src="./jquery-1.7.2.js"></ ...

  9. 开心菜鸟系列----变量的解读(javascript入门篇)

                       console.info(         console.info(window['weiwu'])          console.info(window. ...

随机推荐

  1. Linux常用基本命令(xargs )

    xargs:能够将管道或者标准输入传递的数据转换成xargs命令后面跟随的参数 ghostwu@dev:~/linux/cp$ ls ghostwu_hardlink ghostwu_home gho ...

  2. org.springframework.web.util.NestedServletException Handler processing failed; n

    因为谷歌的lists不支持或使用, 所有要改成java的list工具 谷歌list使用: import com.google.common.collect.Lists; .... Lists.newA ...

  3. nodejs 知识总结

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.添加模块:保存到package.json文件中; # npm install vue --save    注意 ...

  4. 葡萄城报表V11 SP2新版本震撼发布!

    葡萄城报表正式发布 v11.2 版本,强势推出国内首创的基于HTML5的在线报表设计器,从此报表设计告别桌面应用程序,随时随地修改报表,真正跨平台操作,从而使任何报表用户更快速的响应报表业务变化! 在 ...

  5. 稳聘App设计图分享

    摘要||潜心学习,无限开源,我是鸟窝,一只憨厚的鸟,联系我加微信:jkxx123321 很早期就想筹划上线一款招聘类App,一拖再拖,先做还没有上线. 下面的设计原图,为我UI徒弟所做,在此,表示万分 ...

  6. 类与接口(三)java中的接口与嵌套接口

    一.接口 1. 接口简介 接口: 是java的一种抽象类型,是抽象方法的集合.接口比抽象类更加抽象的抽象类型. 接口语法: [修饰符] [abstract] interface 接口名 [extend ...

  7. Python+Selenium笔记(二):配置谷歌+IE环境

    #有的时候可能要访问外国的网站下载资料或工具,这时可能出现各种问题,例如谷歌人机验证显示不了.网站打不开等,建议使用一个FQ软件 (一)  设置IE (1)   http://docs.seleniu ...

  8. JavaScript动画:offset和匀速动画详解(含轮播图的实现)

    本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. offset简介 我们知道,三大家族包括:offset/scroll/c ...

  9. Chrome 无法加载Shockwave Flash

    遇到的问题 Chrome经常出现上图的提示,把Adobe Flash重装了N多次也是无法解决此问题,经多次尝试终于解决此问题. 解决方法 1.在Chrome地址栏输入:chrome://plugins ...

  10. 利用Maven插件将依赖包、jar/war包及配置文件输出到指定目录

    写在前面 ​ 最近遇到一个朋友遇到一个项目需要将maven的依赖包和配置文件分开打包然后用脚本执行程序.这样的好处在于可以随时修改配置文件内容及查看jar包.如果将所有打成一个jar包就会有个问题(例 ...