模块化之间的比较

CommonJS

是nodejs使用的模块化规范,一个单独的文件就是一个模块,加载模块使用require方法同步加载,该方法读取一个文件并执行,最后返回文件内部的exports对象。

//example.js
exports.message = "hi";
exports.say = function (){
    console.log("hello");
};
var example = require('./example.js');
example.say();

如果被require函数引入的模块中也包含依赖,那么依次加载这些依赖。

AMD/RequireJS

CommonJS加载模块是同步的,即模块加载完成才能执行后面的操作。这是因为在服务器环境下,文件一般都在本地磁盘,加载起来比较快。
而在浏览器端就最好使用AMD,即异步加载模块,允许指定回调函数.

用全局函数define来定义模块

 define(id?, dependencies?, factory);
  • id:模块名,这个参数是可选的。如果没有提供该参数,则模块名默认为脚本文件的名称。
  • dependencies:是个定义中模块所依赖模块的数组。
  • factory:工厂方法,为模块初始化要执行的函数或对象。
    如果为函数,它应该只被执行一次。
    如果是对象,此对象应该为模块的输出值。
    如果工厂方法返回一个值(对象,函数,或任意强制类型转换为true的值),应该为设置为模块的输出值

几个例子:

define(["alpha"],function(alpha){
    return {
        verb:function(){
            return alpha.verb()+2;
        }
    }
})
//一个没有依赖性的模块可以直接定义对象:
define({
    add:function(x,y){
        return x+y;
    }
})

兼容CommonJS的写法:

define(function(require,exports,module){
    var a = require('a');
    var b = require('b');

    exports.action = funciton(){……}
})

AMD可以使用全局变量require来加载模块:

var a = require('a');

require(['a', 'b'], function (a, b) {
            //modules a and b are now available for use.
        });

AMD运行的核心是 提前执行,也就是提前执行依赖:

define(['a','b'],function(A,B){
    ……
})

也就是说在factory执行之前,a,b都下载并执行完毕了
好处是可以尽早发现错误:如果模块中出现异常,那么factory不会执行。
坏处就是容易产生带宽和内存的开销,因为很有可能我们依赖的模块其实并没有被用到,但还是下载和执行完毕了。

但是AMD也提供懒加载的形式:

define(function(require,exports,module){
    console.log("main");
    require(['a'],function(a){
        a.hello();
    });
    $('#b').click(function(){
          require(['b'], function(b){
               b.hello();
          });
     });
})

我们并没有提前声明依赖,那么在此模块执行时就不会预先加载a和b,在require的时候才会去加载。

这种懒加载方式会大大减轻初始化时的损耗,但是弊端就是后续要执行a.hello()和b.hello()时,需要实时下载代码然后执行,这样可能会带来操作的卡顿。

CMD/SeaJS

CMD更贴近 CommonJS规范,一个模块就是一个文件;
它推崇依赖就近,想什么时候 require 就什么时候加载,并且不使用回调函数的形式

define

和AMD规范类似,都是用define来定义模块,:

define(id?, deps?, factory)

factory 为函数时,表示是模块的构造方法。执行该构造方法,可以得到模块向外提供的接口。
factory 方法在执行时,默认会传入三个参数:require、exports 和 module

define(function(require,exports,module){
    ……
})
define('hello', ['jquery'], function(require, exports, module) {

  // 模块代码

});

require

require 是一个方法,接受 模块标识 作为唯一参数,用来获取其他模块提供的接口。这里的require是同步的,并没有使用回调函数。

define(function(require,exports){
    var a = require('./a');
    a.doSomething();
})

SeaJS 会检查你的模块factory,找到所有的 require 语句,从而得到你的模块的所有依赖。 在真正 require 当前模块时,会先去请求这个模块的依赖,加载完毕,再去初始化当前的模块。

require.async 方法用来在模块内部异步加载模块,并在加载完成后执行指定回调:

define(function(require, exports, module) {
// 异步加载一个模块,在加载完成时,执行回调
    require.async('./b',function(b){
        b.doSomething();
    })
// 异步加载多个模块,在加载完成时,执行回调
  require.async(['./c', './d'], function(c, d) {
    c.doSomething();
    d.doSomething();
  });
})

注意:require 是同步往下执行,require.async 则是异步回调执行。 require.async 一般用来加载可延迟异步加载的模块。

exports

exports 是一个对象,用来向外提供模块接口。

define(function(require, exports) {

  // 对外提供 foo 属性
  exports.foo = 'bar';

  // 对外提供 doSomething 方法
  exports.doSomething = function() {};

});

除了给 exports 对象增加成员,还可以使用 return 直接向外提供接口。

define(function(require) {

  // 通过 return 直接提供接口
  return {
    foo: 'bar',
    doSomething: function() {}
  };

});

  • 与 RequireJS 的 AMD 规范相比,CMD 与 CommonJS 和 Node.js 的 Modules 规范保持了很大的兼容性。通过 CMD 规范书写的模块,可以很容易在 Node.js 中运行

  • 看出CMD的理念是就近加载。我们可以在需要用到依赖的时候才require,并且不使用回调函数的形式

  • 在导出模块方面,既支持exports导出,也支持直接AMD的直接return导出

ES6的模块

ES6模块与上面的都不同,是静态加载的,也就是在编译阶段进行加载,在编译时就确定模块的依赖关系,以及输入和输出的变量。
而CommonJS、AMD都是在运行时才确定这些关系和输入输出什么的。

  • 运行时加载: CommonJS/AMD 模块就是对象;在输入时是先加载整个模块,生成一个对象,然后再从这个对象上面读取方法,这种加载称为“运行时加载”
  • 编译时加载:ES6 模块不是对象,而是通过 export 命令显式指定输出的代码,输入时采用静态命令的形式。即在输入时可以指定加载某个输出值,而不是加载整个模块,这种加载称为“编译时加载

ES6模块的运行机制与CommonJS不一样,它遇到模块加载命令import时,不会去执行模块,而是只生成一个动态的只读引用。等到真的需要用到时,再到模块里面去取值,ES6模块是动态引用

  • 在 CommonJS 中,导入(imports)是模块导出值的复制值(同时 require()动作是同步的)。也就是说,在一个模块中一个值和这个值导出被复制后的值不是同一个,两者之间不存在连接
  • 在 ES6 中,导入是对导出值的只读。因此,模块中的值和导出后的值是同一个,存在连接,只是在导入的模块中对这个值是只读的。
    “只读”说明在导入的模块中不能直接修改被导入的值,如果要修改被导入的值,可以通过调用被导入模块的函数来达到目的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值