ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

JavaScript 模块化系统 - JavaScript学习系列文章

JavaScript 模块化系统 - JavaScript学习系列文章 一、为什么需要模块化想象一下你正在写一个大型项目, 所有代码都堆在一个文件里:// 可怕的全局变量地狱var utils {...};var api {...};var componentA {...};var componentB {...};// 20000行之后...functiondoSomething() {//谁知道这个函数会不会覆盖前面的定义?}这种写法有几个致命问题:命名冲突:变量和函数都在全局作用域容易覆盖依赖混乱:不知道代码执行前需要加载哪些依赖难以维护:代码组织像意大利面条牵一发而动全身模块化就是为了解决这些问题而生的! 它让我们可以:将代码拆分成独立的小文件(模块)明确声明依赖关系避免污染全局命名空间方便代码复用和维护二、CommonJSCommonJS 是 Node.js 采用的模块系统, 语法非常简单:// math.jsfunctionadd(a, b) {return a b;}functionsubtract(a, b) {return a - b;}//导出模块module.exports {add,subtract};//或者也可以这样导出exports.add add;exports.subtract subtract;使用的时候如下所示:// app.jsconst math require(./math.js);console.log(math.add(2,3));// 5console.log(math.subtract(5,2));// 3它有什么特点呢?同步加载:模块在 require 时同步加载并执行.缓存机制:模块首次加载后会被缓存, 后续 require 直接返回缓存.值拷贝:导出的是值的拷贝(对于原始类型), 修改不会影响原模块.三、ES ModulesES Modules(简称 ESM)是 ECMAScript 2015(ES6)引入的官方模块系统, 现在已经被现代浏览器和 Node.js 支持.基本语法:// math.jsexportfunctionadd(a, b) {return a b;}exportfunctionsubtract(a, b) {return a - b;}// 或者默认导出exportdefault {add,subtract};导入模块:// 命名导入import { add, subtract }from./math.js;// 默认导入import mathfrom./math.js;// 混合导入import math, { add }from./math.js;// 整体导入import *as mathfrom./math.js;与CommonJS的区别:静态分析:ESM 的 import/export 必须在顶层作用域, 可以被静态分析动态绑定:ESM 导出的是值的引用(活的绑定), 修改会影响所有导入异步加载:ESM 在浏览器中是异步加载的// counter.jsexportlet count 0;exportfunctionincrement() {count;}// app.jsimport { count, increment }from./counter.js;console.log(count);// 0increment();console.log(count);//1(ESM是动态绑定)在浏览器里如何加载模块呢?!-- 传统脚本 --scriptsrcapp.js/script!-- 模块脚本 --scripttypemodulesrcapp.js/script关键区别:模块默认defer, 在文档解析完成后执行模块有独立作用域, 不会污染全局模块需要 CORS 配置, 不能使用 file:// 协议模块会自动应用严格模式四、按需加载静态导入(import ... from ...)必须在模块顶层, 但有时候我们需要按需加载:// 普通导入import(./math.js).then(math {console.log(math.add(2,3));});// 配合 async/awaitasyncfunctioncalculate() {const math awaitimport(./math.js);console.log(math.add(2,3));}条件加载:if (user.isAdmin) {import(./admin.js).then(...);}预加载:link relmodulepreload hrefcritical-module.js组合使用:Promise.all([import(./moduleA.js),import(./moduleB.js)]).then(([moduleA, moduleB]) {// 两个模块都加载完成});
返回列表