前端技术Web前端之路前端开发

前端模块化

2017-10-08  本文已影响119人  淘淘笙悦

一开始,javascript 的出现只是作为简单脚本语言来实现简单的页面逻辑,而随着互联网的发展和 web 2.0 时代的到来,越来越多的交互逻辑被放到了客户端实现,这就使得我们的 js 脚本文件变得越来越复杂,这时候需要有一种‘模块化’的思想来组织我们的 js 代码。
javascript 并不是一种模块化语言,它不支持‘类’和‘模块’,尽管在 es6 中已经有了‘类’和‘模块’的概念,但要等到各大浏览器都支持,还需要很长的一段时间。

一.函数
最简单的实现模块的方式是使用函数。

function add(x,y){
    return x+y;
}
function minus(x,y){
    return x-y;
}

如上将两个函数放在同一个 js 文件中,就实现了一个模块,使用的时候直接调用即可,如 add(1,2)。
但是这样做会污染了全局变量,无法保证各模块间的变量名不冲突,并且模块成员之间看不出关系。

二.对象
再高级一点的实现模块的方式是使用对象。

var myModule={
    a:1,
    b:2,
    add:function(x,y){
        return x+y;
    },
    minus:function(x,y){
        return x-y;
    }
}

如上,一般是使用一个对象实现一个模块,调用时直接使用对象调用属性的方式即可,如 myModule.add(1,2) 。
使用这种方式,只要保证模块之间的名字不同,便可以避免模块间的变量名冲突,并且模块内的成员也有了一定的关系。但是使用这种方式的缺陷是外部可以随意更改模块内的成员,如可以直接在外部使用 module_text.a=0 ,更改模块内变量。

三.立即执行函数
更更高级的方式,是使用立即执行函数,在立即执行函数中返回一个对象。

var myModule=(function(){
    var a=1,b=2;

    function add(x,y){
        return x+y;
    }
    function minus(x,y){
        return x-y;
    }

    return {
        add:add,
        minus:minus
    }
})()

如上,是通过立即执行函数来返回一个对象并赋给一个变量,调用方法对象模式,本质上这是一种对象模式。
只是使用这种方法,我们可以通过控制返回对象中的变量来达到隐藏模块内成员的目的,上述代码中在外部我们并不能访问和修改模块内变量 a、b 的值。

四.CommonJS
自2009年 node.js 诞生后,javascript 模块化编程正式进入人们的视野,而 node.js 的模块化系统,便是参照 CommonJS 规范实现的。
在 CommonJS 规范中,一个单独的文件就是一个模块,每个模块都有各自的作用域,即在一个模块(文件)中的变量、函数是私有的,外部无法访问。
在模块内部,module 变量对象代表当前模块,它的 exports 属性也是一个对象,代表对外的接口,所以我们将需要对外暴露的内容放进 module.exprots 对象即可。

//文件名为myModule
var a=1,b=2;

function add(x,y){
    return x+y;
}
function minus(x,y){
    return x-y;
}
module.exports = {
    add: add,
    minus: minus
}

然后我们可以通过 require 方法加载模块:

//main.js文件中
var myModule = require('./myModule.js');

console.log(myModule.minus(2,1)); // 1

但是,由于 require 加载模块的方式是同步加载,使得 CommonJS 规范不适合在浏览器端使用。在服务器端同步加载模块,等待时间取决于硬盘的读取时间,而在浏览器端同步加载模块,等待时间取决于网速快慢,这使得在等待加载模块的过程中,浏览器会处于‘假死’的状态。
所以在浏览器端的模块化编程,一般采用 AMD 和 CMD 规范。

五.AMD
AMD 即 Asynchronous Module Definition,中文名是异步模块定义的意思。
AMD 规范采用 define 函数定义模块
define(id ?,dependencies ?,factory);
第一个参数 id 是一个字符串文字,指定要定义的模块的 id。此参数是可选的,如果不存在,则模块 id 应默认为加载程序请求给定响应脚本的模块的 id。
第二个参数是模块 ids 的数组文字,指被定义的模块所需的依赖关系。此参数是可选的。
第三个参数 factory 是一个应该执行的函数来实例化模块或一个对象。如果 factory 是一个函数,它只能执行一次。如果 factory 是一个对象,则该对象应该被分配为模块的导出值。

define('myModule',['moduleA','moduleB'], function(moduleA,moduleB){
    function doIt(){
        moduleA.doSomething();
        moduleB.doSomething();
    }

    return {
        doIt : doIt
    };
});

然后可以使用 require 函数加载模块,require 接收两个参数。
第一个参数为所依赖的模块标识数组;
第二个参数为回调函数,只有当全部的依赖模块加载完成后才会执行;

require(['myModule'], function (myModule){
    myModule.doIt()
});

六.CMD
CMD 即 Common Module Definition,中文名是通用模块定义的意思。
CMD 规范推崇的是一个模块一个文件,遵循统一的写法。
同样的 CMD 规范采用 define 函数定义模块
define(factory)
接收一个 factory 参数,可以是一个函数、对象或字符串。

define(function(require, exports, module) {
    var $ = require('jquery.js')
    
    //do something
});
上一篇 下一篇

猜你喜欢

热点阅读