1.esm是什么

esm 是将 javascript 程序拆分成多个单独模块,并能按需导入的标准。和webpackbabel不同的是,esm 是 javascript 的标准功能,在浏览器端和 nodejs 中都已得到实现。使用 esm 的好处是浏览器可以最优化加载模块,比使用库更有效率

esm 标准通过importexport语法实现模块变量的导入和导出

esm 模块的特点

  1. 存在模块作用域,顶层变量都定义在该作用域,外部不可见
  2. 模块脚本自动采用严格模式
  3. 模块顶层的this关键字返回undefined
  4. esm 是编译时加载,也就是只有所有import的模块都加载完成,才会开始执行
  5. 同一个模块如果加载多次,只会执行一次

2.export

export语句用来导出模块中的变量

// 导出变量
export let count = 1;
export const CONST_VAR = 'CONST_VAR';
// 导出函数
export function incCount() {count += 1;
}
// 导出类
export class Demo {}function add(x) {return x + count;
}
// 使用export导出一组变量
export {count,add,// 使用as重命名导出的变量add as addCount,
}// 导出default
export default add// 合并导出其他模块的变量
export { name } from './esm_module2.js'
export * from './esm_module2.js'

3.import

import语句用来导入其他模块的变量

// 导入变量
import { count, incCount, CONST_VAR } from './esm_module1.js';// 通过as重命名导入的变量
import { addCount as renamedAddCount } from './esm_module1.js';// 导入默认
import { default as defaultAdd } from './esm_module1.js';
import add from './esm_module1.js';// 创建模块对象
import * as module1 from './esm_module1.js';

4.export 导出的是值引用

esm 模块和 commonjs 模块的一个显著差异是,cjs 导出的是值得拷贝,esm 导出的是值的引用。当模块内部的值被修改时,cjs 获取不到被修改后的值,esm 可以获取到被修改后的值。

cjs 例子

// cjs_module1.js
var count = 1;
function incCount() {count += 1;
}module.exports = {count: count,incCount: incCount,
}// cjs_demo.js
var { count, incCount } = require('./cjs_module1.js');console.log(count); // 1
incCount();
console.log(count); // 1

esm 例子

// esm_module1.js
let count = 1;
function incCount() {count += 1;
}export {count,incCount,
}// esm_demo.js
import { count, incCount } from './esm_module1.js';console.log(count); // 1
incCount();
console.log(count); // 2

从实现原理上来看,cjs 的 module.exports是一个对象,在运行期注入模块。在导出语句module.exports.count = count执行时,是给这个对象分配一个count的键,并赋值为1。 这之后模块中的count变量再怎么变化,都不会干扰到module.exports.count

esm 中的export { count }是导出了count变量的一个只读引用,等于说使用者读取count时,值的指向还是模块中count变量的值。

可以看阮一峰的这篇文章

ES6 入门教程

5.在 html 中使用 esm

使用script标签引入 esm 文件,同时设置type=module,标识这个模块为顶级模块。浏览器将 esm 文件视为模块文件,识别模块的import语句并加载。

<script src="./esm_main.js" type="module"></script>

如果不设置type=module,浏览器认为该文件为普通脚本。检查到文件中存在import语句时,会报如下错误

6.esm的加载机制

esm 标准没有规定模块的加载细节,将这些留给具体环境实现。大致上分为下面四个步骤:

解析:实现读取模块的源代码并检查语法错误

加载:递归加载所有import的模块

链接:对每个加载的模块,都生成一个模块作用域,该模块下的所有全局声明都绑定到该作用域上,包括从其他模块导入的内容

运行时:完成所有import的加载和链接,脚本运行每个已经加载的模块中的语句。当运行到全局声明时,什么也不会做(在链接阶段已经将声明绑定到模块作用域)。

可以看下 mdn 上的这篇深入 esm 的文章

ES6 In Depth: Modules - Mozilla Hacks - the Web developer blog

7.动态加载模块

esm 的一个重要特性是编译时加载,这有利于引擎的静态分析。加载的过程会先于代码的执行。却也导致import导入语句不能在函数或者if语句中执行

// 报语法错误
if (true) {import add from './esm_module1.js';
}

es2020 提案引入import()函数,用来动态加载模块,并且可以用在函数和if语句中。

import('./esm_module1.js').then(module => {console.log(module);})

import()函数接受要加载的模块相对路径,返回一个Promise对象,内容是要加载的模块对象。

使用import()函数还可以实现根据变量动态加载模块

async function getTemplate(templateName) {let template = await import(`./templates/${templateName}`);console.log(template);
}getTemplate("foo");
getTemplate("bar");
getTemplate("baz");

javascript中的esm,import, export相关推荐

  1. 彻底搞清楚javascript中的require、import和export

    为什么有模块概念 理想情况下,开发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块. 但是,Javascript不是一种模块化编程语言,在es6以前,它是不支持"类"( ...

  2. 【彻底搞清楚javascript中的require、import和export 】

    彻底搞清楚javascript中的require.import和export - 最骚的就是你 - 博客园

  3. 1.3 Quick Start中 Step 7: Use Kafka Connect to import/export data官网剖析(博主推荐)

    不多说,直接上干货! 一切来源于官网 http://kafka.apache.org/documentation/ Step 7: Use Kafka Connect to import/export ...

  4. 一篇文章弄懂 JavaScript 中的 import

    import 语句用于导入由另一个模块导出的绑定.无论是否声明了 strict mode,导入的模块都运行在严格模式下.import语句不能在嵌入式脚本中使用. 语法 import defaultEx ...

  5. JavaScript 中 10 个需要掌握基础的问题

    作者:hackernoon 译者:前端小智 来源:Kiran https://mp.weixin.qq.com/s/q0Pvqi9oHOXn7hO02_v4_g 点赞再看,微信搜索 [大迁世界] 关注 ...

  6. [译] JavaScript 中的 CSS:基于组件的样式的未来

    本文讲的是[译] JavaScript 中的 CSS:基于组件的样式的未来, 原文地址:CSS in JavaScript: The future of component-based styling ...

  7. es6 依赖循环_探索 JavaScript 中的依赖管理及循环依赖

    我们通常会把项目中使用的第三方依赖写在 package.json 文件里,然后使用 npm .cnpm 或者 yarn 这些流行的依赖管理工具来帮我们管理这些依赖.但是它们是如何管理这些依赖的.它们之 ...

  8. import 别名_es6模块 import, export 知识点小结

    目前基于webpack.rollup等构建工具进行开发,模块化已经是常态,基本的import.export操作少不了,这里对常用的一些方法做一下总结. ES6模块只支持静态导出,你只可以在模块的最外层 ...

  9. JavaScript中的数据类型判断

    typeof typeof 操作符返回一个字符串,表示未经计算的操作数的类型. 语法 typeof 运算符后接操作数: typeof operand typeof(operand) 参数 operan ...

最新文章

  1. 打造一个宇宙 星系模拟产生对宇宙进化惊人见解
  2. Nginx在安装过程经常出现的问题
  3. volatile指令重排_有多少人面试栽到Volatile上?面试问题都总结到这儿了
  4. HTMl5的存储方式sessionStorage和localStorage详解
  5. python dataframe转置_Dataframe数据的增删改查,对齐(相加),转置,按值(索引)排序
  6. 遇见不在洛谷收藏里的好题(并没有做)
  7. 导出jvm的内存快照进行分析
  8. Spring Boot从Controller层进行单元测试
  9. Android BlueDroid(三):BlueDroid蓝牙开启过程enable
  10. java用户注册模块_用户注册登录模块设计方案报告.docx
  11. 蓝桥杯第八届省赛本科B组C/C++第九题 分巧克力
  12. win10自动停用打印服务器,技术员详解win10系统添加打印机总是自动关闭打印服务的技巧...
  13. 软件工程和计算机科学考公务员,软件工程可以考公务员吗
  14. Ceph 分布式存储架构解析与工作原理
  15. android 华为部分手机剪裁图片模糊问题
  16. md语法语法_PHP –语法概述
  17. 网上宣传的0月租流量卡是骗局吗?看完你就知道了!
  18. 互斥锁Mutex解锁两次
  19. C语言-switch-case语句与多分支结构
  20. 编译原理 实验4 语义分析(基于PL/0,使用C++代码编写)

热门文章

  1. js获取最近七天日期
  2. Java泛型 T extends Serializable
  3. 每日一句英语,看我能够坚持多久
  4. [附源码]Python计算机毕业设计Django的高校资源共享平台
  5. 数据平台的基本功能是什么_如何搭建数据分析平台
  6. 首富软件测试工资,测试你成为富豪 测试你天生是什么命
  7. 小啊呜产品读书笔记001:《邱岳的产品手记-14》第26讲 写好产品文档的诀窍 第27讲 产品案例分析: QuartzHooked的对话式交互
  8. 屏幕小于6英寸的手机_有什么6英寸以下的小屏手机推荐?
  9. MEMC 是什么意思?
  10. 最强Android教程!怒斩获了30家互联网公司offer,赶紧收藏!