# commonJs模块

1. **原文链接：**[**https://segmentfault.com/a/1190000011063732#articleHeader7**](https://segmentfault.com/a/1190000011063732#articleHeader7)
2. **原文链接：**[**http://www.ruanyifeng.com/blog/2015/05/commonjs-in-browser.html**](http://www.ruanyifeng.com/blog/2015/05/commonjs-in-browser.html)
3. **原文链接：**[**http://yijiebuyi.com/blog/7c8ffb3a58657e01e80f3bdc747473d2.html**](http://yijiebuyi.com/blog/7c8ffb3a58657e01e80f3bdc747473d2.html)
4. **原文链接：**[**https://zhaoda.net/webpack-handbook/commonjs.html**](https://zhaoda.net/webpack-handbook/commonjs.html)
5. 原文链接：<http://yijiebuyi.com/blog/7c8ffb3a58657e01e80f3bdc747473d2.html>

不久前，看到火狐在5月份将宣布支持js模块化,即会引入import，export方法。我自己一直都没有用过模块化的插件，比如commonJs,AMD,CMD，这些库的概念倒是都讲的是模块化操作，也就是模块化的编程。因为webpack具有这些插件的所有功能，并且更加强大，所以没有去了解这些插件库，其实webpack是怎样模块化的，我也搞不清楚，都是按照命令行操作，内部的实现没去弄学习，也没研究源码。

#### **模块化的好处：**

1. 功能的复用，写好的功能，可以直接通过模块引入，文件划分也清楚明了。
2. 大文件可以拆分为很多个模块，便于管理和维护。
3. 以前需要某个js插件的功能，就用script标签加载这个js 文件，有的时候就会加载很多个文件。script标签的加载是同步的，浏览器会停止渲染，同步加载这些js文件，这样会增加浏览器的响应时间。
4. 多个文件的命名冲突,全局变量的污染。

以前解决变量命名冲突的方法有，使用闭包，使用对象命名空间。

```javascript
//a.js
var obj_a= {
     test:1,
     say:function(){
          alert(1);
     }

}

//b.js

var obj_b={
     test:"str",
     say:function(){
          alert(144444);
     }

}
```

```javascript
var moudle=(function(){

    var a= 1;
    function say(){
       console.log(34)
    }

    return {a:a,say:say};
```

## CommonJS 模块，nodejs用的这个规范

* **模块定义导出**

**通过exports 或modules.exports导出模块,也就是定义模块。注意es6用的是export,不能直接给exports赋值,并且es6有 export {...} ,node里不可以 exports {...};切记不能弄混了。**

```javascript
//a.js
const a = 1;
let fun1 = function (x,y){

    return x + y ;
}


exports.a = a ;
exports.fun1 = fun1;
//注意   exports {a,fun1}; 不对，es6有 export {a，fun1},但是es6 不能export.a = a，这样导出。

//或
module.exports = {a , fun1};
```

在上面的例子中 ，exports 指向的就是module.exports;当使用模块化的时候，就已经声明 var expoets = module.exports = {};其中module指的就是当前的模块。打印出module就可以看到

```javascript
Module {
  id: '.',
  exports: {"a":1,"fun1":[Function]},
  parent: null,
  filename: '/Users/zss/node-Demo/my-app/testNOde/b.js',
  loaded: false,
  children: [],
  paths: 
   [ '/Users/zss/node-Demo/my-app/testNOde/node_modules',
     '/Users/zss/node-Demo/my-app/node_modules',
     '/Users/zss/node-Demo/node_modules',
     '/Users/zss/node_modules',
     '/Users/node_modules',
     '/node_modules' 
     ] 
   }
```

exports 是node 提供的一个变量指向module.exports，用来收集一些属性最后赋值给module.exports .这样一来，当我们在exports里导出变量a,再用module.exports 导出变量a,最后的结果是moudle.exports 的变量a.总之模块最终调用额是module.exports。

* **模块的分类，有两种模块**
* 一类为原生模块，例如http、path，加载的时候不用指明路径直接加载，速度很快。
* 一类为文件模块，动态加载的模块，也就是需要导入或是自己写。引入的时候需要指定模块的路径

**这两种模块加载的时候都会被缓存，也就是说第一次引用会加载，在引用的时候就会取缓存里的。**

* **模块的加载机制————模块的引用规则**

node的加载流程

1. 找目录下的文件名，然后加上扩展名称，依次按照“ .js  .node .json”查找，.node 和.json文件加上后缀名会快些。
2. 已上面的a.js 为例， 当找到a.js,首先读取内容包上一层function，避免暴露于全局中,这个function闭包有五个参数：exports，require,module，\_*filename,\\*\_dirname\_

```javascript
(function(exports,require,module,__filename,__dirname){

    const a = 1;
    let fun1 = function (x,y){

        return x + y ;
    }

    exports.module= {a,fun1};


});
```

**这就为什么在可以在js文件里直接用 require ,exports ,module,**\_\_*dirname,\_*\_filename.

node是读取缓存的，可以用如下的图来描述：

![](/files/-LgARPBvHgHDverLtEn4)

CommonJs规范比较适合服务器端，浏览启端的需要异步加载，所以就有了CMD、AMD规范。

### 注意当导出一个模块的变量时，是对这个模块变量的缓存复制，也就是说模块块内的变量发生改变时，不影响导出的变量，读取的是缓存里的。这一点与es6的模块机制不同。

```javascript
// a,js
let a = 1;
let b = {"name":"str"};
const fun1 = function(){

      a++;
     return  a ;
};
exports.a=a;
exports.fun1=fun1;
exports.b=b; 

//或
module.exports={a,fun1};

b={test:"change"};

mpdule.exports.b.name == "str"  // true 没改变


//b.js
const obj = require("./a.js");
obj.fun1();//2
console.log(obj.a) // 1 没变
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://sekin.gitbook.io/myjs/mo-kuai-hua-bian-cheng/commonjsamdcmddeng-mo-kuai-hua-jiang-jie.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
