js 理解模块化

经常在面试或者其他文章看到关于模块化的问题,之前也只是寥寥看了几次,对于 CommonJSAMDES6也说不出个所以然,于是今天抽空好好看了 红宝书第4版关于模块化的介绍,这里记录一下。

理解模块模式

初衷

在开发中肯定有设计大量三方库或者业务逻辑代码,较好的方式是将其分割为多个小模块,最后以一定的方式连接起来使用,这就是模块化兴起的初衷。

模块化一般包含什么?

模块化通常需要含一下几个点。<br/>

模块标识符

模块系统本质上是键/值实体,每个模块都有引用它的标志符,一般是路径或者文件名,部分模块系统也支持自定义标识符,这取决于哪种模块系统。

模块依赖

模块系统的核心就是是管理依赖了,脑海中大概有一张 A→B→C,这样的图就可以明白了。

模块加载

根据依赖,加载模块,在浏览器中只有整个依赖图都加载完成,才可以执行入口模块。

入口

这个就比较好理解了,相互依赖的模块必须指定一个模块作为入口(entry point),这也是代码执行的起点。

异步依赖

因为 JavaScript 可以异步执行,所以如果能按需加载就好了。换句话说,可以让 JavaScript 通知模块系统在必要时加载新模块,并在模块加载完成后提供回调。

1// 在模块 A 里面 2load('moduleB').then(function(moduleB) { 3 moduleB.doStuff(); 4});
动态依赖

可以在程序结构中动态引入模块

1if (loadCondition) { 2 require('./moduleA'); 3}
静态分析

模块中包含的发送到浏览器的 JavaScript 代码经常会被静态分析,分析工具会检查代码结构并在不实际执行代码的情况下推断其行为。

循环依赖

CommonJS、AMD 和ES6 在内的所有模块系统都支持循环依赖。

上面几点就是模块化的一些基本知识,接下来就看下我们比较关心的也面试偶尔问道的 CommonJSAMDES6

CommonJS

CommonJS 规范主要概述了同步声明依赖的模块定义,一般用于服务端规范,比如node.js(Node.js使用了轻微修改版本的 CommonJS,因为 Node.js 主要在服务器环境下使用,所以不需要考虑网络延迟问题。),CommonJS模块语法是不能直接在浏览器中使用的

使用方法

1var moduleB = require('./moduleB'); 2module.exports = { 3 stuff: moduleB.doStuff(); 4}; 5/** 6 一般使用 require 和 module.exports的方式 7 可以赋值给变量,也可直接 require 进入,同时不管请求多少次,也只会加载一次 8 第一次加载后,模块就会缓存起来,供后续使用 9**/

AMD

CommonJS 以服务器端为目标环境,能够一次性把所有模块都加载到内存,而 AMD 异步模块定义,是以浏览器为目标。 AMD模块是以函数包装的方式来实现的,就避免暴露全局变量的方式,但是需要AMD加载库来实现。

1// ID 为'moduleA'的模块定义。moduleA 依赖 moduleB, 2// moduleB 会异步加载 3define('moduleA', ['moduleB'], function(moduleB) { 4 return { 5 stuff: moduleB.doStuff(); 6 }; 7});

ES6 模块

以上说的两种都需要模块加载器,ES6引入了模块规范,同时原生浏览器也开始支持,融入了 AMD 和 CommonJS的优点

1 2 //像我们平常写的 3 import { foo } from './fooModule.js' 4 export default 123 5 //或者 6 <script type="module"> 7 import './moduleA.js' 8 <script> 9 10<script type="module" src="./moduleA.js"></script> 11/** 12与传统脚本不同,所有模块都会像<script defer>加载的脚本一样按顺序执行。解析到<script 13type="module">标签后会立即下载模块文件,但执行会延迟到文档解析完成。 14**/

ES6模块的加载

既可以通过浏览器加载,也可以通过打包工具加载

ES6模块部分优点

1 1、模块只能加载一次。 2 2、模块可以请求加载其他模块。 3 3、模块顶级 this 的值是 undefined(常规脚本中是 window)。 4 4、模块中的 var 声明不会添加到 window 对象。 5 5ES6 模块是异步加载和执行的,输出值的引用。

几个不同之处

11、CommonJS模块输出是值的拷贝,ES6 Module模块输出的值是引用 22、CommonJS是运行时加载,ES6 Module是编译是输出 33AMD规范是采用异步方式,依赖前置必须一开始就写好,所有的依赖加载完成后才会执行回调函数里的内容

剩下关于 ES6 模块导入导出的使用方法和规则就不逐一介绍了。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )