JS 模块化规范

在我们最初写代码的时候,引入JS文件用script标签来引入,并且在引入多个JS文件时,当前文件所依赖的JS文件必须放在前面。也就存在一个顺序的问题,而且这是由开发者去判断和把控的。而现在前端项目越来越复杂,难免会出现很多很多script标签引入JS,这无论对于开发和维护都有着一定的缺点。所以出现了模块化的概念。

模块化的形式有很多中,比如把某个特定功能封装成一个函数,但是存在着一个问题,很有可能会出现命名冲突等问题。针对这种问题,又有了对象的方式来模块化,这种不会出现命名冲突,但是外界却可以改变对象内的成员。又有了下面这种方式:

var obj = (function(){
    var name = 'liu';
    var job = 'Web developer';
    function sayName() {
        console.log(name + ' is a ' + job);
    }
    return {
        sayName: sayName
    }
})()

这样外界就不会修改没有暴露出来的对象内的变量。
上面这些是前端模块化的基础。目前通用的模块化规范主要有COMMONJSAMDCMD等等。

COMMONJS

COMMONJS主要是用于服务端的模块化规范,可以说NodeJS是它的最佳实践。看下面一个例子:

//导入一个文件系统模块,返回的是一个对象;
var fs = require('fs');
//调用对象的readFile方法,读文件。
fs.readFile('test.txt', function(data){
    console.log(data);
});

上面是一个读文件的操作,主要引入文件系统模块,这个是一个同步的过程。

当然,也可以自定义一个模块实现特定的功能。比如要实现一个Multi模块,可以这样来实现:

//multi.js
function multi(a ,b) {
    return a*b;
}

module.exports = {
    multi: multi
}
//moduleTest.js
var obj = require('./multi.js');

var res = obj.multi(3, 4);

console.log(res);

结果如下:
这里写图片描述

AMD

上面的COMMONJS规范不适合浏览器端的模块化开发,因为COMMONJS去请求模块是一个同步的过程,如果浏览器用这种规范去开发很可能会出现阻塞情况/假死情况。因此AMD规范就是为解决这种情况而出现的。
由于不是原生JS所支持的,所以AMD规范需要用到RequireJS库。
AMD的用法如下:
定义模块: define([依赖的模块], function(){ //自定义模块 });
引入模块:require([依赖的模块], function(){ //回调 })

在这里,需要说明的一点是:RequireJS是依赖前置,先去执行依赖的模块,然后再执行当前模块。

CMD

CMD典型的就是SeaJSSeaJSRequireJS实现上是差不多的,但是还是有一些区别,主要是在定义方式上和模块的执行时机上。
定义模块: define(function( require, exports, module ){ })
可以看到,SeaJS在定义模块的时候,并不会像RequireJS那样依赖前置,而是就近依赖的原则,需要的时候再去requireSeaJS主要是对模块先加载不执行,等到遇到require的时候才会去执行模块。
对于RequireJSSeaJS的差异可以看下面这个例子:

//c.js
define(function(require, exports, module){
    console.log('c Module');
    require('./b.js');
    console.log('c module finished');
})
//b.js
define(function(require, exports, module){
    console.log('b Module');
    require('./a.js');
    console.log('b module finished');
})
//a.js
define(function(require, exports, module){
    console.log('a Module');
})
//html文件
//requirejs文件部分代码
<script src="require.min.js" data-main="c.js"></script>  
//SeaJs文件部分代码
<script src="Sea.js"></script>
<script>seajs.use('./c');  </script>  

大家可以猜猜两种执行结果有什么不同,这里就不做验证了。

上面这些就是JS模块化的通用方法总结,当然,ES6中已经有了Module模块化的概念,后面还会再对这个进行整理。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章