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 相关文章推荐
jQuery1.3.2 升级到jQuery1.4.4需要修改的地方
Jan 06 Javascript
Javascript中自动切换焦点实现代码
Dec 15 Javascript
js导航菜单(自写)简单大方
Mar 28 Javascript
Javascript实现真实字符串剩余字数提示的实例代码
Oct 22 Javascript
JS(JQuery)操作Array的相关方法介绍
Feb 11 Javascript
微信小程序实现多宫格抽奖活动
Apr 15 Javascript
使用NestJS开发Node.js应用的方法
Dec 03 Javascript
使用apifm-wxapi模块中的问题及解决方法
Aug 05 Javascript
Vue实现开关按钮拖拽效果
Sep 22 Javascript
JS检测浏览器开发者工具是否打开的方法详解
Oct 02 Javascript
AngularJS实现多级下拉框
Mar 25 Javascript
js作用域及作用域链工作引擎
Jul 07 Javascript
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 批量替换html标签的实例代码
2013/11/26 PHP
PHP var关键字相关原理及使用实例解析
2020/07/11 PHP
网页常用特效代码整理
2006/06/23 Javascript
JS简单的轮播的图片滚动实例
2013/06/17 Javascript
js实现类似于add(1)(2)(3)调用方式的方法
2015/03/04 Javascript
javascript瀑布流式图片懒加载实例解析与优化
2016/02/23 Javascript
JavaScript实现简洁的俄罗斯方块完整实例
2016/03/01 Javascript
AngularJS中实现动画效果的方法
2016/07/28 Javascript
jQuery和JavaScript节点插入元素的方法对比
2016/11/18 Javascript
JS验证不重复验证码
2017/02/10 Javascript
JS变量中有var定义和无var定义的区别以及es6中let命令和const命令
2017/02/19 Javascript
nodejs个人博客开发第五步 分配数据
2017/04/12 NodeJs
详解VueJs前后端分离跨域问题
2017/05/24 Javascript
JavaScript实现的拼图算法分析
2019/02/13 Javascript
vue单文件组件无法获取$refs的问题
2020/06/24 Javascript
vue 解决uglifyjs-webpack-plugin打包出现报错的问题
2020/08/04 Javascript
js仿京东放大镜效果
2020/08/09 Javascript
详解Python中用于计算指数的exp()方法
2015/05/14 Python
Python输出各行命令详解
2018/02/01 Python
python3的url编码和解码,自定义gbk、utf-8的例子
2019/08/22 Python
Python使用APScheduler实现定时任务过程解析
2019/09/11 Python
Python编程快速上手——选择性拷贝操作案例分析
2020/02/28 Python
PyQt5.6+pycharm配置以及pyinstaller生成exe(小白教程)
2020/06/02 Python
五分钟带你搞懂python 迭代器与生成器
2020/08/30 Python
python中用ggplot绘制画图实例讲解
2021/01/26 Python
CSS3圆角和渐变2种常用功能详解
2016/01/06 HTML / CSS
html5+svg学习指南之SVG基础知识
2014/12/17 HTML / CSS
通信生自我鉴定
2014/01/18 职场文书
节水倡议书范文
2014/04/15 职场文书
征兵宣传标语
2014/06/20 职场文书
公司委托书怎么写
2014/08/02 职场文书
法定代表人身份证明书
2014/09/10 职场文书
毕业论文致谢格式模板
2015/05/14 职场文书
html+css实现分层金字塔的实例
2021/06/02 HTML / CSS
oracle索引总结
2021/09/25 Oracle
Linux中各个目录的作用与内容
2022/06/28 Servers