JavaScript:模块化及模块化规范

什么是JavaScript的模块化?模块化模块化,那就是先有模块,模块是什么?模块就是将一个复杂的程序按照一定的规则拆分并单独封装成一个块或者文件,每一个块内都有自己的内部数据和方法,并且会向外暴露一些接口或方法与其它模块之间相互联系。模块化就是程序在运行编码过程中,就是按照每个模块一个一个逐一编码,最后形成一整个项目。当然了,这些许许多多的模块不能胡乱的编写和使用,那么就需要一定的规范了,下面给各位开发者介绍几种模块化的规范:

一、script标签

看到这个,是不是异常亲切,script标签作为JavaScript文件加载的最原始的方式,拥有当之无愧的一哥地位。如果将最初的一个JS文件看成是一个模块,那么这些文件内部所暴露的接口一般都是在全局作用域下,而且这些JS文件的调用顺序还不能出错,例如:index.js文件必须依赖于jquery.js文件才能执行,那么引入的时候必须遵循jquery.js文件在index.js文件之前,否则index.js就无法正常执行。

<script src="jquery.js"></script>
<script src="index.js"></script>

这种''一哥''传统的加载方式有很多缺点:因为接口都是暴露在全局作用域下,所以会污染全局作用域;并且引用关系必须由开发者自己处理引用的先后顺序;项目一旦过大,引入文件过多会导致混乱而难以维护。

二、CommonJs规范

CommonJs规范最初是用在服务器端的node的,它有四个重要的环境变量为模块化的实现提供支持:`module`、`exports`、`require`、`global`,基本的调用方式如下:

// 导入
require("module");
require("../index.js");

// 导出
exports.getUserInfo = function() {};
module.exports = userInfo;

这种方式的优点在于:操作简单粗暴;模块可以高度复用;解决了"一哥"污染全局变量的问题;

但是缺点在于不适合在浏览器端模块加载,原因在于CommonJS所用的模块加载方式是同步的方式,同步就意味着阻塞,在模块化文件都存在本地磁盘的服务端内运行的读写速度非常快,不会有影响,但是在浏览器端,浏览器资源的加载方式是异步的,所以不适合。

三、AMD规范

前面说到CommonJS规范是同步加载的方式,不适合于浏览器端,所以AMD(Asynchronous Module Definition异步模块定义)规范就来了。当采用异步加载的方式时,每个模块的加载不会影响到后面的语句执行,所有依赖的模块都定义在一个回调函数中,等加载完成后,回调函数才会执行,如下:

// API
define(id, [depends], callback);
require([module], callback);

// 定义
define("module", ["dep1", "dep2"], function(d1, d2) {...});
// 加载模块
require(["module", "../index"], function(module, index) {...});

AMD规范虽然很好的解决了CommonJs的不适合在浏览器内使用的问题,同时它还可以高效的并行加载多个模块,但是这种规范也存在缺点,首先是比较用起来比较麻烦,提高了开发成本,而且这种规范不符合通用的模块化思维方式。

四、CMD规范

CMD规范跟AMD规范有点像,它集合了CommonJs和AMD二者的特点,支持同步加载也支持异步加载,它的每一个模块就是一个文件,当它加载完一个依赖的模块后不会立即执行,待所有的模块加载完毕后,遇到require指令才会执行相对应的模块。API及使用方式如下:

// 定义模块使用全局函数define,接收factory参数,factory可以是一个函数,也可以是一个对象或字符串
define(function (require, exports, module) {
    //  同步加载模块
    var index1 = require('./index1');
    index1.doSomething();
    // 异步加载一个模块,在加载完成时,执行回调
    require.async(['./index2'], function (index2) {
        index2.doSomething();
    });
    // 对外暴露成员
    exports.doSomething = function () {};
});
// 使用模块
seajs.use('path');

其中factory是一个函数,参数包含require,exports以及module:

  • require:一个方法,用来接收模块标识作唯一参数,获取其它模块所提供的接口;
  • exports:一个方法,用来向外部暴露提供模块接口;
  • module:一个对象,内部存储一些当前模块下的一些属性或者方法;

这种CMD的规范集成了CommonJs和AMD的优点,但是缺点在于这种方式依赖于SPM的打包,模块加载的逻辑比较重,而且CMD 是 SeaJS 在推广过程中对模块定义的规范化产出的,SeaJS对于模块的加载态度是懒执行机制,SeaJS只会在需要使用模块的时候才会执行这个模块。

五、ES6模块化

ES6的标注提出,增加了对于JavaScript语言的模块体系的定义。它的设计思想是趋于静态化,可以在编译的时候就确定模块之间的依赖关系,以及需要的输入和输出的属性或方法,这样就解决了上面提到的CommonJs和AMD等规范中,只能在运行的时候才能确定。ES6中,我们是使用export来导出模块,利用import来引入我们需要的模块。例如:

// 导入
import "/index";
import Vue from "vue";

// 导出
export function getUserInfo() {...};
export default ...
...

这种规范的优点在于可以比较清晰简单的进行静态分析,并且可以面向EcmaScript标准。缺点就是一些原生浏览器还没有实现这个EcmaScript标准,同时新的命令需要新版的Node.js才可以支持。

 

关于JavaScript中模块化及模块化的一些规范就介绍到这里,大家有不同的意见或建议欢迎提出来相互交流。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值