js模块化| 青训营笔记

46 阅读3分钟

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模块化的特点:

  1. 同步加载
  2. 多次引入只会实例化一次。
  3. 每个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'

deferasync的区别

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追求按需加载。