概述
CommonJS 是服务器端模块的规范, Node.js 采用了这个规范

根据 CommonJS 规范, 一个单独的文件就是一个模块

加载模块使用 require 方法, 该方法读取一个文件并执行, 最后返回文件内部的 exports 对象.

// example.js

console.log('evaluating example.js');

var invisible = function(){
  console.log('invisible');
}

exports.message = 'h1';

exports.say = function(){
  console.log(message)
}
`</pre>

使用 require 方法, 加载 example.js 模块

<pre>`var example = require('./example.js');
`</pre>

这时变量 example 就对应模块中 exports 对象, 可以通过这个对象应用模块中提供的各种方法.

<pre>`{
  message: 'h1',
  say: [Function]
}
`</pre>

require 方法默认读取 js 文件, 所以可以省略 .js 扩展名

<pre>`var example = require('./example')
`</pre>

js 文件名前需要加上路径, 可以是相对路径, 也可以是绝对路径. 如果省略路径, node.js 会认为添加一个核心模块, 或者已经安装在本地 node_modules 目录中的模块. 如果加载的是一个目录, node.js 会首先寻找该目录中的 package.json 文件, 加载该文件 main 属性指定的模块, 否则就寻找该目录下的 index.js 文件

定义一个最简单的模块

<pre>`exports.add = function(a,b){return a+b};
`</pre>

//add.js
为 exports 对象添加一个 add 方法,

<pre>`var addition = require('./add');
addition.add(1,2); //3
`</pre>

稍复杂的例子

<pre>`//foobar.js
function foobar(){
  this.foo = function(){
    console.log('hello foo')
  };

  this.bar = function(){
    console.log('hello bar')
  };
}
exports.foobar = foobar;
`</pre>

调用

<pre>`var foobar = require('./foobar').foobar, test = new foobar();
test.bar(); //'hello bar'
`</pre>

有时不需要 exports 返回一个对象, 而仅需要返回一个函数, 就写成 module.exports

<pre>`module.exports = function(){
  console.log('hello world')
}
`</pre>

### AMD 规范与 CommonJS 规范的兼容性

CommonJS 规范加载模块是同步的, 也就是说, 只有加载完成, 才能执行后面的操作. AMD 规范则是非同步加载模块, 允许指定回调函数. 由于 Node.js 主要用于服务器编程, 模块文件一般都已经存在于本地硬盘, 所以加载起来比较快, 不需要考虑非同步加载的方式, 所以 CommonJS 的规范比较适用. 但是, 如果是浏览器环境, 要从服务器端加载模块, 这时就必须采用非同步模式, 因此浏览器端一般采用 AMD 规范.

AMD 规范适用 define 方法定义模块

<pre>`define(['package/lib', function(lib){
  function foo(){
    lib.log('hello world!');
  }

  return {
    foo:foo
  };
}])
`</pre>

AMD 规范允许输出的模块兼容 CommonJS 规范,在这时 define 方法需要写成如下格式

<pre>`define(function(require, exports, module)
  var someModule = require('someModule');
  var anotherModule = require('anotherModule');

  someModule.doTheAwesoem();
  anotherModule.doMoreAwesome();

  exports.asplode = function(){
    someModule.doTheAwesoem();
    anotherModule.doMoreAwesome();
  };
);