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中的几个基本概念

模块上下文:

  1. 在一个模块中,存在一个自由变量“require”函数
    1. 这个“rquire”函数接收一个模块标识符(解释如下“模块标识符”项)
    2. rquire”返回外部模块所输出的API
    3. 如果出现依赖闭环(dependency cycle),那么外部模块在被它的传递依赖(transitive dependencies)所require的时候可能并没有执行完成,这种情况下“require“返回的对象必须至少包含此外部模块在调用require函数之前就已经准备完毕的输出。
    4. 如果请求模块不能返回,那么”require“必须抛出一个错误。
  2. 在一个模块中,存在一个名为”exports“的自由变量,它是一个对象,模块可以在执行的时候把自身API加入到其中。
  3. 模块必须使用”exports“对象来作为输出的唯一表示。

模块标识符:

  1. 模块标示符是一个由正斜杠分隔的”terms“组成的字符串。
  2. 一个term的必须为驼峰样式标识符,或者为”.“或”..“。
  3. 模块标识符可以省略文件名的后缀。比如”.js“。
  4. 模块标识符可以是相对路径(relative)或者绝对路径(top-level)。如果模块标识符的开头是”.“或者”..“则此模块标识符为相对路径。
  5. 绝对路径必须是模块所在命名空间的根。
  6. 相对路径必须是相对于当前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规范有以下定义。

模块上下文:

  1. 在一个模块中,存在一个自由变量“require”函数。
    1. 这个“rquire”函数接收一个模块标识符
    2. rquire”返回外部模块所输出的API
    3. 如果出现依赖闭环(dependency cycle),那么外部模块在被它的传递依赖(transitive dependencies)所require的时候可能并没有执行完成,这种情况下“require“返回的对象必须至少包含此外部模块在调用require函数之前就已经准备完毕的输出。
    4. 如果请求模块不能返回,那么”require“必须抛出一个错误。
    5. require有一个只读的、不可删除的”main“属性。”main“相当于程序根目录的module。如果设置了该属性,则其必须和根目录的module指向相同的对象。
    6. require有个paths属性,该属性是一个具有优先秩序的路径数组,优先级从高到低,路径一直回朔到地根模块目录。
      1. paths属性不会存在于沙盒中。
      2. 在所有模块中pathsattribute均指向相同的值。
      3. paths是无法被替换的。
      4. pathsattribute存在时,修改paths的内容可能会导致模块无法被正确的搜索到。
      5. pathsattribute存在时,它可能只包含了部分path,当模块加载器在使用这些路径之前或者之后,去检查其它的路径。
      6. pathsattribute存在时,它是模块加载器使paths规范化、标准化的依据。
  2. 在一个模块中,存在一个名为”exports“的自由变量,它是一个对象,模块可以在执行的时候把自身API加入到其中。
    1. 模块中必须使用exports对象作为唯一的导出对象。
  3. 在一个模块中,必须存在一个自由变量“module”,并且module是一个对象。
    1. module对象有一个只读的、不可删除的id属性。当执行require(module.id)时,可以通过该id找到对应的module并返回module exports出的对象。
    2. 当创建一个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规范

 

 

posted @ 2019-10-13 11:17  薛胖子  阅读(2)  评论(0编辑  收藏  举报  来源