CommonJS规范
学习Node之前,有必要了解下CommonJS语法。
对于CommonJS语法,官网提供三个版本文档的介绍:1.0、1.1、1.1.1
这里着重介绍1.0和1.1版本的模块(modules)规范。
一,CommonJS 1.0 模块规范
状态:MULTIPLE IMPLEMENTATIONS(被1.1替代)
简介:该规范解决了应该如何编写模块,以便在一类模块系统之间实现互操作,这些模块系统既可以是客户端也可以是服务器端,无论是安全的还是不安全的,都可以在今天实施,或者由具有语法扩展功能的未来系统所支持。这些模块具有最大范围的私密性,可以从其他模块导入单例对象并导出自己的API。隐含地,本规范定义了模块系统必须提供的最小功能,以支持可互操作的模块。
简言之:根据这个规范,每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。
CommonJS中的几个基本概念
模块上下文:
- 在一个模块中,存在一个自由变量“require”函数
- 这个“rquire”函数接收一个模块标识符(解释如下“模块标识符”项)。
- “rquire”返回外部模块所输出的API。
- 如果出现依赖闭环(dependency cycle),那么外部模块在被它的传递依赖(transitive dependencies)所require的时候可能并没有执行完成,这种情况下“require“返回的对象必须至少包含此外部模块在调用require函数之前就已经准备完毕的输出。
- 如果请求模块不能返回,那么”require“必须抛出一个错误。
- 在一个模块中,存在一个名为”exports“的自由变量,它是一个对象,模块可以在执行的时候把自身API加入到其中。
- 模块必须使用”exports“对象来作为输出的唯一表示。
模块标识符:
- 模块标示符是一个由正斜杠分隔的”terms“组成的字符串。
- 一个term的必须为驼峰样式标识符,或者为”.“或”..“。
- 模块标识符可以省略文件名的后缀。比如”.js“。
- 模块标识符可以是相对路径(relative)或者绝对路径(top-level)。如果模块标识符的开头是”.“或者”..“则此模块标识符为相对路径。
- 绝对路径必须是模块所在命名空间的根。
- 相对路径必须是相对于当前require的模块。
示例代码:
math.js
exports.add = function() {
var sum = 0, i = 0, args = arguments, l = args.length;
while (i < l) {
sum += args[i++];
}
return sum;
};
increment.js
var add = require('math').add;
exports.increment = function(val) {
return add(val, 1);
};
program.js
var inc = require('increment').increment;
var a = 1;
inc(a); // 2
二,CommonJS 1.1 模块规范
状态:MULTIPLE IMPLEMENTATIONS(广泛运用)
CommonJS 1.1与 1.0相比主要在 模块上下文(Module Context)部分增加了一些规范。
对于CommonJS 1.1规范有以下定义。
模块上下文:
- 在一个模块中,存在一个自由变量“require”函数。
- 这个“rquire”函数接收一个模块标识符。
- “rquire”返回外部模块所输出的API。
- 如果出现依赖闭环(dependency cycle),那么外部模块在被它的传递依赖(transitive dependencies)所require的时候可能并没有执行完成,这种情况下“require“返回的对象必须至少包含此外部模块在调用require函数之前就已经准备完毕的输出。
- 如果请求模块不能返回,那么”require“必须抛出一个错误。
- require有一个只读的、不可删除的”main“属性。”main“相当于程序根目录的module。如果设置了该属性,则其必须和根目录的module指向相同的对象。
- require有个paths属性,该属性是一个具有优先秩序的路径数组,优先级从高到低,路径一直回朔到地根模块目录。
- paths属性不会存在于沙盒中。
- 在所有模块中paths的attribute均指向相同的值。
- paths是无法被替换的。
- 当paths的attribute存在时,修改paths的内容可能会导致模块无法被正确的搜索到。
- 当paths的attribute存在时,它可能只包含了部分path,当模块加载器在使用这些路径之前或者之后,去检查其它的路径。
- 当paths的attribute存在时,它是模块加载器使paths规范化、标准化的依据。
- 在一个模块中,存在一个名为”exports“的自由变量,它是一个对象,模块可以在执行的时候把自身API加入到其中。
- 模块中必须使用exports对象作为唯一的导出对象。
- 在一个模块中,必须存在一个自由变量“module”,并且module是一个对象。
- module对象有一个只读的、不可删除的id属性。当执行require(module.id)时,可以通过该id找到对应的module并返回module exports出的对象。
- 当创建一个module对象时,该对象可以有一个URI属性。该属性指向对应的模块源文件。该URI不存在于沙盒中。
模块标识符:
同CommonJS 1.0中 模块标识符 相关内容。
三,总结
根据CommonJS规范,一个单独的文件就是一个模块。加载模块使用require方法,该方法读取一个文件并执行,最后返回文件内部的exports对象。
四,参考资料
CommonJS > Modules/1.0 ---- http://wiki.commonjs.org/wiki/Modules/1.0
CommonJS > Modules/1.1 ---- http://wiki.commonjs.org/wiki/Modules/1.1
五,下集预告
AMD规范