JavaScript 模块化编程(笔记)


Posted in Javascript onApril 08, 2015

一直对JS都是一知半解,最近遇到这方面问题,所以在网上学习了一下,现在还没有完全明白,先贴出笔记;

第一章 JavaScript模块化编程

(一):模块的写法

一 原始写法
// 模块就是实现特定功能的一组方法;只要把不同的函数(以及记录状态的变量)简单地放在一起,就算是一个模块;
    function m1(){
        // ...
    }
    function m2(){
        // ...
    }
// 上面的函数m1()和m2(),组成一个模块;使用时直接调用就行;
// 缺点:"污染"了全局变量; 无法保证不与其他模块发生变量名冲突,而且模块成员之间看不出直接关系;

二 对象写法

// 把模块写成一个对象,所有的模块成员都放到这个对象里面;
  var module = new Object({
    _count:0,
    m1:function(){
      // ...
    },
    m2:function(){
      // ...
    }
  });
// 上面的函数m1()和m2(),都封装在module对象里;使用时直接调用这个对象的属性;
  module.m1();
// 但是,这样的写法会暴露所有模块成员,内部状态可以被外部改写;
  module._count = 4;

三 立即执行函数写法

var module = (function(){
    var _count = 0;
    var m1 = function(){
      // ...
    };
    var m2 = function(){

    };
    return {
      m1:m1,
      m2:m2
    };
  })();
// 使用上面的写法,外部代码无法读取内部的_count变量;
  console.info(module._count); // undefined;
// 上面的写法就是JavaScript模块的基本写法;

四 放大模式

// 如果模块很大,必须分成几个部分,或者一个模块需要继承另一个模块,这时就有必要采用"放大模式";
  var module = (function(mod){
    mod.m3 = function(){
      // ...
    };
    return mod;
  })(module);
// 上面的代码为module模块添加了一个新方法m3(),然后返回新的module模块;

五 宽放大模式

// 在浏览器环境中,模块的各个部分通常都是从网上获取的,有时无法知道哪个部分会先加载;
// 如果采用上一节的写法,第一个执行的部分有可能加载一个不存在的空对象,这时就要采用"宽放大模式";
  var module = (function(mod){
    // ...
    return mod;
  })(window.module || {});
// 与"放大模式"相比,"宽放大模式"就是"立即执行函数"的参数可以是空对象;

六 输入全局变量

// 独立性是模块的重要特点,模块内部最好不与程序的其他部分直接交互;
// 为了在模块内部调用全局变量,必须显式地将其他变量输入模块;
  var module = (function($,YAHOO){
    // ...
  })(jQuery,YAHOO);
// 上面的module模块需要使用jQuery库和YUI库,就把这两个库(其实是两个模块)当作参数输入module;
// 这样做除了保证模块的独立性,还使得模块之间的依赖关系变得明显;

第二章 JavaScript模块化编程(二):AMD规范

一 模块的规范
// 目前,通行的JavaScript模块规范共有两种:CommonJS和AMD;

二 CommonJS
// node.js将javascript语言用于服务器端编程,这标志"JavaScript模块化编程"正式诞生;
// node.js的模块系统,就是参照CommonJS规范实现的;
在CommonJS中,有一个全局性方法require(),用于加载模块;
    var math = require('math');        // 加载模块;
    math.add(2,3);                    // 调用模块方法=>5;

三 浏览器环境
// 上一节的代码在浏览器中运行会有很大的问题;
    var math = require('math');
    math.add(2,3);
// 问题:必须在require('math')等math.js加载完成,才会执行math.add(2,3);
// 所以浏览器的模块,不能采用"同步加载",只能采用"异步加载";==>AMD;

四 AMD
AMD(Asynchronous Module Definition)异步模块定义;
// 采用异步加载模块,模块的加载不影响它后面语句的运行,所有依赖这个模块的语句,都定义在一个回调函数中,
// 等加载完成之后,这个回调函数才会运行;
// AMD也采用require()语句加载模块,但是它要求两个参数:
    require([module],callback);
// module:是一个数组,里面的成员就是要加载的模块;
// callback:是加载成功之后的回调函数;
    require(['math'],function(math){
        math.add(2,3);
    });
// math.add()与math模块加载不是同步的,浏览器不会发生假死;所以,AMD比较适合浏览器环境;

第三章 JavaScript模块化编程(三):require.js的用法
一 为什么使用require.js
// 需要依次加载多个js文件;
// 缺点:
// 1.加载的时候,浏览器会停止网页渲染,加载文件越多,网页失去响应的时间就会越长;
// 2.由于js文件之间存在依赖关系,因此必须严格保证加载顺序,当依赖关系很复杂的时候,代码的编写和维护都会变得困难;
// 所以require.js解决了这两个问题:
// 1.实现js文件的异步加载,避免网页失去响应;
// 2.管理模块之间的依赖性,便于代码的编写和维护;

二 require.js的加载
1.加载require.js
    <script scr="js/require.js" defer async="true"></script>
// async属性表明这个文件需要异步加载,避免网页失去响应;IE不支持这个属性,只支持defer,所以把defer也写上;
2.加载main.js
    <script src="js/require.js" data-main="js/main"></script>
// data-main属性的作用是,指定网页程序的主模块=>main.js,这个文件会第一个被require.js加载;
// 由于require.js默认的文件后缀名是js,所以可以把main.js简写成main;

三 主模块main.js的写法
1.如果main.js不依赖任何其他模块,可以直接写入JavaScript代码;
// main.js
    alert('加载成功!');
2.如果main.js依赖于模块,这时就要使用AMD规范定义的require()函数;
// main.js
    require(['moduleA','moduleB','moduleC'],function(moduleA,moduleB,moduleC){
        // ...
    })
// require()函数接收两个参数:
// 参数一:数组,表示所依赖的模块,即主模块依赖的三个模块;
// 参数二:回调函数,当前面指定的模块都加载成功后,它将被调用;加载的模块会以参数形式传入该函数,从而在回调函数内部可以使用这些模块;
// require()异步加载模块,浏览器不会失去响应;它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题;
实例:
    require(['jquery','underscore','backbone'],function($,_,Backbone){
        // ...
    });

四 模块的加载
// 使用require.config()方法,可以对模块的加载行为进行自定义;
// require.config()就写在主模块(main.js)的头部;
// 参数就是一个对象,这个对象的paths属性指定各个模块的加载路径;
// 设定以下三个模块的文件默认和main.js在用一个目录;
    require.config({
        paths:{
            "jquery":"jquery.min",
            "underscore":"underscore.min",
            "backbone":"backbone.min"
        }
    });

// 如果加载的模块和主模块不在同一个目录,就要逐一指定路径;
    require.config({
        paths:{
            "jquery":"lib/jquery.min",
            "underscore":"lib/underscore.min",
            "backbone":"lib/backbone.min"
        }
    });
// 或者直接改变基目录(baseUrl)
    require.config({
        baseUrl:"js/lib",
        paths:{
            "jquery":"jquery.min",
            "underscore":"underscore.min",
            "backbone":"backbone.min"
        }
    });

// 如果模块在另一台主机上,也可以直接指定它的网址
    require.config({
        paths:{
            "jquery":"https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min"
        }
    });
// require.js要求,每个模块是一个单独的js文件;这样的话,如果加载多个模块,就会发出多次HTTP请求,会影响网页的加载速度;
// 因此,require.js提供了一个优化工具,当模块部署完毕以后,可以用这个工具将多个模块合并在一个文件中,减少HTTP请求数;

五 AMD模块的写法

// require.js加载的模块,采用AMD规范,也就是说,模块必须按照AMD的规定来写;
// 具体来说,就是模块必须采用特定的define()函数来定义;如果一个模块不依赖其他模块,那么可以直接定义在define()函数中;
// 在math.js中定义math模块
// math.js
    define(function(){
        var add = function(x,y){
            return x+y;
        };
        return {
            add:add
        };
    });
// 在main.js中加载math模块
    require(['math'],function(math){
        alert(math.add(1,1));
    });
// 如果这个模块还依赖其他模块,那么define()函数的第一个参数,必须是一个数组,指明该模块的依赖性;
// math.js
    define(['myLib'],function(myLib){
        function foo(){
            myLib.doSomething();
        }
        return {
            foo:foo
        };
    });
// 当require()函数加载上面这个模块的时候,就会先加载myLib.js文件;

六 加载非规范的模块

// 加载非规范的模块,在用require()加载之前,要先用require.config()方法,定义它们的一些特征;
    require.config({
        shim:{
            'underscore':{
                exports:'_'
            },
            'backbone':{
                deps:['underscore','jquery'],
                exports:'Backbone'
            }
        }
    });
// require.config()接收一个配置对象,这个对象除了有前面说过的paths属性之外,还有一个shim属性,专门用来配置不兼容的模块;
// (1).定义deps数组,表明该模块的依赖性;
// (2).定义exports值(输出的变量名),表明这个模块外部调用时的名称;
比如:jQuery的插件
    shim:{
        'jquery.scroll':{
            deps:['jquery'],
            exports:'jQuery.fn.scroll'
        }
    };

七 require.js插件

1.domready:可以让回调函数在页面DOM结构加载完成之后运行;
    require(['domready!'],function(doc){
        // called once the DOM is ready;
    })   
2.text和image:允许require.js加载文本和图片文件;
    define(['text!review.txt','image!cat.jpg'],function(review,cat){
        console.log(review);
        document.body.appendChild(cat);
    });

Javascript 相关文章推荐
关于this和self的使用说明
Aug 01 Javascript
js中判断Object、Array、Function等引用类型对象是否相等
Aug 29 Javascript
JavaScript高级程序设计(第3版)学习笔记12 js正则表达式
Oct 11 Javascript
jquery增加时编辑jqGrid(实例代码)
Nov 08 Javascript
jquery 模板的应用示例
Nov 12 Javascript
js中不同的height, top的区别对比
Sep 24 Javascript
javascript同步服务器时间和同步倒计时小技巧
Sep 24 Javascript
浅谈JavaScript 标准对象
Jun 02 Javascript
分享19个JavaScript 有用的简写写法
Jul 07 Javascript
非常实用的jQuery代码段集锦【检测浏览器、滚动、复制、淡入淡出等】
Aug 08 jQuery
JavaScript实现商品评价五星好评
Nov 30 Javascript
Vue全家桶入门基础教程
May 14 Vue.js
JavaScript DOM事件(笔记)
Apr 08 #Javascript
javascript笛卡尔积算法实现方法
Apr 08 #Javascript
JavaScript获取指定元素位置的方法
Apr 08 #Javascript
javascript跨域原因以及解决方案分享
Apr 08 #Javascript
JavaScript 里的类数组对象
Apr 08 #Javascript
cookie的secure属性详解
Apr 08 #Javascript
jQuery简单tab切换效果实现方法
Apr 08 #Javascript
You might like
PHP+jQuery+Ajax实现用户登录与退出
2015/04/27 PHP
Zend Framework动作助手Url用法详解
2016/03/05 PHP
PHP实现支付宝即时到账功能
2016/12/21 PHP
js Date自定义函数 延迟脚本执行
2010/03/10 Javascript
JavaScript高级程序设计 读书笔记之八 Function类及闭包
2012/02/27 Javascript
jquery实现文字由下到上循环滚动的实例代码
2013/08/09 Javascript
js判断为空Null与字符串为空简写方法
2014/02/24 Javascript
js登录弹出层特效
2014/03/07 Javascript
yui3的AOP(面向切面编程)和OOP(面向对象编程)
2015/05/01 Javascript
JavaScript检测上传文件大小的方法
2015/07/22 Javascript
原生js实现百叶窗效果及原理介绍
2016/04/12 Javascript
原生js实现回复评论功能
2017/01/18 Javascript
React Native实现进度条弹框的示例代码
2017/07/17 Javascript
使用form-create动态生成vue自定义组件和嵌套表单组件
2019/01/18 Javascript
vue如何获取自定义元素属性参数值的方法
2019/05/14 Javascript
解决Nuxt使用axios跨域问题
2020/07/06 Javascript
[02:27]DOTA2英雄基础教程 莱恩
2014/01/17 DOTA
python 将字符串转换成字典dict
2013/03/24 Python
Python中的数据对象持久化存储模块pickle的使用示例
2016/03/03 Python
使用PyInstaller将python转成可执行文件exe笔记
2018/05/26 Python
Python3.6+Django2.0以上 xadmin站点的配置和使用教程图解
2019/06/04 Python
jupyter notebook 的工作空间设置操作
2020/04/20 Python
Python如何解除一个装饰器
2020/08/07 Python
Django+Django-Celery+Celery的整合实战
2021/01/20 Python
CSS3 3D旋转rotate效果实例介绍
2016/05/03 HTML / CSS
日本钓鱼渔具和户外用品网上商店:naturum
2016/08/07 全球购物
BISSELL官网:北美吸尘器第一品牌
2019/03/14 全球购物
FILA德国官方网站:来自意大利的体育和街头服饰品牌
2019/07/19 全球购物
优秀毕业大学生推荐信
2013/11/13 职场文书
新闻系毕业生推荐信
2013/11/16 职场文书
党的群众路线教育实践活动心得体会900字
2014/03/07 职场文书
聚美优品的广告词
2014/03/14 职场文书
个人贷款担保书
2014/04/01 职场文书
铁路安全反思材料
2014/12/24 职场文书
《和时间赛跑》读后感3篇
2019/12/16 职场文书
解析redis hash应用场景和常用命令
2021/08/04 Redis