概述
模块通常是指编程语言所提供的代码组织机制,利用此机制可将程序拆解为独立且通用的代码单元。
模块的优点:1.可维护性;2.命名空间;3.重用代码
常见的模块化规范:CommonJS
、AMD
、CMD
,也有ES6的Modules
CommonJS
CommonJS的核心思想就是通过 exports
或者 module.exports
来导出需要暴露的接口,然后通过 require
方法来同步加载所要依赖的其他模块,这个规范里,每个文件就是一个模块。
a.js
let a = 123;
let foo = function () {
console.log("foo");
};
//两个顺序不能颠倒,否则变量a的值就无法暴露
module.exports = {
foo: foo,
};
module.exports.a = a;
b.js
const b = require("./a.js");
console.log(b.a);
b.foo();
module.exports
属性表示当前模块对外输出的接口,其他文件加载该模块,实际上就是读取module.exports
变量。nodeJS为了方便,为每个模块提供一个exports
变量,指向module.exports
。这等同在每个模块头部,有一行这样的命令。
var exports = module.exports;
不能直接将exports
变量指向一个值,等于切断了exports
与module.exports
的联系。如下:
let a = 123;
let foo = function () {
console.log("foo");
};
//这种写法会报错
exports = {
foo: foo,
};
注意:
- CommonJS是同步加载模块的。
- CommonJS是不适用于浏览器端。
浏览器端的模块,不能采用"同步加载"(synchronous),只能采用"异步加载"
客户端主要有:AMD( 实现有RequireJS ) / CMD(实现有SeaJS),随着ES6模块化规范的实现和普及,第三方的模块化实现将会慢慢的淘汰。
AMD / CMD
AMD 是 RequireJS 在推广过程中对模块定义的规范化产出
CMD是SeaJS在推广过程中对模块化定义的规范化产出
两种规范是服务于JavaScript的模块化开发,目前两种都能实现浏览器端的模块化开发的目的
不同:
AMD是预执行(提前执行),CMD是懒执行(延迟执行)。
AMD推崇依赖前置,CMD推崇就近依赖。
// AMD
define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好 注意标红的,通过函数回调的方式将引入的依赖赋值给标红的变量,然后整个块就可以利用这个引入的依赖了
a.doSomething()
// 此处略去 100 行
b.doSomething()
...
});
// CMD
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
// 此处略去 100 行
var b = require('./b')
// 依赖可以就近书写
b.doSomething()
// ...
});
ES6
ES6的模块化方案是真正的规范。 在ES6中,我们可以使用 import 关键字引入模块,通过 export 关键字导出模块。export和import命令可以出现在模块的任何位置,只要处于模块顶层就可以。如果处于块级作用域内,就会报错,接下来说的import命令也是如此。
1.方式一:
let flag = true;
function sum(num1, num2) {
return num1 + num2;
}
export { flag, sum }
//b.js
import {flag,sum} from './a.js'
2.方式二:
//a.js
export const height = 1.88;
export function mul(num1, num2) {
return num1 * num2
}
//b.js
import {height,mul} from './a.js'
3.方式三:
某些情况下,一个模块中包含某个的功能,我们并不希望给这个功能命名,而且让导入者可以自己来命名
这个时候就可以使用export default
。export default
本质是将该命令后面的值,赋给default
变量以后再默认,所以直接将一个值写在export default
之后。一个模块中只能有一个export default
//a.js
export default function (argument) {
console.log(argument);
}
//b.js
import hello from "./a.js";
hello('你好啊');
import使用
1.import命令具有提升效果,会提升到整个模块的头部,首先执行。
2.如果是在HTML代码中使用模块,引入两个js文件时需要设置为module
。才能在浏览器中使用。
3.如果希望某个模块中所有的信息都导入,可以通过*
导入模块中所有的export变量。通常情况下需要给*
起一个别名,方便后续的使用。
//a.js
export const height = 1.88;
export function mul(num1, num2) {
return num1 * num2;
}
//b.js
import * as a from './a.js'
console.log(a.height);