ECMAScript2015以后,原生js推出了模块化概念,称为ECMAScript Module
,简称ESM
。
现在主流浏览器都有很好的支持
模块化的作用
把复杂的问题分解成相对独立的模块,这样的设计可以
降低程序复杂性
,提高代码的重用
,有利于团队协作开发与后期的维护和扩展
模块化的核心
模块独立的作用域
如何导出模块内部数据
如何导入外部模块数据
独立模块作用域
一个文件就是模块,拥有独立的作用域,且导出的模块默认是处于 严格模式
下,之前的文章有总结,小手点一点去看看严格模式与非严格模式的区别
1、ESM
之前写的博客中关于模块的导入语法导出
之前学Nodejs总结的ES6中的模块化
模块的导入和导出与函数的定义和调用类似,在不同的地方有不同的定义与调用规则
导出:使用 export
语句导出模块内部数据
导入:两种模式导入外部模块数据
静态导入方式不支持延迟加载, import导入语句,放在模块化代码的最顶层
通过 import()方法导入返回的数据会被包装在一个对象中,即使是default也是这样
//b.js
// 导出b.js文件中的内容
export default "我是b文件中的内容";
//a.js
// 静态导入
// 导入b.js文件中的数据到a.js文件中
import b from './b.js';
console.log(b);
// 动态导入
let b2 = import ("./b.js");
console.log(b2);
// 动态导入数据的示例(点击鼠标后导入数据)
document.onclick = async function(){
let b3 = await import ("./b.js");
console.log(b3);
//输出的是一个模块化对象 Module {Symbol(Symbol.toStringTag): "Module"}
}
<!--在html文件中-->
<!--模块化中使用script标签引入js文件,需要设置type="module" ,如果不加会报错,取不到数据-->
<script src="./js/a.js" type="module"></script>
2、CommonJS规范
早先前端对于模块化并没有什么规范,反而是偏向服务端的应用有更强烈的需求,
CommonJS
规范是一套偏向服务端的模块化规范,NodeJS 就采用的就是这个规范。
导出模块内部数据
通过 module.exports
或 exports
对象导出模块内部数据
// a.js
let a = 1;
let b = 2;
//导出数据
module.exports = {
x: a,
y: b
}
// 或者这样
exports.x = a;
exports.y = b;
导入外部模块数据
通过 require
函数导入外部模块数据
// b.js
// 导入数据
let a = require('./a.js');
a.x;
a.y;
3、AMD
CommonJS 规范一些特性(基于文件系统,同步加载),前面说过它主要应用于服务器端,并不适用于浏览器端,所以另外定义了适用于浏览器端的规范
AMD(Asynchronous Module Definition)
而浏览器并没有具体实现该规范的代码,因此通过第三方插件库来解决。
去下载requireJS插件库代码require.min.js
通过define方法来定义一个模块,该方法没有返回值,并通过该方法的回调函数参数来产生独立作用域
参数1:导入的路径(存在数组中,这样可以导入多个)
参数2:回调函数,函数中的参数是导入的数据
// a.js
/*
通过define方法来定义一个模块,该方法没有返回值,并通过该方法第二个参数(回调函数)来产生独立作用域
参数1:导入的路径(存在数组中,这样可以导入多个)
参数2:回调函数,函数中的参数是导入的数据
*/
// 导入外部模块数据
// 通过前置依赖列表导入外部模块数据
// 导入b.js内容
// 注意路径'./js/b.js'
define(['./js/b.js'], function (b) {
console.log(b);
});
// b.js
// 导出模块内部数据
// 通过return导出模块内部数据
// 导出b.js内容
define(function(){
let val = "我是AMD规范下的数据";
return val;
});
<!--test.html中-->
<script src="./js/require.min.js" data-main="./js/a.js"></script>
4、UMD
UMD 叫做通用模块定义规范(Universal Module Definition)
严格来说,UMD
并不属于一套模块规范,它主要用来处理 CommonJS
、AMD
、CMD
的差异兼容,使模块代码能在不同的模块环境下都能正常运行
//使用闭包来处理: (匿名函数的定义)(匿名函数需要的参数);
//(function(){
//
//})();
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
// Node, CommonJS-like
module.exports = factory;
}
else if (typeof define === "function" && define.amd) {
// AMD 模块环境下
define(function () {
return factory;
});
}
else {
window.rmb = factory;
}
})(function (val) {
return "¥" + (val / 100).toFixed(2);
});