js模块化| 青训营笔记
最早出现的js模块化规范是在nodejs中实现CommonJS规范。CommonJS规范是一个同步加载模块的方案。
AMD规范,异步模块加载方案,需要引入required.js文件。AMD规范需要模块前置,不是按需加载。
CMD规范,需要引入sea.js文件,解决的AMD不足(不是按需加载),CMD规范是按需加载的规范。
es6中定义了新的模块化方案,目前浏览器不是完整支持,但是我们是可以使用的。
CommonJS
CommonJS 通常用于服务器,是一种同步模块加载方案:
需要数据导出的文件(a.js):
module.exports = {};
导出时,系统提供了module.exports和exports两个变量同时指向同一个对象
let exports = module.exports;
最终导出时,如果module.exports和exports的指向不是同一个对象,则以module.exports为准。
需要导入的文件:
require('./a.js');
commonjs模块化的特点:
- 同步加载
- 多次引入只会实例化一次。
- 每个js文件都是独立模块(作用域完全独立)。
同步导入,且不会重复导入(模块只会实例化一次)。因此,不用担心多次引入同一个模块的问题。
多次引入时,对应的是同一个对象,一个地方变化了,其他地方会跟着变化。
AMD
CMD
需要导出数据的模块:
a.js:
define(function (require, exports, module) {
'use strict';
const app = {
a: 1,
b: require('./a1.js')
}
module.exports = app;
});
define方法用于定义模块,需要导出的数据依然使用module.exports导出(要求是对象)。
模块依然可以再次引入模块,require('./a1.js');
需要引入的页面:
<script src="https://cdn.bootcdn.net/ajax/libs/seajs/3.0.3/sea.js"></script>
<script>
seajs.use(['./abc.js','./def.js'], function (a,b) {
console.log(a);
})
</script>
amd和cmd的语法基本通用,主要的区别在于:
amd追求模块优先加载,而cmd可以在任意位置使用require()按需引入。
es6模块化
export必须输出一个模块,以下写法报错:
export 1;
let x = 123;
export x;
export可以有多个:
export let x = 123;
export let y = 456;
....
导入时,使用:
import {x,y} from '';
导入时因为使用解构赋值,需要知道导出的对象属性名称,使用export default 可以导出默认名称:
export let x = '这是es6的模块化123';
export let y = 456;
export default { a: 1 };
导入时:
import xxx from './es6.js'//接收export default导出数据的地方
import { x, y } from './es6.js'
但export default只能有一个
import有变量提升。
document.querySelector('h1').innerHTML = JSON.stringify(xxx);
import xxx from './es6.js'
import { x, y } from './es6.js'
import出的变量是只读的。
import xxx from './es6.js'
import { x, y } from './es6.js'
x = 123;//这句报错
但是,如果导出的变量的值是对象,则改变对象的属性不出错。
import会执行代码,多次导入模块只会执行一次。
import可以使用*,也可以使用as。
import { x as a, y } from './es6.js'
//如果我们想把模块文件里的所有导出项的集合对象整体得到,需要用到 * ,但是*不是合法的变量名
//所以,结合as 为 * 附加一个合法的名字
import * as abc from './es6.js'
defer与async的区别
defer要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),才会执行;async一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。一句话,defer是“渲染完再执行”,async是“下载完就执行”。另外,如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺序的。
type="module" 等同于 defer
如果你要加载的文件必须等到文档就绪后才能执行,就使用defer。
要加载的文件比较大,但又不是必须等到文档就绪后才执行,就使用async。
<script src="x.js" defer/async></script>
js模块化4种方式的区别:
1、commonjs是同步加载,其他是异步加载。
2、es6的模块化是动态执行(每个文件取值都是新的值),而其他方式的模块都是运行缓存。
3、amd追求模块加载优先,而cmd追求按需加载。