前端模块化
2.1 commonJS
node.js主要使用commonJS,有四个关键词,module、exports、require、global。module.exports用来定义当前模块对外输出的接口,require用来加载模块
commonJs用同步的方式加载模块。在服务端,模块都存在本地磁盘中,读取非常快。在浏览器上,限于网络的原因,更合理的方法是使用异步加载
//文件名 1.common.js
const a=1
function add(a,b){
return a+b
}
module.exports={ // 在这里建议写向外暴露的函数和变量
num:a,
add
}
//文件名 1.引入common.js
// 引入自定义模块是可以省略 .js,同时需要引入路径
// 引入核心模块不需要路径
var math=require('./1.common')
console.log(math.num) //1
console.log(math.add(1,2)); //3
2.2 AMD和require.js
AMD采用异步方式加载模块,模块的加载不影响它后边语句的运行
require.config()指定引用路径等,用define()定义模块,用require()加载模块
require.config({
baseUrl:'js/lib',
paths:{
"jquery":"jquery.min", //实际路径js/lib/jquery
"A":"A.js"
}
})
require(["jquery","A"],function($,_){
//do some thing
})
对于引用模块,将模块名放在【】中作为require()的第一个参数;如果我们定义的模块也依赖其他模块,那么就将他们放在【】中作为define()的第一个参数
2.3 CMD和sea.js
CMD是另一种js的模块化方式,跟AMD比较相似.
区别:AMD推崇前置依赖、CMD推崇后置依赖,延迟执行
/
/ AMD写法
define(['a','b','c','d'],function(a,b,c,d){
// 等于在最前面声明了并初始化了所有模块
if(false){
// 即使没有用到d 但d还是执行了
b.doSomething()
}
})
// CMD写法
define(function(require,exports,module){
var a=require('./a')
a.doSomething()
什么时候需要就什么时候申请
if(false){
var b=require('./b')
b.doSomething()
}
})
2.4 ES6 Module
ES6 模块化比较简单,主要使用 export 和 import,export主要用来规定对外的接口,import 用来引入模块
//导出模块
const a=1
function add(num){
console.log(num);
}
export {a,add}
//在另一个文件里引入
import a from './4.es6模块化'
console.log(a); //1
add(9999) //9999
除了使用import的时候,需要知道所加载的变量名或者函数名。
使用export default命令,为模块指定默认输出,对应的import语句不需要使用大括号。
const a=1
function add(num){
console.log(num);
}
export default {a,add}
import AAA from './4.es6模块化'
console.log(AAA.a); //1
AAA.add(9999) //9999
ES6的模块不是对象,在编译的时候就会被引入模块代码,而不是在代码运行时加载,所以无法实现条件加载
2.5 ES模块与CommonJS 模块的差异
2.5.1 CommonJS 模块输出的是一个值的拷贝,ES6 模块输出是值的引用
//1.common.js
const person={
name:'fxk',
age:10
}
function add(a,b){
return a+b
}
module.exports={ // 在这里建议写向外暴露的函数和变量
person,
add
}
//引入 测试输出模块是什么拷贝
var math=require('./1.common')
math.person.age=15
var math2=require('./1.common')
console.log(math2.person.age); //15
得出结论:CommonJS 输出的是浅拷贝
CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。
ES6 模块是动态引用,并不会缓存值。
2.5.2 CommonJS 模块时运行时加载,ES6 模块是编译时输出接口
运行时加载:CommonJS模块就是对象;即在输入时先加载整个模块,生成一个对象,然后再从这个对象上读取方法,这种加载称为“运行时加载”
编译时加载:ES6模块不是对象,而是通过export命令显示指定输出的代码,import时采用静态命令的形式。
CommonJS 加载的是一个对象(即module.exports
属性) ,该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。