1.为什么要模块化编程

命名冲突的故事

小A的代码不行了。utile.js被B改动导致。

文件依赖的故事

1.小A写的代码被小B,小C拿去用,各种不行,乃至以后的小D小E。

2.A.js依赖B.js,B.js依赖C.js。永无止境的依赖魔咒。可读性差。

模块化可以解决这两个问题

对外提供API接口,内部变量不可被污染,解决了命名冲突。

模块对内解决依赖关系,解决了依赖关系。

2.什么是模块化

从哪里来

js本身没有模块化的东西。只是后来网页程序逐渐复杂,我们的功能越来越多,于是有些人就开始写一些具有特定功能的插件。这些应该就是模块的前身了。

模块的发展过程

函数写法:

function m1(){
    //...
}

非常容易被污染的命名。

对象写法:

var module1 = new Object({
    _count : 0,
    m1 : function (){
      //...
    },
    m2 : function (){
      //...
    }
  });

虽然m1和m2不再直接暴漏,但是内部依然能被访问,比如我们可以改变_count的值:module1._count = 5;

立即执行函数可以完全限制访问,并且提供对外接口。其实这就是模块的原型

 var module1 = (function(){
    var _count = 0;
    var m1 = function(){
      //...
    };
    var m2 = function(){
      //...
    };
    return {
      m1 : m1,
      m2 : m2
    };
  })();

实现继承

 var module1 = (function (mod){
    mod.m3 = function () {
      //...
    };
    return mod;
 })(module1);

引入全局变量(其实就是其他模块),依赖变得明显且充分,这个时候的依赖关系和变量冲突问题似乎解决了

var module1 = (function ($, YAHOO) {
    //...
    var name = "zhangshan";
    return {};
})(jQuery, YAHOO);
var module1 = (function ($, YAHOO) {
    //...
    var name = "lisi";
    return {};
})(jQuery, YAHOO);

3.成熟的模块化编程语言Node.js是如何实现模块化的呢

这是一段基本的Node.js代码

'use strict';// 引入hello模块:
var greet = require('./hello');
var s = 'Michael'; 
greet(s); // Hello, Michael!

再看hello.js这个模块

'use strict';
var s = 'Hello';
function greet(name) {
    console.log(s + ', ' + name + '!'); 
} 
module.exports = greet;

为什么exports一下,就能被别的模块使用了呢?Node.js模块的实现过程

加载hello.js时先包装一下

(function () {
    // 读取的hello.js代码:
    var s = 'Hello';
    var name = 'world';
    console.log(s + ' ' + name + '!');
    // hello.js代码结束
})();

那么对外的接口是怎么输出的呢

// 准备module对象:
var module = {
    id: 'hello',    //模块属性,Node.js对这个对象进行了存储。
    exports: {}
};
var load = function (module) {
    // 读取的hello.js代码:
    function greet(name) {
        console.log('Hello, ' + name + '!');
    }

    module.exports = greet;    // hello.js代码结束
    return module.exports;
};
var exported = load(module);// 保存module:save(module, exported);

这样就实现了模块的输出

4.cmd和amd的区别

CMD 推崇依赖就近,AMD 推崇依赖前置。看代码:

  CMD

define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
// 此处略去 100 行
var b = require('./b') // 依赖可以就近书写
b.doSomething()
// ...
})

AMD

// AMD 默认推荐的是
define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
a.doSomething()
// 此处略去 100 行
b.doSomething()

5.sea.js模块化编程的实现

http://ruanwenwu.cn/blog/104.html