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

【前端知识】JS模块规范

JS模块规范

    • 概述
      • CommonJS 规范 代码示例
      • AMD 规范 代码示例
      • ES6 Module 规范 代码示例
      • IIFE 规范 代码示例
      • 全局变量 代码示例
    • CommonJS 模块和 ES6 模块有什么区别?
      • 1. 语法和声明方式
      • 2. 动态和静态导入
      • 3. 循环依赖
      • 4. 默认导出和命名导出
      • 5. 文件扩展名
      • 6. 环境和应用
      • 7. 工具和构建工具
    • 动态导入在 ES6 模块中怎么用?
      • 基本用法
      • 示例
      • 在函数或条件语句中动态导入
      • 注意事项
    • 动态导入和静态导入有什么区别?
      • 静态导入(Static Imports)
      • 动态导入(Dynamic Imports)
      • 总结

概述

JavaScript 模块化规范的发展历程中,出现了多种不同的规范,每种规范都有其特定的使用场景和优缺点。以下是一些主要的模块化规范及其特点:

  1. CommonJS

    • 主要用于服务器端,如 Node.js 环境。
    • 采用同步加载模块的方式,适用于服务器端文件系统的操作。
    • 通过 module.exportsrequire 实现模块的导出和引入。
  2. AMD (Asynchronous Module Definition)

    • 专为浏览器端设计,支持异步加载模块。
    • 通过 define 函数定义模块,并通过 require 加载模块。
    • RequireJS 是 AMD 规范的一个实现。
  3. ES6 Module

    • 现代 JavaScript 官方模块化标准,提供了 importexport 语法。
    • 支持静态分析和动态导入。
    • 原生支持异步加载,使用 import() 函数。
  4. IIFE (Immediately Invoked Function Expression)

    • 早期的模块化方式,通过立即执行的函数包装代码块,避免全局变量污染。
  5. 全局变量

    • 在 JavaScript 发展的早期,模块之间的通信依赖于全局变量。

以下是每种规范的代码示例:

CommonJS 规范 代码示例

// 文件 1
var username = 'Alice';
function greetUser() {console.log('Hello, ' + username + '!');
}
// 文件 2
var username = 'Bob';
function displayUsername() {console.log('Current user: ' + username);
}

如果这两个文件都在同一个页面中执行,它们共享同一个全局命名空间,可能会造成 username 被覆盖。

AMD 规范 代码示例

// 定义模块
define(['jquery', 'underscore'], function($, _) {
return {
name: 'Module A',
sayHello: function() {
console.log('Hello from Module A!');}};
});
// 加载模块
require(['./components/ModuleA'], function(ModuleA) {
const element = document.createElement('div');
document.body.appendChild(element);
new ModuleA(element);});

在这个示例中,ModuleA 通过 jqueryunderscore 两个依赖模块定义了它的功能,然后通过返回的对象导出了 name 属性和 sayHello 方法。

ES6 Module 规范 代码示例

// math.js
export function add(a, b) {return a + b;
}
export function subtract(a, b) {return a - b;
}
// app.js
import { add, subtract } from './math';
console.log(add(5, 3)); // 输出 8
console.log(subtract(5, 3)); // 输出 2

ES Module 是 ECMAScript 6 引入的官方模块化方案,具有静态导入和动态导入的能力。

IIFE 规范 代码示例

(function () {// 初始化代码let firstVariable;let secondVariable;
})();
// firstVariable 和 secondVariable 变量在函数执行后会被丢弃

IIFE 是一种设计模式,也被称为 自执行匿名函数,主要包含两部分:一个具有词法作用域的匿名函数,并且用 圆括号运算符 () 运算符闭合起来。

全局变量 代码示例

// 文件 1
var globalVar = 'I am global';
function globalFunction() {console.log(globalVar);
}
// 文件 2
function useGlobal() {console.log(globalVar);
}

在这种模式下,所有变量和函数都暴露在全局作用域中,容易造成命名冲突和全局污染。

CommonJS 模块和 ES6 模块有什么区别?

CommonJS 和 ES6 模块是 JavaScript 中两种主要的模块化规范,它们在设计理念和实现方式上有一些关键的区别:

1. 语法和声明方式

  • CommonJS

    • 使用 require 来导入模块。
    • 使用 module.exportsexports 来导出模块。
    • 同步加载模块,适用于服务器端,因为文件系统操作是同步的。
    // CommonJS 模块导出
    module.exports = { myFunction };// CommonJS 模块导入
    const myModule = require('./myModule');
    
  • ES6 模块

    • 使用 import 来导入模块。
    • 使用 export 来导出模块。
    • 支持静态分析和动态导入,更适合现代前端工程,支持异步加载。
    // ES6 模块导出
    export function myFunction() {// ...
    }// ES6 模块导入
    import { myFunction } from './myModule.js';
    

2. 动态和静态导入

  • CommonJS

    • 模块的导入是同步的,不支持静态分析,不利于代码分割和懒加载。
  • ES6 模块

    • 支持静态导入,可以在编译时确定依赖关系,有利于代码分割和懒加载。
    • 也支持动态导入,通过 import() 函数实现,返回一个 Promise。

3. 循环依赖

  • CommonJS

    • 支持循环依赖,因为模块加载是同步的,可以在模块加载过程中解决依赖。
  • ES6 模块

    • 支持循环依赖,但由于是静态导入,需要明确依赖关系,否则可能导致运行时错误。

4. 默认导出和命名导出

  • CommonJS

    • 没有默认导出的概念,所有导出都是命名的。
    • exports 对象可以添加多个属性。
  • ES6 模块

    • 支持默认导出,每个模块可以有一个默认导出。
    • 支持命名导出,可以导出多个值。

5. 文件扩展名

  • CommonJS

    • 通常不需要指定文件扩展名,因为 Node.js 会自动解析。
  • ES6 模块

    • 在浏览器中使用 ES6 模块时,通常需要指定文件扩展名(如 .js.mjs)。

6. 环境和应用

  • CommonJS

    • 主要应用于 Node.js 环境。
    • 在浏览器中通过构建工具(如 Webpack)支持。
  • ES6 模块

    • 是现代浏览器原生支持的模块化规范。
    • 在 Node.js 中通过 .mjs 扩展名或配置支持。

7. 工具和构建工具

  • CommonJS

    • 在构建工具中,如 Webpack,CommonJS 模块可以被高效地打包。
  • ES6 模块

    • 在现代构建工具中,ES6 模块可以直接被利用,无需打包,支持树摇(Tree-shaking)。

总的来说,ES6 模块提供了更现代、更灵活的模块化方案,特别是在浏览器环境中,而 CommonJS 模块则在 Node.js 环境中更为常见。随着 ES6 模块的普及,它逐渐成为前端开发的主流选择。

动态导入在 ES6 模块中怎么用?

在 ES6 模块中,动态导入是通过 import() 函数实现的,这个函数返回一个 Promise 对象,它允许你将模块的导入推迟到需要的时候。动态导入对于实现代码分割(code splitting)、懒加载(lazy loading)以及动态依赖管理等场景非常有用。

基本用法

动态导入的基本语法如下:

import(modulePath).then((module) => {// 使用 module 中的导出}).catch((error) => {// 处理错误});

这里的 modulePath 是模块的路径,可以是相对路径或绝对路径。.then() 方法在模块加载成功时被调用,并传递一个包含模块导出的对象。.catch() 方法在加载失败时被调用,处理可能发生的错误。

示例

假设你有两个模块:moduleA.jsmoduleB.js,它们都定义了一些功能。

moduleA.js:

export function foo() {console.log('Function foo from Module A');
}

moduleB.js:

export function bar() {console.log('Function bar from Module B');
}

你可以在主模块中使用动态导入来导入这些模块,并在需要时调用它们的功能:

// 动态导入 moduleA 和 moduleB
import('./moduleA.js').then(({ foo }) => {foo(); // 输出: Function foo from Module A
}).catch((error) => {console.error('Failed to load module A', error);
});import('./moduleB.js').then(({ bar }) => {bar(); // 输出: Function bar from Module B
}).catch((error) => {console.error('Failed to load module B', error);
});

在函数或条件语句中动态导入

动态导入可以在函数内部或任何需要的地方使用,这使得它非常灵活:

function loadModule(moduleName) {import(`./${moduleName}.js`).then((module) => {module.default();}).catch((error) => {console.error(`Failed to load module ${moduleName}`, error);});
}// 根据条件动态加载模块
if (Math.random() > 0.5) {loadModule('moduleA');
} else {loadModule('moduleB');
}

注意事项

  • 动态导入的模块是异步加载的,这意味着它们不会阻塞主线程。
  • 动态导入的模块是单独打包的,这有助于实现代码分割,减少初始加载时间。
  • 动态导入需要服务器支持模块的 MIME 类型(通常是 text/javascript)。
  • 在使用动态导入时,确保处理错误和异常情况,因为网络问题或路径错误都可能导致加载失败。

动态导入是 ES6 模块提供的一个强大特性,它使得模块的按需加载成为可能,有助于提升应用的性能和用户体验。

动态导入和静态导入有什么区别?

动态导入(Dynamic Imports)和静态导入(Static Imports)是 ES6 模块规范中两种不同的模块加载方式,它们在语法、用途和加载行为上有所区别:

静态导入(Static Imports)

  1. 语法
    静态导入使用 import 关键字,在文件顶部以同步方式声明,它允许导入模块的特定导出。

    // 静态导入
    import { myFunction } from './myModule.js';
    
  2. 加载时机
    静态导入在 JavaScript 代码解析阶段就被处理,也就是说,模块会在代码执行前被加载。

  3. 用途
    静态导入适用于依赖关系明确且需要在应用启动时加载的模块。它有助于提升应用的加载性能,因为所有依赖的模块都可以被浏览器或 Node.js 提前知道并加载。

  4. 错误处理
    静态导入的错误需要在应用启动时处理,如果依赖的模块加载失败,会导致应用启动失败。

  5. 代码分割
    静态导入通常不支持代码分割,因为它需要在应用启动时加载所有依赖的模块。

动态导入(Dynamic Imports)

  1. 语法
    动态导入使用 import() 函数,它是一个返回 Promise 的函数,允许在代码执行过程中根据需要加载模块。

    // 动态导入
    import('./myModule.js').then((myModule) => {myModule.myFunction();
    }).catch((error) => {console.error('Module failed to load', error);
    });
    
  2. 加载时机
    动态导入的模块在代码执行到该模块的导入语句时才会被加载,支持异步加载。

  3. 用途
    动态导入适用于那些可能不需要立即加载的模块,或者需要根据特定条件动态加载的模块。它支持代码分割,有助于减少应用的初始加载时间。

  4. 错误处理
    动态导入的错误处理是异步的,可以在模块加载失败时进行更灵活的处理。

  5. 代码分割
    动态导入天然支持代码分割,因为它允许按需加载模块。

总结

  • 静态导入 适用于依赖明确且需要在应用启动时加载的模块,它支持树摇(Tree-shaking)和静态分析。
  • 动态导入 适用于按需加载或懒加载的模块,它支持代码分割和异步加载,有助于提升应用的初始加载性能。

在实际开发中,你可以根据应用的需求和模块的使用情况选择使用静态导入或动态导入,或者两者结合使用,以实现最佳的加载性能和用户体验。

相关文章:

【前端知识】JS模块规范

JS模块规范 概述CommonJS 规范 代码示例AMD 规范 代码示例ES6 Module 规范 代码示例IIFE 规范 代码示例全局变量 代码示例 CommonJS 模块和 ES6 模块有什么区别?1. 语法和声明方式2. 动态和静态导入3. 循环依赖4. 默认导出和命名导出5. 文件扩展名6. 环境和应用7. 工…...

vue3展示pag格式动态图

提示:如果是webpack环境的,参考:Pag格式在vue3中的简单使用方法_pag文件-CSDN博客 下面展示的是在vite环境下配置pag 1、安装libpag npm i libpag --save 2、安装rollup-plugin-copy npm i rollup-plugin-copy --save 3、封装pag组件 下…...

代码随想录算法训练营第三十九天|Day39 动态规划

198.打家劫舍 视频讲解:https://www.bilibili.com/video/BV1Te411N7SX https://programmercarl.com/0198.%E6%89%93%E5%AE%B6%E5%8A%AB%E8%88%8D.html 思路 #define max(a, b) ((a) > (b) ? (a) : (b)) int rob(int* nums, int numsSize) {if(numsSize 0){ret…...

qt QMovie详解

1、概述 QMovie 是 Qt 框架中用于处理动画文件的类。它支持多种动画格式,包括 GIF 和一些常见的视频格式(尽管对视频格式的支持依赖于底层平台)。QMovie 类主要用于在 QLabel 或 QGraphicsView 等控件中显示动画。通过加载动画文件&#xff…...

数据集整理

系列博客目录 文章目录 系列博客目录1.Visual Genome数据集2.COCO数据集3.Flickr30k数据集10.集合多个数据集的网站 1.Visual Genome数据集 官网链接:https://homes.cs.washington.edu/~ranjay/visualgenome/index.html Visual Genome数据集梳理 Visual Genome数据…...

认证授权基础概念详解

目录 认证 (Authentication) 和授权 (Authorization)的区别是什么? RBAC 模型了解吗? 什么是 Cookie ? Cookie 的作用是什么? 如何在项目中使用 Cookie 呢? 如何在 Spring Boot 中创建和读取 Cookie 创建 Cookie Cookie 到期日期 安全…...

美国地址生成器站点

推荐一:fakexy 官网地址:https://www.fakexy.com 推荐二:好维持官网地址: https://www.dizhishengcheng.com 官网除了支持生成美国地址信息外,还支持生成英国、加拿大、日朩、澳大利亚、德国、法国、意大利、西班牙、巴…...

微信4.0大版本升级跨平台支持界面全面改版

微信4.0公测版现已正式发布,作为微信的大版本升级,新版微信基于全新架构开发,跨平台支持Windows和MAC系统,界面也全面改版,聊天宝也第一时间适配微信4.0,为广大客户提供快捷回复支持 前言 微信4.0公测版现…...

不想贴秋膘?正确打开秋冬运动姿势

这个秋天想要轻装上阵,想健康入秋更要美美入冬怎么破?这期把正确打开秋冬姿势一次性告诉你哦~ 天气变凉,脂肪可要燃起来~想要无痛入秋,最重要的动起来!每天都抽出一点时间去运动一下,不光让身体燃起来&…...

【AIGC半月报】AIGC大模型启元:2024.11(上)

【AIGC半月报】AIGC大模型启元:2024.11(上) (1) Hunyuan-Large(腾讯开源大模型)(2) FLUX1.1 pro(文生图)(3) CogVideoX v1.5(智谱AI升级文生视频大模型) (1) Hunyuan-Lar…...

纯前端生成PDF(jsPDF)并下载保存或上传到OSS

前言 在工作中遇到了一个需求,就是把前端页面生成PDF并保存在本地,因为前端网站可能会展示各种表格,图表信息内容并带有比较鲜艳的色彩样式,如果让后端生产的PDF的话样式可能和前端页面展示的有所差异,所以这个任务就落…...

海外媒体发稿:旅游业媒体推广12个方面的注意事项-华媒舍

1.社交媒体推广过多 社交媒体是旅游业媒体推广的重要途径之一,过分依赖社交媒体将会成为一个常见误区。尽管社交媒体能够帮助旅行目的地提升知名度和曝光度,但如果过度投入精力与资源,可能忽视别的合理推广方式。 2.忽略SEO优化 搜索引擎提…...

分割回文串(DFS)

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串。返回 s 所有可能的分割方案。 示例 1: 输入:s "aab" 输出:[["a","a","b"],["aa","b&qu…...

Qt第三课 ----------容器类控件

作者前言 🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂 ​🎂 作者介绍: 🎂🎂 🎂 🎉🎉&#x1f389…...

打印菱形(C语言)

程序&#xff1a; #include <stdio.h> int main() { int i,j; for(i1;i<5;i){ for(j0;j<6-i;j){ printf(" ");} for(j0;j<i*2-1;j){ printf("*");} printf("\n");} …...

Oracle 19c 中启用 scott 用户

Oracle 19c 中启用 scott 用户 文章目录 Oracle 19c 中启用 scott 用户正常操作如果ORA-01918: 用户 SCOTT 不存在?/sqlplus/admin/scott.sql 没有 scott.sql 怎么处理 正常操作 连接到 Oracle 数据库&#xff1a; 使用 sqlplus 工具或者其他 SQL 客户端工具&#xff08;如 S…...

git commit 校验

commitlint官方链接 1. npm install --save-dev commitlint/config-conventional commitlint/cli 2. 配置commitlint.config.cjs(项目根目录中&#xff09; module.exports {extends: [commitlint/config-conventional],rules: {type-enum: [2,always,[Feat, Fix, Doc, Style,…...

【AtCoder】Beginner Contest 377-B.Avoid Rook Attack

Problem Statement 题目链接 There is a grid of 64 64 64 squares with 8 8 8 rows and 8 8 8 columns. Let ( i , j ) (i,j) (i,j) denote the square at the i i i-th row from the top ( 1 ≤ i ≤ 8 ) (1\leq i\leq8) (1≤i≤8) and j j j-th column from the lef…...

江协科技STM32学习- P38 软件SPI读写W25Q64

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…...

【Triton 教程】低内存 Dropout

Triton 是一种用于并行编程的语言和编译器。它旨在提供一个基于 Python 的编程环境&#xff0c;以高效编写自定义 DNN 计算内核&#xff0c;并能够在现代 GPU 硬件上以最大吞吐量运行。 更多 Triton 中文文档可访问 →https://triton.hyper.ai/ 在本教程中&#xff0c;您将编…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

uniapp 实现腾讯云IM群文件上传下载功能

UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中&#xff0c;群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS&#xff0c;在uniapp中实现&#xff1a; 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...

GraphQL 实战篇:Apollo Client 配置与缓存

GraphQL 实战篇&#xff1a;Apollo Client 配置与缓存 上一篇&#xff1a;GraphQL 入门篇&#xff1a;基础查询语法 依旧和上一篇的笔记一样&#xff0c;主实操&#xff0c;没啥过多的细节讲解&#xff0c;代码具体在&#xff1a; https://github.com/GoldenaArcher/graphql…...

车载诊断架构 --- ZEVonUDS(J1979-3)简介第一篇

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...

Django RBAC项目后端实战 - 03 DRF权限控制实现

项目背景 在上一篇文章中&#xff0c;我们完成了JWT认证系统的集成。本篇文章将实现基于Redis的RBAC权限控制系统&#xff0c;为系统提供细粒度的权限控制。 开发目标 实现基于Redis的权限缓存机制开发DRF权限控制类实现权限管理API配置权限白名单 前置配置 在开始开发权限…...

路由基础-路由表

本篇将会向读者介绍路由的基本概念。 前言 在一个典型的数据通信网络中&#xff0c;往往存在多个不同的IP网段&#xff0c;数据在不同的IP网段之间交互是需要借助三层设备的&#xff0c;这些设备具备路由能力&#xff0c;能够实现数据的跨网段转发。 路由是数据通信网络中最基…...