使用RequireJS优化Web应用前端

随着网站逐渐变成“ 互联网应用程序”,嵌入网页的JavaScript代码越来越庞大,越来越复杂。
网页越来越像桌面程序,需要一个团队分工协作、进度管理、单元测试等等... ...开发者不得不使用软件工程的方法,管理网页的业务逻辑。
JavaScript模块化编程,已经成为一个迫切的需求。理想情况下,开发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块。
但是JavaScript不是一种模块化语言,它不支持“类”,更不要说是“模块”了。

1、原始写法

  <script type="text/javascript">
        function m1() { }
        function m2() { }
    </script >
上面的m1()和m2()组成一个模块,使用的时候直接调用就好了。
但是,这种做大的缺点很明显:“污染”了全局变量,无法保证不与其他的模块变量名发生冲突,而且模块成员之间看不吃直接关系。

2、对象写法:

  var module = new Object({
            _count: 10,
            m1: function () {
                alert( "我是方法m1" );
            },
            m2: function () {
                alert( "我是方法m2" );
            }
        });

函数m1() 和 m2()都封装在module对象里,使用的时候直接调用这个对象的属性。

缺点:这样的写法会暴露所有的模块成员,内部状态可以被外部改写。比如,外部代码可以直接改变内部计数器的值。

module._count = 1000; //改变计数器的值


3、立即执行函数

(immediately-invoked function expression,IIFE)可以达到不暴露私有成员的目的。

  <script type="text/javascript">
        var module1 = (function () {
            var _count = 0;
            var m1 = function () {
                //
            };
            var m2 = function () {
                //
            };
            return {
                m1: m1,
                m2: m2
            };
        })();
    </script >
使用上面的写法,外部代码无法直接读取内部的 _count 变量。

4、放大模式 

  <script type="text/javascript">
        var module1 = (function () {
            var count = 0;
            var m1 = function () {
                //
            };
            var m2 = function () {
                //
            };
            return {
                m1: m1,
                m2: m2
            };
        })();

        var module1 = (function (mod) {
            mod.m3 = function () {
                //
            };
            return mod;
        })(module1);
    </script >
上面这段代码为module1添加了一个新的方法m3(),然后返回新的module模块。

5、宽放大模式:(loose augmentation)

在浏览器环境中,模块的各个部分通常都是在网络上获取的,有时候无法知道哪个部分会先加载,如果采用上一节的写法,第一个执行的部分有可能加载一个不存在的空对象,这时候要采用“宽放大模式”。

  <script type="text/javascript">
        var module1 = (function () {
            var count = 0;
            var m1 = function () {
                //
            };
            var m2 = function () {
                //
            };
            return {
                m1: m1,
                m2: m2
            };
        })();

        var module1 = (function (mod) {
            mod.m3 = function () {
                //
            };
            return mod;
        })(window.module1 || {});
    </script >
与“放大模式”相比,“宽放大模式”就是“ 立即执行函数”的参数可以是 空对象

6、输入全局变量

独立性是模块的重要特点,模块内部最好不与程序的其他部分直接交互。
为了在模块内部调用全局变量,必须显式地将其他变量输入模块。

var module1 = (function ($, YAHOO) {
            //
        })(jQuery, YAHOO);
上面的module1模块需要使用jQuery和YUI库,就把这两个库(其实就是两个模块)当做参数输入module1。这样做除了保证模块的独立性,还使得模块之间的依赖关系变得明显。

7、模块的规范

为什么模块很重要?
因为有了模块,我们就可以方便的使用别人的代码,想要什么功能,就加载什么模块。
但是这样做需要有一个前提,那就是大家都必须以同样的方式编写模块,否则你有你的写法,我有我的写法,岂不乱套了!考虑到JavaScript模块现在还没有官方规范,这一点更为重要。
目前通行的JavaScript模块有两种,CommonJS和AMD。

8、CommonJS

2009年,美国程序员Ryan Dahl创造了node.js项目,将javascript语言用于服务器端编程。
这标志“JavaScript模块化编程”正式诞生,在浏览器环境下,没有模块也不是特别大的问题,毕竟网页程序的复杂度有限;但是在服务器端,一定要有模块,与操作系统和其他用应用程序互动,否则根本没办法编程。

node.js的模块系统,就是参照CommonJS规范实现的。在CommonJS中,有一个全局性的方法require(),用于加载模块。假设有一个数学模块math.js,可以像下面这样加载。

var math = require(‘math’); //加载模块
math.add(2,3); //5 调用模块内方法
需要知道require()方法用于加载模块的作用。

9、浏览器环境

有了服务器模块后,很自然的,大家就想要客户端模块。而且最好两者能够兼容,一个模块不用修改,在服务器和浏览器都可以运行。
但是,由于一个重大的局限,使得CommonJS规范不使用于浏览器。
问题来了,还是这段代码:

var math = require(‘math’); //加载模块
math.add(2,3); //5 调用模块内方法
运行到第二行的时候,必须等待math.js加载完成。也就是说,如果加载时间很长,整个应用就会停在那里。也就是说,如果加载时间很久,整个应用就会停在那里等待。
这对服务器端不是问题,因为所有的模块都存在本地硬盘,可以同步加载完成,等待时间就是硬盘读取的时间。但是,对于浏览器这却是个大问题,因为模块都在服务器端,等待时间取决于网速的快慢,可能要等很长时间,浏览器处于“假死”状态。

因此,浏览器端的模块,不能采用“同步加载”(synchronize),只能采用“异步加载”(asynchronous)。这就是AMD规范诞生的背景。

10、AMD

AMD是“asynchronous Module Definition”的缩写,意思是“异步模块定义”。它采用异步方式加载模式,模块的加载不影响他后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成后,这个回调函数才会运行。

AMD也采用require()语句加载模块,但是不同于CommonJS,他要求两个参数:
require([module],callback);
第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功之后的回调函数。如果将前面的代码改成AMD形式,就是下面这样:

require(['math'],function(math){
math.add(2,3);
});

math.add()与math模块加载不上同步的,浏览器不会发生假死。所以很显然,AMD比较适合浏览器环境。
目前,主要有两个JavaScript库实现了AMD规范:require.js和curl.js。



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值