前端模块化

CommonJS是用在服务器端的,同步的,如:nodeJS;
AMD、CMD是用在浏览器端的,异步的,如:requireJS和seaJS;

CommonJS

CommonJs 是服务器端模块的规范,Node.js采用了这个规范。

CommonJS规范规定,一个单独的文件就是一个模块。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。

特点:
  • 所有代码都运行在模块作用域,不会污染全局作用域。
  • 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。如果想让模块再次运行就必须清除缓存。
  • 模块加载的顺序是按照其在代码中出现的顺序。
基本语法
  • 引入模块:require(‘模块名’),如果是第三方模块,直接传入模块名就可以;如果是自定义模块,需要传入模块文件路径。
  • 暴露模块:module.exports = value 或 exports.xxx = value。

CommonJS规范规定,每个模块内部,module变量代表当前模块。这个变量其实是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。

require方法读取一个文件后并执行该JavaScript文件,最后返回文件内部的exports对象。

如下:exe.js

//私有变量
var test = 666666;
//共有方法
function People(name,age){
	this.name = name;
	this.age = age;
	this.like = function(){
		//do something...
	}
}
//exports对象上的方法和变量是共有的
var Andi = new People('Andi',23);
exports.Andi = Andi;

require方法默认读取js文件,所以可以省略js后缀

var test = require('./exe').Andi;
test.like();

CommonJS加载模块是同步的,所以只有加载完成后才能执行后面的操作。像nodeJS主要用于服务器编程,加载的模块文件一般都已经存在本地硬盘,所以加载起来比较块,不用考虑异步加载方式,因此CommonJS规范比较使用。

如果是浏览器环境,要从服务器加载模块,这就必须采用异步模式了,所以就有了AMD、CMD解决方案。

模块加载机制

CommonJS模块的加载机制是,输入的是被输出的值的拷贝。也就是说,一旦输出一个值,模块内部的变化就不会影响到模块输出的值。

//lib.js
var counter = 2;
function incCounter(){
	counter++;
}
module.exports = {
	counter:counter,
	incCounter:incCounter
}

lib.js文件输出内部变量counter和改写该变量的内部方法incCounter。

//main.js
var lib = require('./lib');

console.log(lib.counter);//3
lib.incCounter();
console.log(lib.counter);//3

上面代码说明,lib输出以后,lib.js模块内部的变化不会影响到lib了,因为lib.counter是一个原始类型的值,会被缓存。除非写成一个函数,才能得到内部变动后的值。

AMD(Asynchromous Module Definition)

AMD是requireJS在推广过程中对模块定义的规范花产出。

AMD是异步加载模块,它的模块支持对象、函数、构造器、字符串、JSON等类型的模块。

AMD规范用define方法定义模块
通过数组引入依赖,回调函数通过形参传入依赖

define(['module1','module2','module3'],function(module1,module2){
	function foo(){
		//do something
		module1.test();
	}
	return {foo:foo};
})

AMD规范允许输出模块兼容CommonJS规范,这时define方法如下:

define(funtion(require,exports,module){
	var module1 = require('./module1');
	module1.test();

	exports.fun1 = function(){
		//something
	}
})

CMD(Common Module Definition)

CMD是SeaJS在推广过程中对模块化定义的规范化产出,和AMD很相似,尽量保持简单。

CMD规范专门用于浏览器端,模块的加载是异步的,模块使用时才会加载执行。

CMD和AMD的主要区别有一下几点:
1、对于模块的依赖AMD的提前执行,CMD是延迟执行。requireJS从2.0开始,也开始可以延迟执行了。
2、CMD推崇依赖就近,AMD推崇依赖前置。
3、AMD的API默认是一个当多个用,CMD严格区分推崇职责单一。AMD里require分全局的和局部的。CMD里面没有全局的 require,提供 seajs.use()来实现模块系统的加载启动。CMD里每个API都简单纯粹。

AMD写法:

define(['./a','/.b'],function(a,b){
	//依赖一开始就写好
	a.test();
	b.test();
})

CMD写法:

define(function(require,exports,module){
	//依赖就近写法
	var a = require('./a');
	a.test();

	if(states){
		var b = require('./b');
		b.test();
	}
	//通过 exports 就可以向外提供接口
	exports.each = function(arr){
		//do something
	}
})
CMD规范基本用法
  • 定义暴露的模块:
//定义没有依赖的模块
define(function(require,exports,module){
	exports.xxx = value;
	module.exports = value;
})

//定义有依赖的模块
define(function(require,exports,module){
	//引入依赖模块(同步)
	var module1 = require('./module1');
	//引入依赖模块(异步)
	require.async('./module2',function(ms){
		
	})
	//暴露模块
	exports.xxx = value;
})
  • 引入使用的模块:

在CMD规范中,如果我们想使用某个模块,只需要通过seajs.use()方法就可以。

//使用sai模块
seajs.use('sai',function(Sai){
	//使用模块sai中的init方法
	Sai.init();
})

ES6模块化

ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。

ES6模块化语法
  • import 命令用于输入其他模块提供的功能
  • export 命令用于规定模块的对外接口
/** 定义模块math.js **/
var num = 10;
var add = function(a,b){
	return a + b;
}
export {num, add};

/** 引入模块 **/
import {num, add} from './math';
console.log(add(10,num));//20

上面的例子使用 import 命令的时候,用户需要知道所加载变量名和函数名,否则无法加载。

为了给用户提供方便,让他们不用阅读文档就能加载模块,就用到了export default 命令,微模块指定默认输出。

//export-module.js
export default function(){
	console.log('输出了');
}

//import-module.js
import custom from './export-module';
custom();//输出了

使用export default 指定默认输出,当其他模块加载该模块时,import 命令可以为该模块指定任意命名。

ES6模块与CommonJS模块的差异

它们有两个重大的差异

  • CommonJS模块输出的是一个值的拷贝,ES6模块输出的是值的引用。
  • CommonJS模块是运行时加载,ES6模块是编译时输出接口。

zccst
lifesinger
浪里行舟
ruanyifeng

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值