ES6 -- 模块化(CommonJS、AMD、ES Module)
模块模式
将代码拆分成独立的块,然后再将这些块连接起来可以通过模块模式来实现。这种模式背后的思想很简单:把逻辑分块,各自封装,相互独立,每个块自行决定对外暴露什么,同时自行决定引入执行哪些外部代码。
模块标识符
模块系统本质上是键/值实体,其中每个模块都有个可用于引用它的标识符。这个标识符在模拟模块的系统中可能是字符串,在原生实现的模块系统中可能是模块文件的实际路径
模块依赖
每个模块都会与某一个唯一的标识符关联,该标识符可用于检索模块。这个标识符通常是 JavaScript文件的路径,但在某些模块系统中,这个标识符也可以是在模块本身内部声明的命名空间路径字符串。
模块加载
- 加载模块的概念派生自依赖契约。当一个外部模块被指定为依赖时,本地模块期望在执行它时,依赖已经准备好并已初始化。
- 在浏览器中,加载模块涉及几个步骤。加载模块涉及执行其中的代码,但必须是在所有依赖都加载并执行之后。如果浏览器没有收到依赖模块的代码,则必须发送请求并等待网络返回。收到模块代码之后,浏览器必须确定刚收到的模块是否也有依赖。然后递归地评估并加载所有依赖,直到所有依赖模块都加载完成。只有整个依赖图都加载完成,才可以执行入口模块。
入口
相互依赖的模块必须指定一个模块作为入口,这也是代码执行的起点。
动态依赖
if(loadCondition) {require('./moduleA');
}
在这个模块中,是否加载 moduleA 是运行时确定的。
动态依赖可以支持更复杂的依赖关系,但代价是增加了对模块进行静态分析的难度。
静态分析
分析工具会检查代码结构并在不实际执行代码的情况下推断其行为。
循环依赖
加载器回执行深度优先的依赖加载:
使用ES6之前对模块加载器
在ES6原生支持模块之前,使用模块的JavaScript代码本质上是希望使用默认没有的语言特性。因此,必须按照符合某种规范的模块语法来编写代码,另外还需要单独的模块工具把这些模块语法与JavaScript运行时连接起来。这里的模块语法和连接方式有不同的表现形式,通常需要在浏览器中额外加载库或者在构建时完成预处理。
CommonJS
CommonJS规范概述了同步声明依赖的模块定义。这个规范主要用于在服务器端实现模块化代码组织,但也可用于定义在浏览器中使用的模块依赖。CommonJS模块语法不能直接在浏览器中运行
注意 一般认为,Node.js的模块系统使用了CommonJS规范,实际上并不完全正确。Node.js使用了轻微修改版本的CommonJS,因为Node.js主要在服务器环境下使用,所以不需要考虑网络延迟问题。考虑到一致性,本节使用Node.js风格的模块定义语法。
CommonJS模块定义需要使用require()指定依赖,而使用exports对象定义自己的公共API。
var moduleB = require('./moduleB');
module.exports = {stuff: moduleB.doStuff();
}
无论一个模块在 require() 中被引用多少次,模块永远是单例
console.log('moduleA');
var a1 = require('./moduleA');
var a2 = require('./moduleA');console.log(a1===a2); // true
模块第一次加载后会被缓存,后续加载会取得缓存的模块。模块的加载顺序由依赖图决定。
在 CommonJS 中,模块加载时模块系统执行的同步操作。因此 require()可以像下面这样以编程方式嵌入在模块中:
console.log('moduleA');
if (loadCondition) {require('./moduleA');
}
如果moduleA已经在前面某个地方加载过了,这个条件 require()就意味着只暴露moduleA这个命名空间而已。
异步模块定义
CommonJS以服务端为目标环境,能够一次性把所有模块都加载到内存,而异步模块定义(AMD Asynchronous Module Definition)的模块定义系统则以浏览器为目标执行环境,这需要考虑网络延迟的问题。AMD的一般策略是让模块声明自己的依赖,而运行在浏览器中的模块系统会按需获取依赖,并在依赖加载完成后立即执行依赖它们的模块。
AMD模块实现的核心是用函数包装模块定义。这样可以防止声明全局变量,并允许加载器库控制何时加载模块。包装函数也便于模块代码的移植,因为包装函数内部的所有模块代码使用的都是原生JavaScript结构。包装模块的函数是全局 define 的参数,它是由AMD加载器库的实现定义的
AMD模块可以使用字符串标识符指定自己的依赖,而AMD支持可选地为模块指定字符串标识符。
// ID 为‘moduleA’的模块定义。moduleA依赖moduleB,
// moduleB会异步加载
define('moduleA', ['moduleB'], function(moduleB) {return {stuff: moduleB.duStuff();}
})
AMD也支持require和exports对象,通过他们的可以在AMD模块工厂函数内部定义CommonJS风格的模块。这样可以像请求模块一样请求它们,但AMD加载器会将它们识别为原生AMD结构,而不是模块定义
define('moduleA', ['require'], function(require){if(condition) {var moduleB = require('moduleB');}
})
通用模块定义
为了统一CommonJS和AMD生态系统,通用模块定义(UMD,Universal Module Definition)规范应运而生。UMD可用于创建这两个系统都可以使用的模块代码。本质上,UMD定义的模块会在启动时检测要使用哪个模块系统,然后进行适当配置,并把所有逻辑包装在一个立即调用的函数表达式中。
下面是只包含一个依赖的UMD模块定义的示例:
(function (root, factory) {if(typeof define === 'function' && define.amd) {//AMD。注册为匿名函数define(['moduleB'], factory);}else if (typeof module === 'object' && module.exports) {// Node。不支持严格CommonJS// 但可以在Node这样支持module.exports的类 CommonJS环境下使用module.exports = factory(require('moduleB'));}else {// 浏览器全局上下文(root是window)root.returnExports = factory(root.moduleB);}}(this, function (moduleB) {// 以某种方式使用moduleB// 将返回值作为模块的导出// 这个例子返回了一个对象// 但是模块也可以返回函数作为到处值return {};}));
模块加载器终将没落
随着ECMAScript 6模块规范得到越来越广泛的支持,上述展示的模式终会走向没落
使用 ES6 模块
ES6模块最大的一个改进就是引入了模块规范。这个规范全方位简化了之前出现的模块加载器,原生浏览器支持意味着加载器以及其他预处理都不再必要。从很多方面看,ES6模块系统是集AMD和CommonJS之大成者。
模块标签及定义
ECMAScript 6模块是作为一整块JavaScript代码而存在的。带有type="module"属性的
模块加载
完全支持 ECMAScript 6模块的浏览器可以从顶级模块加载整个依赖图,且是异步完成的。浏览器会解析入口模块,确定依赖,并发送对依赖模块的请求。这些文件通过网络返回之后,浏览器就会解析它们的内容,确定它们的依赖,如果这些二级依赖还没有加载,则会发送更多请求。这个异步递归加载过程会持续到整个应用程序的依赖图都解析完成。解析完依赖图,应用程序就可以正式加载模块了。
这个过程与AMD风格的模块加载非常相似。模块文件按需加载,且后续模块的请求会因为这个依赖模块的网络延迟而同步延迟。
模块行为
ECMAScript 6模块借用了CommonJS和AMD的很多优秀特性。如:
- 模块代码只在加载后执行
- 模块只能加载一次
- 模块是单例
- 模块可以定义公共接口,其他模块可以基于这个公共接口观察和交互。
- 模块可以请求加载其他模块
ES6模块系统也增加了一下新行为 - ES6模块默认在严格模式下执行
- ES6模块不共享全局命名空间
- 模块顶级this的值是undefined(常规脚本中是window)
- 模块中的 var 声明不会添加到 window 对象
- ES6模块是异步加载和执行的
模块导出
ES6模块支持两种导出:命名导出和默认导出。
- export 关键字用于声明一个值为命名导出。导出语句必须在模块顶级,不能嵌套在某个块中
- 导出值对模块内部JavaScript的执行没有直接影响,因此 export 语句与导出值对相对位置或者 export 关键字在模块中出现的顺序没有限制。export语句甚至可以出现在它要导出的值之前:
const foo = 'foo';export { foo };export const foo = 'foo';export { foo };const foo = 'foo';
命名导出就好像模块是被导出值的容器。
1. 行内命名导出export const foo = 'foo';const foo = 'foo';export { foo };
2. 导出时可以提供别名,别名必须在export子句的大括号语法中指定。const foo = 'foo';export { foo as myFoo };
3. 导出声明分组const foo = 'foo';const bar = 'bar';const baz = 'baz';export { foo, bar as myBar, baz};
默认导出就好像模块与被导出的值是一回事。默认导出使用 default 关键字将一个值声明为默认导出,每个模块只能有一个默认导出
export default foo
export default function() {}
export default function foo() {}
export default function*() {}
export default class {}
模块导入
模块可以通过使用import关键字使用其他模块导出的值。必须出现在模块的顶级
- 模块标识符可以是相对于当前模块的相对路径,也可以是指向模块文件的绝对路径。它必须是纯字符串,不能说动态计算的结果。
- 导入对模块来说是只读的,实际上相当于const声明的变量。在使用*执行批量导入时,赋值给别名的命名导出就好像使用Object.freeze()冻结过一样。直接修改导出的值时不可能的,但是可以修改导出对象的属性
- 命名导出和默认导出的区别也反映在他们的导入上。命名导出可以使用*批量获取并赋值给保存导出集合的别名,而无需列出每个标识符:
const foo = 'foo', bar = 'bar', baz = 'baz'
export {foo, bar, baz}import * as Foo form './foo.js'
console.log(Foo.foo); // foo
- 要指名导入,需要把标识符放在 import 子句中。
import { foo, bar, baz as myBaz } from './foo.js';
- 默认导出就好像整个模块就是导出值一样。可以使用 default 关键字并提供别名来导入。
import { default as foo } from './foo.js';
import foo from './foo.js'
模块转移导出
模块导入的值可以直接通过管道转移到导出。此时,也可以将默认导出转换为命名导出,或者相反。如果想把一个模块的所有命名导出集中在一块,可以像下面这样在bar.js中使用*导出:
export * from './foo.js'
这样,foo.js中的所有命名导出都会出现在导入bar.js的模块中。如果foo.js有默认导出,则该语法会忽略它。
相关文章:
ES6 -- 模块化(CommonJS、AMD、ES Module)
模块模式 将代码拆分成独立的块,然后再将这些块连接起来可以通过模块模式来实现。这种模式背后的思想很简单:把逻辑分块,各自封装,相互独立,每个块自行决定对外暴露什么,同时自行决定引入执行哪些外部代码…...
c# xml 参数读取读取的简单使用
完整使用之测试参数的读取(xml) 保存一个xml文档(如果没有就会生成一个默认的 里面的参数用的是我们默认设置的),之后每次更改里面的某项,然后保存 类似于重新刷新一遍。 这里所用的xml测试参数前面需要加…...
gym原来是这样用的
今天down了一个深度强化学习的程序,但是试来试去总是跑不成功,第一句就出问题了 env gym.make("clusterEnv-v0").unwrapped总是报没有该环境,思想半天,然后发现这是自己写的环境,需要到gym中去注册才能使用…...
百度SEO优化技巧与布局(提升网站排名的5种有效方法)
网站SEO关键词介绍: SEO(SearchEngineOptimization)即搜索引擎优化,是通过一系列技术手段和策略,让网站在搜索引擎中获得更好的排名和流量。关键词是SEO优化的重要组成部分,通过关键词布局合理,…...
文案配音软件哪个好?(适合新手使用)
随着短视频的逐渐普及,视频博主越来越多,所以很多朋友也期待成为视频博主。但是,如果你想成为一个有名的视频博主,你需要在很多层面上比别人做得更好。其中之一就是视频文字的配音。相信大部分人都没有配音的技巧,所以…...
excel映射xml方法
excel映射xml方法 创建xml模板 新建一个文本文件,编写模板并命名为xxx.xml <?xml version"1.0" encoding"UTF-8"?> <root><item ID""><surname></surname><man></man><woman>&…...
2023/10/15
文章目录 1.uniapp之Vue2升Vue3值得注意的几点1.1 页面生命周期的使用1.2 引入资源的方式 2. 浏览器本地存储之Cookie和webStorage3. CSS变量 var()的用法4. CSS之实现线性渐变背景5. 图片无法和文字对齐的正确解决方案6. 使用正则处理接口返回的富文本内的图片7. transition实…...
Linux系统中如何开启和配置OpenGauss数据库的远程连接
文章目录 前言1. Linux 安装 openGauss2. Linux 安装cpolar3. 创建openGauss主节点端口号公网地址4. 远程连接openGauss5. 固定连接TCP公网地址6. 固定地址连接测试 前言 openGauss是一款开源关系型数据库管理系统,采用木兰宽松许可证v2发行。openGauss内核深度融合…...
【Docker】Docker网络及容器间通信详解
目录 背景 默认网络 1、bridge 网络模式 2、host 网络模式 3、none 网络模式 4、container 网络模式 自定义网络 容器间网络通信 IP通信 Docker DNS server Joined容器 前言 本实验通过docker DNS server和joined 容器两种方法实现Docker容器间的通信。Docker容器间…...
TikTok国际版 使用特网科技Bluestacks模拟器安装方法
特网科技Bluestacks模拟器主机 桌面自带Bluestacks模拟器 TikTok国际版Bluestacks模拟器搜索tiktot 登录google应用商店-安装TikTok 安装过程可能需要3-5分钟不等-配置过低可能会导致安装失败,建议升级更高内存。 安装完成-打开 安装成功APP-我的游戏查看 打开国际版…...
【Hello Algorithm】暴力递归到动态规划(四)
动态规划的数组压缩技巧 - 机器人走格子问题 题目是leetcode62题目原题 表示如下 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中…...
arm day 8
arm 写一段按键中断代码 main.c #include "uart.h" #include "key_it.h" int main() {char c;char *s;uart4_init();//串口初始化//中断初始化key_it_config();while(1){//保证主程序不结束}return 0; } src/key_it.c #include"key_it.h"voi…...
k8s-14 存储之volumes
Volumes配置管理 容器中的文件在磁盘上是临时存放的,这给容器中运行的特殊应用程序带来一些问题。首先,当容器崩溃时,kubelet 将重新启动容器,容器中的文件将会丢失因为容器会以干净的状态重建。其次,当在一个 Pod 中…...
二分图博弈
一张二分图,Alice和Bob每人走一步,不能重复走,谁不能走谁输 结论:若存在最大匹配不包含初始点,则Bob赢,否则Alice赢 以上图为例,红色为最大匹配。 首先对于Alice第一步只能走黑边。而Alice无论…...
【C++】C++11—— 包装器
📝个人主页:Sherry的成长之路 🏠学习社区:Sherry的成长之路(个人社区) 📖专栏链接:C学习 🎯长路漫漫浩浩,万事皆有期待 上一篇博客:【C】C11…...
LED显示屏高刷新率和低刷新率有什么区别
LED显示屏的刷新率是指图像在LED显示屏上更新的速度,也即屏幕上的图像每秒钟出现的次数,它的单位是赫兹(Hz)。LED显示屏的刷新率越高,图像闪烁感就越小,稳定性也就越高,换言之对视力的保护也越好…...
国际伦敦银点差费值得吗?
伦敦银是国际轨技术属市场上广受追捧的白银保证金交易品种,具有交易时长、交易制度灵活、资金利用率高等诸多的优点。 国际伦敦银的优势主要来自它所实行的是保证金交易制度。目前香港平台一般执行的保证金比例标准是2%,以目前22美元/盎司左右的白银价格…...
常见的作物模型应用技巧!DSSAT模型、APSIM模型、WOFOST模型与PCSE模型等应用
①最新DSSAT作物模型建模方法及应用 DSSAT模型内核算法是基于Fortran语言开发的,软件界面是基于C进行开发。了解和熟悉DSSAT模型的关键算法和软件的操作是学习DSSAT模型的基础。此外,想要成为一名优秀的作物模型使用者与科研团队不可或缺的人才ÿ…...
2023年中国超硬材料制品分析及超硬刀具市场规模分析[图]
超硬材料是指硬度特别高的材料,可分为天然以及人造两种,前者主要包括天然的钻石(金刚石)、黑钻石,后者则包括人造金刚石、立方氮化硼。 超硬材料制品分类 资料来源:共研产业咨询(共研网&#x…...
使用React、Express实现一个问卷发布/收集系统
1. 设置项目结构 questionnaire-system/client/ // 前端应用src/components/ // React组件pages/ // 页面App.jsindex.jsserver/ // 后端服务routes/ // 路由models/ // 数据模型app.jspackage.json2. 启动前端应用…...
DDD之上下文映射图(Context Mapping)
领域驱动设计系列文章,点击上方合集↑ 1. 开头 在DDD中,限界上下文与限界上下文之间需要相互集成,这种集成关系在DDD中称为上下文映射(Context Mapping),也就是子域与子域之间的集成关系。 所以首先我们…...
CountDownLatch的原理
使用CountDownLatch可以实现等待多个线程执行完毕的功能,实现线程之间的协调,让它们按照我们期望的顺序执行,从而避免了可能出现的并发问题。 CountDownLatch是如何实现主线程等待子线程全部结束的呢? 代码用例 这里我们使用一段…...
Java新特性Stream流详解
一、概述 Stream流是Java 8 API添加的一个新的抽象,以一种声明性方式处理数据集合(侧重对于源数据计算能力的封装,并且支持序列与并行两种操作方式)。 Stream流是对集合(Collection)对象功能的增强…...
关于VScode中一些常用的快捷操作!
vscode CTRLO:打开文件夹以开始工作 先CTRLK 再CTRLO:打开文件夹以开始工作 如何选择workspace:file → open folder→选目标文件夹【当前工作区选择会影响代码是否能运行】 如何打开终端:View → terminal debug看不到变化历史&…...
Django 使用Mysql数据库
目录 Django 使用Mysql数据库本地安装Mysql数据服务安装好Pymysql服务Django配置数据库迁移各种报错无法找到mysqlclient数据库拒绝连接 Django 使用Mysql数据库 本地安装Mysql数据服务 安装好Pymysql服务 python3 -m pip install PyMySQL官方文档介绍 Django配置 官网文档 …...
js继承的几种方式(原型链继承、构造函数继承、组合式继承、寄生组合式继承、ES6的Class类继承)
1.原型链继承 实现原理:子类的原型指向父类实例。子类在自身实例上找不到属性和方法时去它父类实例(父类实例和实例的原型对象)上查找,从而实现对父类属性和方法的继承 缺点: 子类创建时不能传参(即没有…...
AnyTransition/过渡动画, MatchedGeometryEffect/匹配几何动画效果 的使用
1. AnyTransition 过渡动画效果 1.1 创建过度动画案例 AnyTransitionBootcamp.swift import SwiftUI/// 旋转修饰 View struct RotateViewModifier :ViewModifier{let rotation: Doublefunc body(content: Content) -> some View {content.rotationEffect(Angle(degrees: r…...
mac版postman升级后数据恢复办法
postman升级了一下,所有的collections都丢失了。 首先在finder里找到这个路径 /Users/{用户名}/Library/Application Support/Postman找到升级之前的的最新的backup.json,然后在postman里import这个文件。 所有升级前的collections都恢复了࿰…...
四.镜头知识之放大倍率
四.镜头知识之放大倍率 文章目录 四.镜头知识之放大倍率4.0 前言4.1 镜头的光学放大倍率的计算方法4.2 显示器的电子放大倍率4.2.1 智能硬件产品的显示放大倍率计算案例4.3 系统放大倍率4.4 智能硬件产品的系统放大倍率计算案例4.4 智能硬件产品的系统放大倍率计算案例4.0 前言…...
Jenkins UI 自动化持续化集成测试
一:安装jenkins 环境 在官网下载msi 直接安装即可 二:设置全局变量 设置allure 路径 三:创建项目 1、创建自由风格项目 2、如果项目在本地,且本地服务器是windows ,找到Jenkins安装根目录,寻找config…...
wordpress 中文编辑器/网络营销专业是做什么的
概述 Executors类是JDK 1.5开始自带的一个非常强大的主要用于创建各类线程池的工具类。 常用方法介绍 newFixedThreadPool newFixedThreadPool方法有两种函数签名: 1 2public static ExecutorService newFixedThreadPool(int nThreads) public static ExecutorSe…...
成都网站建设 erp/搜索引擎谷歌入口
教育 -花卉栽培-章节资料考试资料-潍坊职业学院【】 庭院常用花卉栽培技术—单元作业 庭院常用花卉栽培技术—单元测验 1、【单选题】属于二年生花卉的是( )。 A、万寿菊 B、波斯菊 C、百日菊 D、羽衣甘蓝 参考资料【 】 2、【单选题】在北方寒冷地区冬天…...
茂县建设局网站/谁有恶意点击软件
// template_one.cpp : 定义控制台应用程序的入口点。 //#include "stdafx.h" #include<iostream> using namespace std;//如果想要将类模板的声明与实现分别放在.h和.cpp文件中,那么在使用到类模板实现的文件,需要将该.cpp文件include进…...
中国工程建设造价信息网站/北京seo实战培训班
有时我们在安装系统后,发现没有安装当前系统的内核源码在/usr/src/kernels目录下。其实很简单,是少安装了一个rpm包(kernel-devel); 安装上就可以了 有些软件安装没有问题,运行时就报错。(我今天…...
aspx网站实例/seo整站优化费用
你的外部for循环条件给你带来了问题.这是你的循环: –for (int i 0; i < array[i].length; i)现在,当我达到值3时,您正在尝试访问数组[3] .length.这将抛出IndexOutOfBounds异常.由于每个内部数组的大小相同,您可以将循环更改为: –for (int i 0; i…...
游戏网站app/石家庄网站建设方案推广
解决方法如下: 1>、进入超级用户模式。也就是输入"su -",系统会让你输入超级用户密码,输入密码后就进入了超级用户模式。 2>、添加文件的写权限。也就是输入命令"chmod uw /etc/sudoers"。 3>、编辑/etc/sudoers文件…...