当前位置: 首页 > news >正文

JS模块化,ESM模块规范的 导入、导出、引用、调用详解

JS模块化,ESM模块规范的 导入、导出、引用、调用详解

  • 写在前面
  • 实例代码
    • 1、模块导出 - export
      • 导出之 - 独立导出
      • 导出之 - 集中多个导出
      • 导出之 - 默认导出
      • 导出之 - 集中默认导出
      • 导出之 - 混合导出
    • 2、模块导入 - import
      • 导入之 - 全部导入
      • 导入之 - 默认导入
      • 导入之 - 指定导入
      • 导入之 - 混合导入
      • 导入之 - 改名导入
    • 3、模块导入即导出
      • 导入即导出之 - 所有导入导出
      • 导入即导出之 - 默认导入导出
      • 导入即导出之 - 默认改名导入导出
      • 导入即导出之 - 指定多个导入导出
      • 导入即导出之 - 混合导入即导出
    • 4、模块引用与调用
      • 引用与调用之 - 本地资源加载
      • 引用与调用之 - 异步加载模块

写在前面

在之前的 JS模块化的各种规范 之 CJS、AMD、CMD、UMD、ESM 文章中,介绍了关于JS模块化的各种规范的区别和简单使用。
由于ESM模块规范也是 ECMAScript2015(ES6)中的规范标准,在日常的Web项目开发、小程序开发、APP开发等都是很常用的,所以本文重点将 ESM模块规范中的 导出、导入、导出、引用、调用等,结合日常开发需求做进一步的介绍。

实例代码

这里分别以不同的实例代码,逐步介绍ESM模块规范的导出、 导入、引用、调用等使用方法。

1、模块导出 - export

模块导出 就是将js文件中的 变量、常量、函数、对象、类 等对象 向外导出(暴露)以方便外部的js文件所引用和调用。
在JS的ESM模块规范中,主要通过 export 关键字 来 向外导出想要导出(暴露)的对象。

导出之 - 独立导出

独立导出方式,是直接在要向外导出(暴露)变量、常量、函数、对象、类 等对象的对面加上 export 关键字即可!

export let count = 666;export const PI = Math.PI;const random = Math.random();
export { random as default };export const sum = (n1, n2) => {return n1 + n2;
};export function isOdd(n) {return n % 2 === 1 || n % 2 === -1;
};export class Person {constructor(name) {this.name = name;}sayHello() {console.log(`Hello! 我是${this.name}`);}
};

导出之 - 集中多个导出

集中多个导出方式,一般是在代码的最底部,将要向外导出(暴露)变量、常量、函数、对象、类等对象,通过 export export default 以对象的形式导出!

let count = 666;const PI = Math.PI;const sum = (n1, n2) => {return n1 + n2;
};function isOdd(n) {return n % 2 === 1 || n % 2 === -1;
};class Person {constructor(name) {this.name = name;}sayHello() {console.log(`Hello! 我是${this.name}`);}
};// 集中多个导出
export {count, // 注:如果对象中的 键key 和 值value 的命名完全相同 可省去 :random 后面这部分!!PI,sum,isOdd,Person
};

导出之 - 默认导出

默认导出方式,是使用 export default 关键字 直接导出,该导出方式只能导出单个内容。

// 可直接向外导出(暴露)变量、常量、函数、对象、类等对象
export default function sayHello(name) {console.log(`Hello! 我是${name}`);
};
  • 注意:export default 默认导出 在一个js模块文件中,不能同时存在多个默认导出(也就是说,在一个js模块文件中 export default 能只出现一次!!!)

导出之 - 集中默认导出

集中默认导出方式,是使用 export default 关键字 以对象形式导出,该导出方式可以同时导出多个内容。

const PI = Math.PIfunction isOdd(n) {return n % 2 === 1 || n % 2 === -1;
};class Person {constructor(name) {this.name = name;}sayHello() {console.log(`Hello! 我是${this.name}`);}
};export default {count: 666,PI,sum: (n1, n2) => {return n1 + n2;},isOdd,Person,sayHello: function (name = '') {console.log(`Hello! 我是${name}`);},
};

导出之 - 混合导出

混合导出方式,就是 在一个JS模块文件中,既有独立导出、集中导出 又有 默认导出、集中默认导出等形式一起组合导出。

📢下面混合导出的代码内容 以 demo.js 文件命名,为接下来的模块 导入、引用、调用实例做演示用!!

/*** demo.js*/let count = 666;// 独立导出 常量
export const PI = Math.PI;const sum = (n1, n2) => {return n1 + n2;
};// 独立导出 函数
export function isOdd(n) {return n % 2 === 1 || n % 2 === -1;
};// 独立导出 类
export class Person {constructor(name = '') {this.name = name;}sayHello() {console.log(`Hello! 我是${this.name}`);}
};// 默认导出
export default {// 默认导出 变量count: count,// 默认导出 函数sum,// 默认导出 类Person,// 默认导出 字符变量 (可直接创建 并 导出[ 变量、常量、函数、对象、类] 等对象)pi: '3.141592653589793',// 默认导出 函数 方式1is: function (val, type) {return toString.call(val) === `[object ${type}]`;},// 默认导出 函数 方式2isArray: (arr = []) => {return Object.prototype.toString.call(arr) === '[object Array]' || Array.isArray(arr);},// 默认导出 函数 方式3isObject(val) {// 注:在这里还可以通过 this关键字 来调用当前默认导出模块中的 其他导出属性内容// 如 this.pi; this.sum(1, 2);return val !== null && this.is(val, 'Object') || (typeof val === 'object' && val !== null);},// 默认导出 类AudioTrack: class {constructor(trackId = '', trackName = '', trackUrl = 'https://') {this.trackId = trackId;this.trackName = trackName;this.trackUrl = trackUrl;};start() {console.log(`开始播放${this.trackName}`);};stop() {console.log(`停止播放${this.trackName}`);};}
};

2、模块导入 - import

在JS的ESM模块规范中,
当通过 export 关键字 来 向外导出想要导出(暴露)对象以后,
就可以通 import 关键字 来 导入 对应的(注:要一一对应) 导出内容。

导入之 - 全部导入

全部导入方式,使用 ⁎星号 将模块文件中所有的import 独立导出、export default 默认导出 等导出的内容全部导入进来

import * as all from "./demo.js";
// 注:通过export default 关键 默认导出(暴露)的内容在default属性中,和export独立导出的在同一级上!!
console.log('demo.js模块 所有导出的内容:', all);

导入之 - 默认导入

默认导入方式,只会将导出文件中通过export default 关键字向外 导出(暴露)的内容导入进来。

import def from "./demo.js";
// 注:该导入方式只会 export default 关键字向外 导出(暴露)的内容导入进来!
console.log('demo.js模块 默认导出的内容:', def );

导入之 - 指定导入

指定导入方式,是将导出文件中通过export 关键字向外 导出(暴露)的内容 根据指定变量名(不分顺序)的导入进来。

// 指定将PI, isOdd, Person 导入进来
import { PI, isOdd, Person } from "./demo.js";

导入之 - 混合导入

混合导入方式,就是将导出文件中通过export default 关键字 和 export 关键字 向外 导出(暴露)的内容 根据指定变量名(不分顺序)的导入进来。

// 注:def 接收的就是在导出文件中通过export default 关键字向外导出内容,而在大括号{}中接收到在导出文件中通过export关键字向外导出内容。
// 注:def 这个变量名字是可能自定义的。
import def, { PI, isOdd, Person } from "./demo.js";

导入之 - 改名导入

改名导入,是在导入时的 变量名 和 当前文件中的 变量名 有冲突(相同)时,通过 as 关键字 将导入的变量 新更改一下名字,再导入进来。

// 将原大写的PI 更改为 小写的pi
import def, { PI as pi, isOdd, Person } from "./demo.js";// 当前文件中的 变量名 有冲突
const PI = '3.141592653589793 ';
console.log(PI, pi);

3、模块导入即导出

模块导入即导出方式,一般主要是用于,为了尽可能的减少 在各个JS模块文件之间出到多次导入问题的。
例如:
在A.js模块文件中,同时需要用到B.js模块文件 和 C.js模块文件。
而B.js模块文件中也要用到C.js模块文件。
此时: 我们可以只需在A.js模块文件中 导入 B.js模块文件,然后B.js模块文件中 导入 C.js模块文件即可。

导入即导出之 - 所有导入导出

所有导入导出,是将模块所有的内容导入 又 全部导出。

  • 这里扮演的B.js模块文件 向A.js模块文件 导出C.js模块文件中的所有导出 。
export * from './demo.js';

导入即导出之 - 默认导入导出

默认导入导出,是将 demo.js模块文件中的 export default 默认模块向外导出。

export  { default } from './demo.js';

导入即导出之 - 默认改名导入导出

将 demo.js模块文件中的 export default 默认模块改名在MyDemo下向外导出。

export  { default as MyDemo } from './demo.js';

导入即导出之 - 指定多个导入导出

指定多个导入导出,是将导出文件中通过export 关键字向外 导出(暴露)的内容 根据指定变量名(不分顺序)的导入和导出

  • 这里扮演的B.js模块文件 向A.js模块文件导出PI, random, isOdd,【在A.js模块文件中,同时需要用到B.js模块文件 和 C.js模块文件】。
export  { PI, random, isOdd } from './demo.js';

导入即导出之 - 混合导入即导出

混合导入即导出,就是将 默认模块 和 指定多个变量一起导出。

// 注:default 是关键字,它装着在导出模块文件中通过export default默认导出的内容。
export { default PI, isOdd, Person } from './demo.js';// 将 demo.js模块文件中的 export  default 默认模块改名在myDef后向外导出。
export { default as myDef, PI, isOdd, Person } from './demo.js';

4、模块引用与调用

在模块导入以后 引用与调用,就是在模块导入以后 就和 我们平时在一个js文件中写代码一样去引用和调用 变量、常量、函数、对象、类 等对象一样,直接使用即可。

引用与调用之 - 本地资源加载

在vite + vue3 项目开发过程,有时需要在 js 代码中去加载本地图片,由于vite默认不支持 require()方法,所以我们可以使用 import来加载本地资源,而且 在项目构建(打包)后也能正常的显示资源。

  • 注:在下面代码中, 资源前面的…/assets/ 是根据当前这个getLocalFile()函数所在的js文件的相对路径,在vue项目中,一般这个文件是放在src目录下面的utils文件夹里面,而资产文件则一般是放在src目录下面的assets文件夹里面,utils 和 assets是同一级目录的(都在src目录下);

function getLocalFile(url) {return new URL(`../assets/${url}`, import.meta.url).href;
};
getLocalFile('img/logo.jpg');// ts写法的简写
const getLocalFile = (url: string): string => new URL(`../assets/${url}`, import.meta.url).href;
getLocalFile('img/logo.jpg');

引用与调用之 - 异步加载模块

模块异步加载,在一些业务场景中是非常有用的,例如:聊天室,在用户进入聊天室之前需要先进行登录后才能进入,所以在用户没登录成功以前,WebSocket是不应该连接的,需要等到登录成功以后才连接。


function load() {import('./demo.js').then((esm) => {console.log('esm就是./demo.js模块文件中所有导出的内容:', esm);console.log(esm.PI);const def = esm.default;console.log('esm.default就是./demo.js模块文件中默认导出的内容:', def);def.sum(100, 200);});import('./demo.js').then(({ PI, isOdd, Person }) => {console.log('也可以直接解构./demo.js模块文件分别独立导出的内容:', PI, isOdd, Person);isOdd(666);const p = new Person('沐枫');p.sayHello();});
};// 在用户点击以后再去加载 想要引用和调用的模块。
btn.onclick = function () {load();
};// 注:如果是在html文件中直接使用时,需要在script标签中加上type="module"属性,并且要在http服务器环境中打开才能正常使用哦!!
<script type="module">import('./demo.js').then((esm) => {...});
</script>

相关文章:

JS模块化,ESM模块规范的 导入、导出、引用、调用详解

JS模块化&#xff0c;ESM模块规范的 导入、导出、引用、调用详解 写在前面实例代码1、模块导出 - export导出之 - 独立导出导出之 - 集中多个导出导出之 - 默认导出导出之 - 集中默认导出导出之 - 混合导出 2、模块导入 - import导入之 - 全部导入导入之 - 默认导入导入之 - 指…...

markdown常用的快捷键

一级标题 #加 空格 是一级标题 二级标题 ##加空格是二级标题 三级标题 字体 * 粗体&#xff1a;两个**号 斜体&#xff1a;一个 斜体加粗&#xff1a;三个 删除&#xff1a;两个~~ 我是字体 我是字体 我是字体 我是字体 引用 箭头符号>加空格 回车 分割线 三个 - …...

VSCode中的任务什么情况下需要配置多个问题匹配器problemMatcher?多个问题匹配器之间的关系是什么?

☞ ░ 前往老猿Python博客 ░ https://blog.csdn.net/LaoYuanPython 一、简介 在 VS Code 中&#xff0c;tasks.json 文件中的 problemMatcher 字段用于定义如何解析任务输出中的问题&#xff08;错误、警告等&#xff09;。 problemMatcher是一个描述问题匹配器的接口&…...

C语言鞍点数组改进版

题目内容&#xff1a; 给定一个n*n矩阵A。矩阵A的鞍点是一个位置&#xff08;i&#xff0c;j&#xff09;&#xff0c;在该位置上的元素是第i行上的最大数&#xff0c;第j列上的最小数。一个矩阵A也可能没有鞍点。 你的任务是找出A的鞍点。 改进目标&#xff1a; 网络上很多…...

K8s:部署 CNI 网络组件+k8s 多master集群部署+负载均衡及Dashboard k8s仪表盘图像化展示

目录 1 部署 CNI 网络组件 1.1 部署 flannel 1.2 部署 Calico 1.3 部署 CoreDNS 2 负载均衡部署 3 部署 Dashboard 1 部署 CNI 网络组件 1.1 部署 flannel K8S 中 Pod 网络通信&#xff1a; ●Pod 内容器与容器之间的通信 在同一个 Pod 内的容器&#xff08;Pod 内的容…...

【数据结构】树家族

目录 树的相关术语树家族二叉树霍夫曼树二叉查找树 BST平衡二叉树 AVL红黑树伸展树替罪羊树 B树B树B* 树 当谈到数据结构中的树时&#xff0c;我们通常指的是一种分层的数据结构&#xff0c;它由节点&#xff08;nodes&#xff09;组成&#xff0c;这些节点之间以边&#xff08…...

Vert.x学习笔记-Vert.x的基本处理单元Verticle

Verticle介绍 Verticle是Vert.x的基本处理单元&#xff0c;Vert.x应用程序中存在着处理各种事件的处理单元&#xff0c;比如负责HTTP API响应请求的处理单元、负责数据库存取的处理单元、负责向第三方发送请求的处理单元。Verticle就是对这些功能单元的封装&#xff0c;Vertic…...

干货分享:基于 LSTM 的广告库存预估算法

近年来&#xff0c;随着互联网的发展&#xff0c;在线广告营销成为一种非常重要的商业模式。出于广告流量商业化售卖和日常业务投放精细化运营的目的&#xff0c;需要对广告流量进行更精准的预估&#xff0c;从而更精细的进行广告库存管理。 因此&#xff0c;携程广告纵横平台…...

dataframe删除某一列

drop import pandas as pd data {‘A’: [1, 2, 3], ‘B’: [4, 5, 6], ‘C’: [7, 8, 9]} df pd.DataFrame(data) #使用drop方法删除列 df df.drop(‘B’, axis1) # 通过指定列名和axis1来删除列 del import pandas as pd data {‘A’: [1, 2, 3], ‘B’: [4, 5, 6]…...

提升ChatGPT答案质量和准确性的方法Prompt engineering

文章目录 怎么获得优质的答案设计一个优质prompt的步骤:Prompt公式:示例怎么获得优质的答案 影响模型回答精确度的因素 我们应该知道一个好的提示词,要具备一下要点: 清晰简洁,不要有歧义; 有明确的任务/问题,任务如果太复杂,需要拆分成子任务分步完成; 确保prompt中…...

SpringBoot + Vue2项目打包部署到服务器后,使用Nginx配置SSL证书,配置访问HTTP协议转HTTPS协议

配置nginx.conf文件&#xff0c;这个文件一般在/etc/nginx/...中&#xff0c;由于每个人的体质不一样&#xff0c;也有可能在别的路径里&#xff0c;自己找找... # 配置工作进程的最大连接数 events {worker_connections 1024; }# 配置HTTP服务 http {# 导入mime.types配置文件…...

HTML 表格

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>表格标签</title>/* <style>.yun {widt…...

AIGC(生成式AI)试用 10 -- 安全性问题

上次遗留的问题&#xff1a;代码的安全性呢&#xff1f;下次找几个问题测试下看。 AI&#xff0c;你安全吗&#xff1f; AI生成的程序&#xff0c;安全吗&#xff1f; 也许这个世界最难做的事就是自己测试自己&#xff1a;测试什么&#xff1f;如何测&#xff1f; …...

STM32循迹小车原理介绍和代码示例

目录 1. 循迹模块介绍 2. 循迹小车原理 3. 循迹小车核心代码 4. 循迹小车解决转弯平滑问题 1. 循迹模块介绍 TCRT5000传感器的红外发射二极管不断发射红外线当发射出的红外线没有被反射回来或被反射回来但强度不够大时红外接收管一直处于关断状态&#xff0c;此时模块的输出…...

Nginx 配置详细讲解

Nginx.conf 配置文件分为三部分&#xff0c;分别为main块、events块、http块&#xff08;http块又包含server块和location块&#xff09;&#xff0c;如下图。 第一部分&#xff1a;main块(全局块) main块主要是设置一些影响Nginx服务器整体运行的配置指令&#xff0c;主要包括…...

gdb 日志记录不显示到屏幕的方法(gdb13最新版)

tags: gdb categories: [Debug] 写在前面 gdb 的更新好快啊… 之前的选项都有改动了, 比如 logging… 需要屏幕重定向不能简单设置: set logging on set logging redirect on了, 而是要多开一个配置, 踩坑了 方法 在此之前先看一下我的 gdbinit 配置: set debuginfod e…...

JAVA智慧工地管理系统源码基于微服务

智慧工地是将互联网的理念和科技引入施工现场&#xff0c;从施工现场源头抓起&#xff0c;大程度的收集人员、安全、环境、质量等关键业务数据。通过结合物联网、大数据、互联网、云计算等技术建立云端大数据管理平台&#xff0c;形成端云大数据的体系与模式&#xff0c;这就是…...

学习笔记三十四:Ingress和 Ingress Controller概述

Ingress和 Ingress Controller概述 回顾service四层负载在k8s中为什么要做负载均衡Service不足之处四层负载和七层负载的区别OSI七层模型&#xff1a; Ingress介绍Ingress Controller介绍Ingress-controller 作用Ingress和Ingress Controller总结使用Ingress Controller代理k8s…...

Webpack的Tree Shaking。它的作用是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…...

研发效能DevOps: Git安装

目录 一、理论 1.Git 2.Git 工具 二、实验 1.Git安装 2.配置Git 3. VS Code加载Git 一、理论 1.Git &#xff08;1&#xff09;简介 Git 是一个分布式版本控制及源代码管理工具;Git 可以为你的项目保存若干快照&#xff0c;以此来对整个项目进行版本管理。 Git 是一个…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程

STM32F1 本教程使用零知标准板&#xff08;STM32F103RBT6&#xff09;通过I2C驱动ICM20948九轴传感器&#xff0c;实现姿态解算&#xff0c;并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化&#xff0c;适合嵌入式及物联网开发者。在基础驱动上新增…...

MySQL的pymysql操作

本章是MySQL的最后一章&#xff0c;MySQL到此完结&#xff0c;下一站Hadoop&#xff01;&#xff01;&#xff01; 这章很简单&#xff0c;完整代码在最后&#xff0c;详细讲解之前python课程里面也有&#xff0c;感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...

《信号与系统》第 6 章 信号与系统的时域和频域特性

目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...

Python爬虫实战:研究Restkit库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的有价值数据。如何高效地采集这些数据并将其应用于实际业务中,成为了许多企业和开发者关注的焦点。网络爬虫技术作为一种自动化的数据采集工具,可以帮助我们从网页中提取所需的信息。而 RESTful API …...

goreplay

1.github地址 https://github.com/buger/goreplay 2.简单介绍 GoReplay 是一个开源的网络监控工具&#xff0c;可以记录用户的实时流量并将其用于镜像、负载测试、监控和详细分析。 3.出现背景 随着应用程序的增长&#xff0c;测试它所需的工作量也会呈指数级增长。GoRepl…...