JavaScript 的模块机制

Posted by Gemicat on November 15, 2015

模块机制

随着Web2.0的发展,Js从表单校验跃迁到应用开发的级别上:

工具(浏览器兼容) -> 组件(功能模块) -> 框架(功能模块组织) -> 应用(业务模块组织)

1.CommonJS规范

希望JavaScript能在任何地方运行

1.1CommonJS的模块规范

CommonJS对模块的定义分为模块引用、模块定义和模块表示3个部分

1.模块引用

var math = require('math');

在CommonJs中,存在require()方法引入一个模块API到当前上下文中

2.模块定义

通过exports对象定义当前模块的方法或者变量,在模块中还存在一个module对象,代表模块本身,而exports是module的属性。在Node中,一个文件就是一个模块,将方法挂载在exports对象上作为属性即可定义到处的方式:

//math.js
exports.add = function () {
    var sum = 0, i = 0,
        args = arguments,
        l = args.length;
    while (i < 1) {
        sum += args[i++];
    }
    return sum;
}

在另一个文件引用方法并使用

//program.js
var math = require('math');
exports.increment = function (val) {
    return math.add(val, 1);
}

3.模块标识

模块标识其实就是传递给require()方法的参数,可以没有文件后缀.js

CommonJS构建的模块导出和引入机制使用户完全不必考虑变量污染。

2.Node的模块实现

在Node中引入模块,需要经历如下3个步骤:

1.路径分析

2.文件定位

3.编译执行

在Node中,模块分为两类:一类是Node提供的模块,称为核心模块;另一类是用户编写的模块,称为文件模块。

核心模块在Node源码编译过程中,被编译成二进制文件。在Node进程启动自动加载到内存,加载速度是最快的。

文件模块是在运行时加载的。

两类模块都采用有限从缓存加载的策略,不用支出是核心模块的缓存检查先于文件模块的缓存检查。

2.1路径分析和文件定位

1.模块标识符分析

(1)核心模块,如http、fs、path等。
(2).或..开始的相对路径文件模块。
(3)以/开始的绝对路径文件模块。
(4)以非路径形式的文件模块,如自定义的connect模块。

2.模块编译

在Node中,每个文件模块就是一个对象。对于不同文件扩展名,其载入方法也有所不同:

(1).js文件。通过fs模块同步读取文件后编译执行。
(2).node文件。这是用C/C++编写的扩展文件,通过dlopen()方法加载最后编译生成的文件。
(3).json文件。通过fs模块同步读取文件后,用JSON.parse()解析返回结果。
(4)其余扩展名文件。被当做.js文件载入。

3.核心模块

核心模块分为Javascript编写的和C/C++编写的,其中C/C++编写的在src目录下,Javascript文件放在lib目录下。

4.前后端公用模块

4.1 AMD规范

AMD规范适用于前段应用场景,全称是Asynchronus Module Definition(异步模块定义)。AMD规范是CommonJS模块规范的一个延伸,它的模块定义如下:

define(id?, dependencies?, factory);

它的模块id和依赖是可选的,与Node模块相似的地方是factory的内容。

4.2 CMD规范

CMD规范与AMD规范的区别在于定义模块和依赖引入部分:

define(function(require,exports,module){
    //the module code goes here
});

require、exports和module通过形参传给模块,在需要依赖模块时,调用require()引入。