ESM对比CommonJS

news2024/9/19 13:47:15

以下内容均总结自es-modules-a-cartoon-deep-dive

1. ESM是异步的而CommonJS是同步的

异步是ESM面临的最大挑战。和CommonJS的执行环境Node获取模块文件的方式不同,ESM获取模块文件是通过网络。如果ESM从获取到执行所有模块都是顺序进行会导致主线程长期处于pending状态,无法响应用户事件。

import "https://example.com/main.js"
console.log("我在等上面导入的模块执行完成")

为了解决这个问题ESM将模块的解析和执行分成了三部分,分别是构建(Construction),实例化(Instantiation)和执行(Evaluation)。
浏览器在构建阶段会通过入口模块(<script type="module" src="https://example.com/main.js" />)下载所有依赖的模块生成模块的依赖图。这部分工作不会阻塞主线程,此时主线程可以响应用户的点击滚动等事件。
而CommonJS则无此顾虑。Node脚本运行在服务器中,而对应的模块文件也可以在服务器的磁盘中获取而无需通过网络,所以模块加载和执行可以同步进行,没有加载时间过长阻塞主线程的顾虑。

2. ESM是编译时解析依赖而CommonJS是运行时解析依赖

一个字符串"https://example.com/main.js"在编译时可以被理解为字符串,在运行时也是一个字符串,但是如果是一个标识符pathname在编译时和运行时含义则打不相同,该标识符在代码没有执行到这块的时无法确定其具体值。这就导致ESM的module specifier(就是下图部分,图片来自es-modules-a-cartoon-deep-dive),无法使用标识符。
在这里插入图片描述
例:

import {count} from "./counter.js" // ok
import {count} from `${pathname}.js` // error

在CommonJS中module specifier中存在变量是合法的,因为CommonJS中模块的解析是在运行时,在运行时标识符pathname可以计算出值。

require(`${pathname}.js`) // ok

3. ESM导出的是引用而CommonJS导出的是值拷贝

在ESM中导入的变量会跟着导出的变动而变动。

ESM

// module.js
export let a = 1;
export function changeA() {a = 10;}

// entry.js
import {a, changeA} from './module.js';
changeA();
console.log(a); // 10

变量a在原模块中变成10后,在导入模块entry中也会跟着变化,所以在ESM中模块导出的是引用,具体实现可参考es-modules-a-cartoon-deep-dive。

CommonJS

// module.js
let a = 1;
const changeA = function() {a = 10;}
exports.a = a;
exports.changeA = changeA;

// entry.js
const module = require('./module.js');
module.changeA()
console.log(a) // 1

变量在元模块中变成10之后导入模块entry中并没有跟着变化,所以在ESM中模块导出的是值。

补充

可以将JS中的变量简单理解为一个盒子,这个盒子中可以存放数字,字符串等。

const a = 1;
const b = a;

上例中声明了一个变量a对应一个盒子,这个盒子里面放的是数字1,然后又声明了一个盒子b,这个b中放的是从盒子a中拿出来的值1。所以当盒子a中的值从1变成2的时候b盒子中的1并不会跟着变化。
JS的变量对应的盒子中不止能放值,还能放一个盒子。

const a = {value: 1};
const b = a;

上例中声明了一个a盒子,里面放了一个盒子{value: 1},然后又声明了一个盒子b,里面放的也是盒子{value: 1}。这时当盒子{value: 1}value值从1变成2ab盒子都能取到最新值。
所以ESM导出的是这个盒子,而CommonJS导出的是值。具体实现可参考es-modules-a-cartoon-deep-dive。

4. ESM执行在严格模式下而CommonJS未自动开启严格模式

在ESM下从入口开始所有脚本都默认按照严格模式解析,其影响包括但不限于:

  1. 变量必须声明后再使用
  2. 函数的参数不能有同名属性,否则报错
  3. 不能使用with语句
  4. 不能对只读属性赋值,否则报错
  5. 不能使用前缀 0 表示八进制数,否则报错
  6. 不能删除不可删除的属性,否则报错
  7. 不能删除变量delete prop,会报错,只能删除属性delete global[prop]
  8. eval不会在它的外层作用域引入变量
  9. eval和arguments不能被重新赋值
  10. arguments不会自动反映函数参数的变化
  11. 不能使用arguments.callee
  12. 不能使用arguments.caller
  13. 禁止this指向全局对象
  14. 不能使用fn.caller和fn.arguments获取函数调用的堆栈
  15. 增加了保留字(比如protected、static和interface)

以上限制信息来自于Module 的语法
对于JS模块文件的识别是通过<script type="module" src="https://example.com/main.js" />入口文件对应标签上的属性type="module"识别的,被改文件引用的所有文件都会被当做模块文件解析。

而在CommonJS中因为没有script标签作为入口明确识别模块文件,所以时间变的些许复杂,查阅相关资料显示可以通过.mjs后缀名来让Node明白这是一个ESM文件,可以启用严格模式。

参考

  1. es-modules-a-cartoon-deep-dive
  2. Module 的语法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1533492.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI预测福彩3D第15弹【2024年3月20日预测--第3套算法重新开始计算第4次测试】

今天咱们继续对第3套算法进行第4次测试&#xff0c;第3套算法加入了012路的权重。废话不多说了&#xff0c;直接上结果吧~ 最终&#xff0c;经过研判分析&#xff0c;2024年3月21日福彩3D的七码预测结果如下&#xff1a; 百位&#xff1a;4 5 7 1 0 6 2 十位&#xff1a;3 1 5 …

第十节HarmonyOS 常用容器组件4-Grid与GridItem

1、描述 网格容器&#xff0c;由行和列分割的单元格所组成&#xff0c;通过指定“项目”所在的单元格做出各种各样的布局。 子组件 包含GridItem子组件。 3、接口 Grid(scroller?: Scroller) 4、参数 参数名 参数类型 必填 描述 scroller Scroller 否 可滚动组件…

安科瑞智能断路器产品介绍【可监可控 远程操控 短路保护】

开发背景 过去几年智慧用电的产品应用中&#xff0c;大多数只安装于进线测。主要存在以下几个问题&#xff1a;难定位&#xff0c;不知道具体哪个回路出线问题&#xff0c;排查困难&#xff1b;出线过载或线缆温度过高无法知晓&#xff1b;即使是出线回路安装了的场景&#xf…

uniapp+uview 学习笔记(二)—— H5开发

文章目录 前言一、开发步骤1.创建项目2.安装组件库并导入使用3.封装请求4.国际化5.打包 总结 前言 本文主要介绍使用uniapp框架和uview组件库进行H5开发&#xff0c;需要用到的开发工具为HBuilder X。 一、开发步骤 1.创建项目 打开HBuilder X&#xff0c;在顶部栏目选择 新…

英国教育部学生信息中心

你是否曾因学历无法得到国内雇主的认可而感到困扰?别担心,英国教育部学校信息中心为你解忧!作为英国政府官方认可的学历认证机构,其权威性和可靠性广受认可,为留学生求职提供了强大的支持。 一、打破求 职困境:学历真实性认证的重要性 在求职过程中,学历的真实性和有效性是雇…

电脑照片分辨率怎么调?这款dpi修改工具好用

许多考试平台在上传证件照片的时候&#xff0c;大多都会对图片分辨率有具体要求&#xff0c;但是如果遇上手上的图片分辨率达不到要求&#xff0c;那么怎么改图片分辨率呢&#xff1f;可以利用专业的dpi修改工具来处理&#xff0c;比如今天分享的就是一个在线修改图片分辨率的方…

积鼎CFD发动机燃烧仿真,实现航空航天发动机内部燃烧过程的流体仿真

航空航天发动机中的燃烧现象是一种复杂的物理化学过程&#xff0c;包括流动、雾化、相变、传热传质、点火熄火、化学反应、污染物排放、热声振荡和冷却等多个过程&#xff0c;加上燃烧的非定常性和高湍流度&#xff0c;使得准确模拟燃烧过程变得异常困难。在传统CFD模拟需要考虑…

javaSwing推箱子游戏

一、简介 策略性游戏可以锻炼人的思维能力还能缓解人的压力&#xff0c;使人们暂时忘却生活当中的烦恼&#xff0c;增强人们的逻辑思维能力&#xff0c;游戏的艺术美也吸引着越来越多的玩家和厂商&#xff0c;寓教于乐&#xff0c;在放松人们心情的同时还可以活跃双手。在人类…

扩展学习|数字经济与公共管理的相关论文(管理世界)

一是如何建立与数字经济时代相适应的政府监管体制机制&#xff1f; 问题一和二来源&#xff1a;[1]王岭.数字经济时代中国政府监管转型研究[J].管理世界,2024,40(03):110-126204127.DOI:10.19744/j.cnki.11-1235/f.2024.0027. &#xff08;1&#xff09;数字经济时代政府监管转…

ByteTrack多目标跟踪——YOLOX详解

文章目录 1 before train1.1 dataset1.2 model 2 train2.1 Backbone2.2 PAFPN2.3 Head2.3.1 Decoupled Head2.3.2 anchor-free2.3.3 标签分配① 初步筛选② simOTA 2.3.4 Loss计算 项目地址&#xff1a; ByteTrack ByteTrack使用的检测器是YOLOX&#xff0c;是一个目前非常流行…

在 NVIDIA DGX Cloud 上使用 H100 GPU 轻松训练模型

近期&#xff0c;我们正式宣布推出 DGX 云端训练 (Train on DGX Cloud) 服务&#xff0c;这是 Hugging Face Hub 上针对企业 Hub 组织的全新服务。 通过在 DGX 云端训练&#xff0c;你可以轻松借助 NVIDIA DGX Cloud 的高速计算基础设施来使用开放的模型。这项服务旨在让企业 H…

vue2 项目运行 浏览器自动打开 vue项目启动如何自动打开浏览器 vue2取消浏览器自动打开浏览器,vue2关闭自动打开浏览器

1. 找到package.json 2. 找到scripts 在后面添加 --open即可&#xff1a; 3. 运行npm run serve 运行之后&#xff0c;就可以自动打开默认浏览器 4. 同理&#xff0c;不想自动打开 &#xff0c;将 --open 删除即可&#xff01;

【机器学习】基于布谷鸟搜索算法优化的BP神经网络分类预测(CS-BP)

目录 1.原理与思路2.设计与实现3.结果预测4.代码获取 1.原理与思路 【智能算法应用】智能算法优化BP神经网络思路【智能算法】布谷鸟搜索算法&#xff08;CS)原理及实现 2.设计与实现 数据集&#xff1a; 数据集样本总数2000 多输入多输出&#xff1a;样本特征24&#xff0…

选择器加练习

一、常用的选择器 1.元素选择器 语法 : 标签名{} 作用 : 选中对应标签中的内容 例:p{} , div{} , span{} , ol{} , ul{} ...... 2.类选择器(class选择器) 语法 : .class属性值{} 作用 : 选中对应class属性值的元素 注意:class里面的属性值不能以数字开头,如果以符号开头,…

鸿蒙Harmony应用开发—ArkTS-属性动画

组件的某些通用属性变化时&#xff0c;可以通过属性动画实现渐变过渡效果&#xff0c;提升用户体验。支持的属性包括width、height、backgroundColor、opacity、scale、rotate、translate等。布局类改变宽高的动画&#xff0c;内容都是直接到终点状态&#xff0c;例如文字、can…

C++之模版详解

一.array与vector对比 由图发现&#xff0c;使用array数组是必须提前开好空间&#xff0c;而vector是顺序表&#xff0c;可以实现动态开辟空间 array也支持迭代器&#xff0c;如下&#xff1a; int main() {array<int, 10> arr{ 1,2,3,4,5,6,7,8,9,10 };auto it arr.be…

蓝牙HFP协议推荐的语音丢包补偿算法浮点实现的定点化

最近在做蓝牙的宽带语音通话。相对于蓝牙窄带语音&#xff0c;主要变化是把采样率从8k变到16k&#xff0c;以及编解码器从CVSD变成mSBC&#xff08;modified SBC&#xff0c;改进的SBC&#xff09;等。蓝牙语音通话相关的HFP&#xff08;Hand Free Profile&#xff09;强烈建议…

第1关:创建数据库

任务描述 创建一个名为mydata的数据库。 相关知识 MySQL创建数据库的语法如下&#xff1a; 其中&#xff0c;database_name是要创建的数据库的名称。 开始你的任务吧&#xff0c;祝你成功&#xff01; #请在此处添加实现代码 ########## Begin ########## CREATE DATABASE …

如何有效防止员工摸鱼

在现代企业中&#xff0c;员工的工作效率直接影响到公司的运营和发展。然而&#xff0c;有时员工在上班时间会出现摸鱼现象&#xff0c;这不仅浪费了工作时间&#xff0c;还影响了团队的整体氛围和工作效率。 为了有效解决这一问题&#xff0c;本文将探讨一系列具体措施&#…

代码随想录day27(1)二叉树:二叉树的最近公共祖先(leetcode236)

题目要求&#xff1a;给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 思路&#xff1a;首先遍历顺序应为后序&#xff0c;因为判断两个节点的最近公共祖先实际上要自底向上&#xff0c;可以通过回溯来实现。实际上包含两种情况&#xff1a;第一种是节点p本身有一个子…