模块(Module): 一块具有独立功能的代码,可以是一个函数,一个对象,甚至是一个字符串或者数字,通常存储为一个单独的文件;
**模块化出现的原因:**js很难编写大型项目,由于全局变量的污染和难以管理的依赖关系, 这些问题导致了js无法进行精细的模块划分,因为精细的模块划分会导致更多的全局污染以及更加复杂的依赖关系;
目前只有node环境才支持CommonJs
模块化标准,要使用CommonJs
,必须安装node
;
nodejs
直接运行某个js文件,该文件被称为入口文件;
nodejs
遵循EcmaScript
标准,但是由于脱离了浏览器环境,因此:
1.可以在nodejs中使用EcmaScript
标准的任何语法或api,例如:循环,判断,数组,对象等;
2.不能在nodejs
中使用浏览器的webApi
,例如:dom对象
,window对象
,document对象
等;
node
中的所有代码均在CommonJs规范下运行;
具体规范:
1.一个js文件即为一个模块;
2.如果一个模块需要暴露一些数据或者功能供其他模块使用,需要使用代码module.exports =xxx
;
3.如果一个模块需要使用另一个模块导出的内容,需要使用require('模块路径')
;
1.路径必须以./或…/开头;
2.如果模块文件后缀名为.js,可以省略后缀名;
3.require函数返回的是模块导出的内容;
4.模块中所有全局代码产生的变量,函数,均不会对全局造成任何污染,仅在模块内使用;
5.模块具有缓存,第一次导入模块时会缓存模块的导出,之后再导入同一个模块,直接使用之前缓存的结果;
由于CommonJs模块化,代码会形成下面结构,同时解决了js的两个问题**(全局变量的污染和难以管理的依赖关系)**
node实际上是将模块文件中的代码放置到一个函数环境中执行,可以想象该函数的样子;
function (module){
module.exports = { };
var exports = module.exports;
//模块中的代码
...
return module.exports
}
//exports和module.exports区别
真正最后导出的是module.exports,只不过在模块代码执行之前,定义一个变量var exports = module.exports
module.exports是一个空对象,最后return的是module.exports
浏览器使用下边方式引入一个ES6模块文件
<script src="入口文件" type="module">
1.模块的导出分为两种,基本导出和默认导出
可以将整个模块的导出想象成一个对象,基本导出的是该对象的某个属性,默认导出的是该对象的特殊属性default
//导出结果:想象成一个对象
{
a:xxx,//基本导出
b:xxx,//基本导出
default:xxx, //默认导出
c:xxx//基本导出
}
注意: 1.基本导出可以有多个,默认导出只能有一个;
2.基本导出必须要有名字,默认导出由于有特殊名字,所以可以不用写名字;
export var a = 1 //基本导出 a = 1
export var b = function(){} //基本导出 b = function(){}
export function method(){} //基本导出 method = function(){}
var c = 3;
export {c} //基本导出 c = 3
export { c as temp } //导出的名字重新命名 基本导出 temp = 3
export default 3 //默认导出 default = 3
export default function(){} //默认导出 default = function(){}
export { c as default } //默认导出 default = 3
export {a, b, c as default} //基本导出 a=1, b=function(){}, 默认导出 default = 3
import {a,b} from "模块路径" //导入属性 a、b,放到变量a、b中
import {a as temp1, b as temp2} from "模块路径" //导入属性a、b,放到变量temp1、temp2 中
import {default as a} from "模块路径" //导入属性default,放入变量a中,default是关键字,不能作为变量名,必须定义别名
import {default as a, b} from "模块路径" //导入属性default、b,放入变量a、b中
import c from "模块路径" //相当于 import {default as c} from "模块路径"
import c, {a,b} from "模块路径" //相当于 import {default as c, a, b} from "模块路径"
import * as obj from "模块路径" //将模块对象放入到变量obj中
import "模块路径" //不导入任何内容,仅执行一次模块
注意:
1.ES6 module采用的依赖预加载模式,所有模块导入代码均会提升到代码顶部;
2.不能将导入代码放置到判断,循环中;
3.导入的内容放置到常量中,不可更改;
4.ES6 module使用了缓存,保证每个模块仅加载一次;