mirror of
https://github.com/ZiuChen/ZiuChen.github.io.git
synced 2025-08-18 15:39:35 +08:00
243 lines
141 KiB
HTML
243 lines
141 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en-US" dir="ltr">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>前端工程化 | ZiuChen</title>
|
||
<meta name="description" content="Unlimited Progress.">
|
||
<link rel="preload stylesheet" href="/assets/style.60c127af.css" as="style">
|
||
<link rel="modulepreload" href="/assets/app.f4e2d6d1.js">
|
||
<link rel="modulepreload" href="/assets/note_Front-end Engineering.md.3f047f08.lean.js">
|
||
|
||
<link rel="icon" href="/logo.png">
|
||
<script id="check-dark-light">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
|
||
</head>
|
||
<body>
|
||
<div id="app"><div class="Layout" data-v-3af881ed><!--[--><!--]--><!--[--><span tabindex="-1" data-v-00bddfc0></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-00bddfc0> Skip to content </a><!--]--><!----><header class="VPNav" data-v-3af881ed data-v-3796071a><div class="VPNavBar has-sidebar" data-v-3796071a data-v-fe00b0e5><div class="container" data-v-fe00b0e5><div class="title" data-v-fe00b0e5><div class="VPNavBarTitle has-sidebar" data-v-fe00b0e5 data-v-a7f91dcc><a class="title" href="/" data-v-a7f91dcc><!--[--><!--]--><!--[--><img class="VPImage logo" src="/logo.png" alt data-v-dca92699><!--]--><!--[-->ZiuChen<!--]--><!--[--><!--]--></a></div></div><div class="content" data-v-fe00b0e5><div class="curtain" data-v-fe00b0e5></div><div class="content-body" data-v-fe00b0e5><!--[--><!--]--><!----><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-fe00b0e5 data-v-a4f7fa5c><span id="main-nav-aria-label" class="visually-hidden" data-v-a4f7fa5c>Main Navigation</span><!--[--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/" data-v-a4f7fa5c data-v-1a106a35 data-v-8dd200cc><!--[-->首页<!--]--><!----></a><!--]--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-a4f7fa5c data-v-e76b733c><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-e76b733c><span class="text" data-v-e76b733c><!----> 我的项目 <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-e76b733c><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-e76b733c><div class="VPMenu" data-v-e76b733c data-v-faf23071><div class="items" data-v-faf23071><!--[--><!--[--><div class="VPMenuLink" data-v-faf23071 data-v-c0d2d58e><a class="VPLink link" href="/project/ClipboardManager/" data-v-c0d2d58e data-v-8dd200cc><!--[-->超级剪贴板<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-faf23071 data-v-c0d2d58e><a class="VPLink link" href="/project/SmartWordBreak/" data-v-c0d2d58e data-v-8dd200cc><!--[-->超级分词<!--]--><!----></a></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-a4f7fa5c data-v-e76b733c><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-e76b733c><span class="text" data-v-e76b733c><!----> 开源作品 <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-e76b733c><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-e76b733c><div class="VPMenu" data-v-e76b733c data-v-faf23071><div class="items" data-v-faf23071><!--[--><!--[--><div class="VPMenuLink" data-v-faf23071 data-v-c0d2d58e><a class="VPLink link" href="/works/opensource.html" data-v-c0d2d58e data-v-8dd200cc><!--[-->个人作品<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-faf23071 data-v-c0d2d58e><a class="VPLink link" href="/works/contribution.html" data-v-c0d2d58e data-v-8dd200cc><!--[-->社区贡献<!--]--><!----></a></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-a4f7fa5c data-v-e76b733c><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-e76b733c><span class="text" data-v-e76b733c><!----> 学习笔记 <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-e76b733c><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-e76b733c><div class="VPMenu" data-v-e76b733c data-v-faf23071><div class="items" data-v-faf23071><!--[--><!--[--><div class="VPMenuLink" data-v-faf23071 data-v-c0d2d58e><a class="VPLink link" href="/note/JavaScript.html" data-v-c0d2d58e data-v-8dd200cc><!--[-->JavaScript基础<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-faf23071 data-v-c0d2d58e><a class="VPLink link" href="/note/CSS.html" data-v-c0d2d58e data-v-8dd200cc><!--[-->CSS基础<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-faf23071 data-v-c0d2d58e><a class="VPLink link" href="/note/JavaScriptEnhanced.html" data-v-c0d2d58e data-v-8dd200cc><!--[-->JavaScript进阶<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-faf23071 data-v-c0d2d58e><a class="VPLink link active" href="/note/Front-end%20Engineering.html" data-v-c0d2d58e data-v-8dd200cc><!--[-->前端工程化<!--]--><!----></a></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/article/%E4%B8%80%E6%96%87%E8%AF%BB%E6%87%82%E4%BC%AA%E7%B1%BB%E4%B8%8E%E4%BC%AA%E5%85%83%E7%B4%A0.html" data-v-a4f7fa5c data-v-1a106a35 data-v-8dd200cc><!--[-->文章创作<!--]--><!----></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/self/" data-v-a4f7fa5c data-v-1a106a35 data-v-8dd200cc><!--[-->个人介绍<!--]--><!----></a><!--]--><!--]--></nav><!----><div class="VPNavBarAppearance appearance" data-v-fe00b0e5 data-v-2d4753dd><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" aria-label="toggle dark mode" aria-checked="false" data-v-2d4753dd data-v-867372a0 data-v-dc009bc3><span class="check" data-v-dc009bc3><span class="icon" data-v-dc009bc3><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-867372a0><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-867372a0><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></div><div class="VPSocialLinks VPNavBarSocialLinks social-links" data-v-fe00b0e5 data-v-f0005c73 data-v-819d8281><!--[--><a class="VPSocialLink" href="https://ziuchen.github.io/" target="_blank" rel="noopener" data-v-819d8281 data-v-ba84061a><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></a><a class="VPSocialLink" href="https://juejin.cn/user/1887205216238477" target="_blank" rel="noopener" data-v-819d8281 data-v-ba84061a><svg width="36" height="28" viewBox="0 0 36 28" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M17.5875 6.77268L21.8232 3.40505L17.5875 0.00748237L17.5837 0L13.3555 3.39757L17.5837 6.76894L17.5875 6.77268ZM17.5863 17.3955H17.59L28.5161 8.77432L25.5526 6.39453L17.59 12.6808H17.5863L17.5825 12.6845L9.61993 6.40201L6.66016 8.78181L17.5825 17.3992L17.5863 17.3955ZM17.5828 23.2891L17.5865 23.2854L32.2133 11.7456L35.1768 14.1254L28.5238 19.3752L17.5865 28L0.284376 14.3574L0 14.1291L2.95977 11.7531L17.5828 23.2891Z" fill="#1E80FF"/></svg></a><!--]--></div><div class="VPFlyout VPNavBarExtra extra" data-v-fe00b0e5 data-v-0467f0ad data-v-e76b733c><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-e76b733c><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="icon" data-v-e76b733c><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle><circle cx="5" cy="12" r="2"></circle></svg></button><div class="menu" data-v-e76b733c><div class="VPMenu" data-v-e76b733c data-v-faf23071><!----><!--[--><!--[--><!----><div class="group" data-v-0467f0ad><div class="item appearance" data-v-0467f0ad><p class="label" data-v-0467f0ad>Appearance</p><div class="appearance-action" data-v-0467f0ad><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" aria-label="toggle dark mode" aria-checked="false" data-v-0467f0ad data-v-867372a0 data-v-dc009bc3><span class="check" data-v-dc009bc3><span class="icon" data-v-dc009bc3><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-867372a0><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-867372a0><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></div></div></div><div class="group" data-v-0467f0ad><div class="item social-links" data-v-0467f0ad><div class="VPSocialLinks social-links-list" data-v-0467f0ad data-v-819d8281><!--[--><a class="VPSocialLink" href="https://ziuchen.github.io/" target="_blank" rel="noopener" data-v-819d8281 data-v-ba84061a><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></a><a class="VPSocialLink" href="https://juejin.cn/user/1887205216238477" target="_blank" rel="noopener" data-v-819d8281 data-v-ba84061a><svg width="36" height="28" viewBox="0 0 36 28" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M17.5875 6.77268L21.8232 3.40505L17.5875 0.00748237L17.5837 0L13.3555 3.39757L17.5837 6.76894L17.5875 6.77268ZM17.5863 17.3955H17.59L28.5161 8.77432L25.5526 6.39453L17.59 12.6808H17.5863L17.5825 12.6845L9.61993 6.40201L6.66016 8.78181L17.5825 17.3992L17.5863 17.3955ZM17.5828 23.2891L17.5865 23.2854L32.2133 11.7456L35.1768 14.1254L28.5238 19.3752L17.5865 28L0.284376 14.3574L0 14.1291L2.95977 11.7531L17.5828 23.2891Z" fill="#1E80FF"/></svg></a><!--]--></div></div></div><!--]--><!--]--></div></div></div><!--[--><!--]--><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-fe00b0e5 data-v-f1813d69><span class="container" data-v-f1813d69><span class="top" data-v-f1813d69></span><span class="middle" data-v-f1813d69></span><span class="bottom" data-v-f1813d69></span></span></button></div></div></div></div><!----></header><div class="VPLocalNav" data-v-3af881ed data-v-07d63927><button class="menu" aria-expanded="false" aria-controls="VPSidebarNav" data-v-07d63927><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="menu-icon" data-v-07d63927><path d="M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"></path><path d="M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"></path><path d="M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"></path><path d="M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"></path></svg><span class="menu-text" data-v-07d63927>Menu</span></button><a class="top-link" href="#" data-v-07d63927>Return to top</a></div><aside class="VPSidebar" data-v-3af881ed data-v-eec6a639><div class="curtain" data-v-eec6a639></div><nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1" data-v-eec6a639><span class="visually-hidden" id="sidebar-aria-label" data-v-eec6a639> Sidebar Navigation </span><!--[--><!--]--><!--[--><div class="group" data-v-eec6a639><section class="VPSidebarItem level-0 collapsible" data-v-eec6a639 data-v-66b47b62><div class="item" role="button" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link" data-v-66b47b62 data-v-8dd200cc><!--[--><h2 class="text" data-v-66b47b62>我的项目</h2><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-66b47b62><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-66b47b62><!--[--><div class="VPSidebarItem level-1 is-link" data-v-66b47b62 data-v-66b47b62><div class="item" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link link" href="/project/ClipboardManager/" data-v-66b47b62 data-v-8dd200cc><!--[--><p class="text" data-v-66b47b62>超级剪贴板</p><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><!----></div></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-66b47b62 data-v-66b47b62><div class="item" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link link" href="/project/SmartWordBreak/" data-v-66b47b62 data-v-8dd200cc><!--[--><p class="text" data-v-66b47b62>超级分词</p><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><!----></div></div><!----></div><!--]--></div></section></div><div class="group" data-v-eec6a639><section class="VPSidebarItem level-0 collapsible" data-v-eec6a639 data-v-66b47b62><div class="item" role="button" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link" data-v-66b47b62 data-v-8dd200cc><!--[--><h2 class="text" data-v-66b47b62>开源作品</h2><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-66b47b62><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-66b47b62><!--[--><div class="VPSidebarItem level-1 is-link" data-v-66b47b62 data-v-66b47b62><div class="item" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link link" href="/works/opensource.html" data-v-66b47b62 data-v-8dd200cc><!--[--><p class="text" data-v-66b47b62>个人作品</p><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><!----></div></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-66b47b62 data-v-66b47b62><div class="item" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link link" href="/works/contribution.html" data-v-66b47b62 data-v-8dd200cc><!--[--><p class="text" data-v-66b47b62>社区贡献</p><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><!----></div></div><!----></div><!--]--></div></section></div><div class="group" data-v-eec6a639><section class="VPSidebarItem level-0 collapsible" data-v-eec6a639 data-v-66b47b62><div class="item" role="button" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link" data-v-66b47b62 data-v-8dd200cc><!--[--><h2 class="text" data-v-66b47b62>文章创作</h2><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-66b47b62><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-66b47b62><!--[--><div class="VPSidebarItem level-1 is-link" data-v-66b47b62 data-v-66b47b62><div class="item" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link link" href="/article/%E3%80%902023%E3%80%91%E9%9D%92%E8%AE%AD%E8%90%A5%20-%20%E5%89%8D%E7%AB%AF%E7%BB%83%E4%B9%A0%E9%A2%98%E6%B1%87%E6%80%BB%E8%A7%A3%E6%9E%90.html" data-v-66b47b62 data-v-8dd200cc><!--[--><p class="text" data-v-66b47b62>【2023】青训营 - 前端练习题汇总解析</p><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><!----></div></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-66b47b62 data-v-66b47b62><div class="item" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link link" href="/article/%E4%B8%80%E6%96%87%E8%AF%BB%E6%87%82%E4%BA%8B%E4%BB%B6%E5%86%92%E6%B3%A1%E4%B8%8E%E4%BA%8B%E4%BB%B6%E6%8D%95%E8%8E%B7.html" data-v-66b47b62 data-v-8dd200cc><!--[--><p class="text" data-v-66b47b62>一文读懂事件冒泡与事件捕获</p><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><!----></div></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-66b47b62 data-v-66b47b62><div class="item" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link link" href="/article/%E4%B8%80%E6%96%87%E8%AF%BB%E6%87%82%E4%BC%AA%E7%B1%BB%E4%B8%8E%E4%BC%AA%E5%85%83%E7%B4%A0.html" data-v-66b47b62 data-v-8dd200cc><!--[--><p class="text" data-v-66b47b62>一文读懂伪类与伪元素</p><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><!----></div></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-66b47b62 data-v-66b47b62><div class="item" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link link" href="/article/%E4%B8%80%E6%96%87%E8%AF%BB%E6%87%82%E5%87%BD%E6%95%B0%E4%B8%ADthis%E6%8C%87%E5%90%91%E9%97%AE%E9%A2%98.html" data-v-66b47b62 data-v-8dd200cc><!--[--><p class="text" data-v-66b47b62>一文读懂函数中this指向问题</p><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><!----></div></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-66b47b62 data-v-66b47b62><div class="item" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link link" href="/article/%E4%BB%8E0%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AA%E5%B9%B4%E5%BA%A6%E6%8A%A5%E5%91%8A.html" data-v-66b47b62 data-v-8dd200cc><!--[--><p class="text" data-v-66b47b62>从0实现一个年度报告</p><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><!----></div></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-66b47b62 data-v-66b47b62><div class="item" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link link" href="/article/%E5%BD%BB%E5%BA%95%E6%90%9E%E6%87%82%E5%AF%B9%E8%B1%A1%E7%9A%84%E6%95%B0%E6%8D%AE%E5%B1%9E%E6%80%A7%E6%8F%8F%E8%BF%B0%E7%AC%A6%E3%80%81%E5%AD%98%E5%82%A8%E5%B1%9E%E6%80%A7%E6%8F%8F%E8%BF%B0%E7%AC%A6.html" data-v-66b47b62 data-v-8dd200cc><!--[--><p class="text" data-v-66b47b62>彻底搞懂对象的数据属性描述符、存储属性描述符</p><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><!----></div></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-66b47b62 data-v-66b47b62><div class="item" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link link" href="/article/%E6%B7%B1%E5%85%A5Vue3%E6%BA%90%E7%A0%81%EF%BC%8C%E7%9C%8B%E7%9C%8BVue.use%E5%90%8E%E7%A9%B6%E7%AB%9F%E5%8F%91%E7%94%9F%E4%BA%86%E4%BB%80%E4%B9%88%EF%BC%9F.html" data-v-66b47b62 data-v-8dd200cc><!--[--><p class="text" data-v-66b47b62>深入Vue3源码,看看Vue.use后究竟发生了什么?</p><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><!----></div></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-66b47b62 data-v-66b47b62><div class="item" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link link" href="/article/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3Proxy%E4%B8%8EReflect.html" data-v-66b47b62 data-v-8dd200cc><!--[--><p class="text" data-v-66b47b62>深入理解Proxy与Reflect</p><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><!----></div></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-66b47b62 data-v-66b47b62><div class="item" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link link" href="/article/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%E6%B5%8F%E8%A7%88%E5%99%A8%E7%BC%93%E5%AD%98%E6%9C%BA%E5%88%B6.html" data-v-66b47b62 data-v-8dd200cc><!--[--><p class="text" data-v-66b47b62>深入理解浏览器缓存机制</p><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><!----></div></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-66b47b62 data-v-66b47b62><div class="item" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link link" href="/article/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3%E6%B5%8F%E8%A7%88%E5%99%A8%E8%BF%90%E8%A1%8C%E5%8E%9F%E7%90%86.html" data-v-66b47b62 data-v-8dd200cc><!--[--><p class="text" data-v-66b47b62>深入理解浏览器运行原理</p><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><!----></div></div><!----></div><!--]--></div></section></div><div class="group" data-v-eec6a639><section class="VPSidebarItem level-0 collapsible has-active" data-v-eec6a639 data-v-66b47b62><div class="item" role="button" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link" data-v-66b47b62 data-v-8dd200cc><!--[--><h2 class="text" data-v-66b47b62>学习笔记</h2><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-66b47b62><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-66b47b62><!--[--><div class="VPSidebarItem level-1 is-link" data-v-66b47b62 data-v-66b47b62><div class="item" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link link" href="/note/JavaScript.html" data-v-66b47b62 data-v-8dd200cc><!--[--><p class="text" data-v-66b47b62>JavaScript基础</p><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><!----></div></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-66b47b62 data-v-66b47b62><div class="item" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link link" href="/note/CSS.html" data-v-66b47b62 data-v-8dd200cc><!--[--><p class="text" data-v-66b47b62>CSS基础</p><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><!----></div></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-66b47b62 data-v-66b47b62><div class="item" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link link" href="/note/JavaScriptEnhanced.html" data-v-66b47b62 data-v-8dd200cc><!--[--><p class="text" data-v-66b47b62>JavaScript进阶</p><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><!----></div></div><!----></div><div class="VPSidebarItem level-1 is-link is-active has-active" data-v-66b47b62 data-v-66b47b62><div class="item" data-v-66b47b62><div class="indicator" data-v-66b47b62></div><a class="VPLink link link" href="/note/Front-end%20Engineering.html" data-v-66b47b62 data-v-8dd200cc><!--[--><p class="text" data-v-66b47b62>前端工程化</p><!--]--><!----></a><div class="caret" role="button" data-v-66b47b62><!----></div></div><!----></div><!--]--></div></section></div><!--]--><!--[--><!--]--></nav></aside><div class="VPContent has-sidebar" id="VPContent" data-v-3af881ed data-v-e31feb0e><div class="VPDoc has-sidebar has-aside" data-v-e31feb0e data-v-30dabfe4><div class="container" data-v-30dabfe4><div class="aside" data-v-30dabfe4><div class="aside-curtain" data-v-30dabfe4></div><div class="aside-container" data-v-30dabfe4><div class="aside-content" data-v-30dabfe4><div class="VPDocAside" data-v-30dabfe4 data-v-7110f5c9><!--[--><!--]--><!--[--><!--]--><div class="VPDocAsideOutline" data-v-7110f5c9 data-v-9c6f1a55><div class="content" data-v-9c6f1a55><div class="outline-marker" data-v-9c6f1a55></div><div class="outline-title" data-v-9c6f1a55>On this page</div><nav aria-labelledby="doc-outline-aria-label" data-v-9c6f1a55><span class="visually-hidden" id="doc-outline-aria-label" data-v-9c6f1a55> Table of Contents for current page </span><ul class="root" data-v-9c6f1a55 data-v-02afc12d><!--[--><!--]--></ul></nav></div></div><!--[--><!--]--><div class="spacer" data-v-7110f5c9></div><!--[--><!--]--><!----><!--[--><!--]--><!--[--><!--]--></div></div></div></div><div class="content" data-v-30dabfe4><div class="content-container" data-v-30dabfe4><!--[--><!--]--><main class="main" data-v-30dabfe4><div style="position:relative;" class="vp-doc _note_Front-end%20Engineering" data-v-30dabfe4><div><h1 id="前端工程化" tabindex="-1">前端工程化 <a class="header-anchor" href="#前端工程化" aria-hidden="true">#</a></h1><h2 id="node-js" tabindex="-1">Node.js <a class="header-anchor" href="#node-js" aria-hidden="true">#</a></h2><ul><li>什么是Node.JS Node的应用场景</li><li>JS代码执行</li><li>Node的输入和输出</li><li>Node的全局对象</li></ul><h3 id="什么是node-js" tabindex="-1">什么是Node.js <a class="header-anchor" href="#什么是node-js" aria-hidden="true">#</a></h3><p>Node.js是一个基于<strong>V8 JavaScript引擎</strong>的<strong>JavaScript运行时环境</strong></p><ul><li>V8可以嵌入到任何C++应用程序中,无论是Chrome还是Node.js,事实上都嵌入了V8引擎来执行JavaScript代码</li><li>在Chrome浏览器中,还需要解析、渲染HTML、CSS等相关渲染引擎,另外还需要支持浏览器操作的API、浏览器自己的事件循环</li><li>在Node.js中我们也需要进行一些额外操作:文件系统读写、网络IO、加密、压缩解压文件等</li></ul><p>可以简单总结出Node.js和浏览器的区别</p><ul><li><p>Chrome浏览器</p><ul><li><p>Blink负责解析HTML文档,遇到JavaScript标签时将内容交给V8引擎</p></li><li><blockquote><p>Blink 是 Google Chrome 浏览器的渲染引擎,V8 是 Blink 内置的 JavaScript 引擎</p></blockquote><ul><li>预分析:检查语法错误但不生成AST树</li><li>生成AST:语法分析、词法分析后,生成抽象语法树(AST) <ul><li>AST 为每一行代码定义键值对。初始类型标识符定义 AST 属于一个程序,然后所有代码行将定义在主体内部,主体是一个对象数组。</li></ul></li><li>生成字节码:基线编译器(Ignition)将 AST 转换为字节码</li><li>生成机器代码:优化编译器 (Turbofan) 将字节码转换为优化的机器代码。另外,在逐行执行字节码的过程中,<strong>如果一段代码经常被执行,V8会直接将这段代码转换并保存为机器码</strong>,下次执行不需要经过字节码,优化了执行速度</li></ul></li></ul></li><li><p>Node.js</p><ul><li>只处理JavaScript代码 内部V8引擎负责JS代码的执行</li><li>JavaScript代码 -> V8 -> Node.js Bindings -> LibUV</li><li>LibUV是使用<strong>C语言编写的库</strong>,提供了<strong>事件循环、文件系统读写、网络IO、线程池</strong>等等内容</li></ul></li></ul><p></p><h3 id="node-js的应用场景" tabindex="-1">Node.js的应用场景 <a class="header-anchor" href="#node-js的应用场景" aria-hidden="true">#</a></h3><ul><li>前端开发的库都是以node包形式管理的</li><li>npm yarn pnpm成为前端开发使用最多的工具</li><li>使用Node.js作为Web服务器开发、中间件、代理服务器</li><li>借助Node.js完成前后端渲染的同构应用</li><li>编写脚本工具 构建项目 打包代码等</li><li>Electron桌面应用程序</li></ul><h3 id="node-js的参数传递" tabindex="-1">Node.js的参数传递 <a class="header-anchor" href="#node-js的参数传递" aria-hidden="true">#</a></h3><h4 id="process-argv" tabindex="-1"><code>process.argv</code> <a class="header-anchor" href="#process-argv" aria-hidden="true">#</a></h4><p><code>process.argv</code>返回一个数组</p><ul><li>在代码中通过<code>process.argv[2]</code>读取来自命令行的额外参数</li><li><code>process.argv[0]</code> <code>process.argv[1]</code>分别为<code>node.exe</code>的绝对路径和<code>目标文件</code>的绝对路径</li></ul><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// sum.js</span></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> x </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> process</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">argv[</span><span style="color:#F78C6C;">2</span><span style="color:#A6ACCD;">]</span></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> y </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> process</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">argv[</span><span style="color:#F78C6C;">3</span><span style="color:#A6ACCD;">]</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(x </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> y)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><div class="language-sh line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;"># 通过命令行运行node执行脚本 并传入参数</span></span>
|
||
<span class="line"><span style="color:#FFCB6B;">node</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">sum.js</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">5</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">10</span><span style="color:#A6ACCD;"> </span><span style="color:#676E95;font-style:italic;"># 15</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><h4 id="console" tabindex="-1">console <a class="header-anchor" href="#console" aria-hidden="true">#</a></h4><ul><li><code>console.log</code> 打印内容到stdout并加上换行符</li><li><code>console.clear</code> 清空当前stdout中的内容</li><li><code>console.trace</code> 打印字符串<code>Trace: </code>到stderr <ul><li>将堆栈跟踪打印到代码中的当前位置</li></ul></li></ul><h4 id="repl" tabindex="-1">REPL <a class="header-anchor" href="#repl" aria-hidden="true">#</a></h4><p>在浏览器的控制台选项卡中,我们可以通过输入JS代码与之交互,在Node.js中同样提供了类似的功能</p><ul><li>REPL是Read-Eval-Print Loop的简称,翻译为:读取-求值-输出循环</li><li>REPL是一个<strong>简单的、交互式的编程环境</strong></li><li>在命令行窗口中输入<code>node</code>即可进入</li></ul><h3 id="node中的全局对象" tabindex="-1">Node中的全局对象 <a class="header-anchor" href="#node中的全局对象" aria-hidden="true">#</a></h3><p>在浏览器中,我们可以在JS代码中访问全局对象<code>window</code>,代表当前标签窗口</p><p>在Node.js中的全局对象名为<code>global</code>,在控制台输出<code>global</code>对象:</p><div class="language-sh line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;">></span><span style="color:#A6ACCD;"> global</span></span>
|
||
<span class="line"><span style="color:#89DDFF;"><</span><span style="color:#A6ACCD;">ref </span><span style="color:#89DDFF;">*</span><span style="color:#F78C6C;">1</span><span style="color:#89DDFF;">></span><span style="color:#A6ACCD;"> Object </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">global</span><span style="color:#89DDFF;">]</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">global:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">Circular </span><span style="color:#89DDFF;">*</span><span style="color:#F78C6C;">1</span><span style="color:#89DDFF;">]</span><span style="color:#A6ACCD;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">clearInterval:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">Function: clearInterval</span><span style="color:#89DDFF;">]</span><span style="color:#A6ACCD;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">clearTimeout:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">Function: clearTimeout</span><span style="color:#89DDFF;">]</span><span style="color:#A6ACCD;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">setInterval:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">Function: setInterval</span><span style="color:#89DDFF;">]</span><span style="color:#A6ACCD;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">setTimeout:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">Function: setTimeout</span><span style="color:#89DDFF;">]</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">{</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">Symbol(nodejs.util.promisify.custom)</span><span style="color:#89DDFF;">]</span><span style="color:#82AAFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">Getter</span><span style="color:#89DDFF;">]</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">queueMicrotask:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">Function: queueMicrotask</span><span style="color:#89DDFF;">]</span><span style="color:#A6ACCD;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">performance:</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">Performance</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">{</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">nodeTiming:</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">PerformanceNodeTiming</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">{</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">name:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">node</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">entryType:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">node</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">startTime:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#C3E88D;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">duration:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">2245.9675999991596</span><span style="color:#C3E88D;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">nodeStart:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1.7120999991893768</span><span style="color:#C3E88D;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">v8Start:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">7.749699998646975</span><span style="color:#C3E88D;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">bootstrapComplete:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">56.47019999846816</span><span style="color:#C3E88D;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">environment:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">28.44789999909699</span><span style="color:#C3E88D;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">loopStart:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">97.62589999847114</span><span style="color:#C3E88D;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">loopExit:</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">-1,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">idleTime:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">2070.0206</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> },</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">timeOrigin:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1675854922619.539</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> },</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">clearImmediate:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">Function: clearImmediate</span><span style="color:#89DDFF;">]</span><span style="color:#A6ACCD;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#FFCB6B;">setImmediate:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">Function: setImmediate</span><span style="color:#89DDFF;">]</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">{</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">Symbol(nodejs.util.promisify.custom)</span><span style="color:#89DDFF;">]</span><span style="color:#82AAFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">[</span><span style="color:#A6ACCD;">Getter</span><span style="color:#89DDFF;">]</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> }</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br></div></div><h4 id="常见的全局对象" tabindex="-1">常见的全局对象 <a class="header-anchor" href="#常见的全局对象" aria-hidden="true">#</a></h4><ul><li><code>Buffer</code></li><li><code>clearImmediate</code></li><li><code>clearInterval</code></li><li><code>clearTimeout</code></li><li><code>console</code><ul><li>和控制台交互</li></ul></li><li><code>process</code><ul><li>提供了Node进程中相关的信息</li><li>Node的运行环境、系统环境变量、参数等</li></ul></li><li><code>queueMicrotask(callback)</code></li><li><code>setImmediate(callback, [, ...args])</code></li><li><code>setInterval(callback, delay[, ...args])</code></li><li><code>setTimeout(callback, delay[, ...args])</code></li><li><code>TextDecoder</code></li><li><code>TextEncoder</code></li><li><code>URL</code></li><li><code>URLSearchParams</code></li><li><code>WebAssembly</code></li></ul><h4 id="特殊的全局对象" tabindex="-1">特殊的全局对象 <a class="header-anchor" href="#特殊的全局对象" aria-hidden="true">#</a></h4><p><code>__dirname</code> <code>__filename</code> <code>exports</code> <code>module</code> <code>require()</code></p><ul><li>这些变量看起来是全局的,其实并不是(它们仅存在于模块范围内),只是每个模块中都有</li><li>它们在命令行交互中是不可使用的</li><li><code>__dirname</code> 当前模块的目录名</li><li><code>__filename</code> 当前模块的文件名</li><li><code>exports</code> <code>module</code> <code>require()</code>将在模块章节中讲解</li></ul><h4 id="global对象" tabindex="-1"><code>global</code>对象 <a class="header-anchor" href="#global对象" aria-hidden="true">#</a></h4><p><code>global</code>是一个全局对象</p><ul><li>在Node.js环境下,之前的 <code>process</code> <code>console</code> <code>setTimeout</code>等都有被放入到<code>global</code>中</li><li>而在浏览器中,这些全局API是被放到<code>window</code>对象上的</li></ul><p>这无异于增加了开发者的心智负担,所以在最新的ECMA标准中出现了<code>globalThis</code>,指向全局对象</p><ul><li>在浏览器中的<code>globalThis</code>指向<code>window</code>对象</li><li>在Node.js中的<code>globalThis</code>指向<code>global</code>对象</li></ul><p>两个全局对象的区别:在浏览器中通过<code>var</code>定义的变量会被放到<code>window</code>对象上,而Node.js不会</p><h2 id="模块化开发" tabindex="-1">模块化开发 <a class="header-anchor" href="#模块化开发" aria-hidden="true">#</a></h2><ul><li>认识模块化开发</li><li>CommonJS和Node</li><li>require函数解析</li><li>AMD和CMD(已经被时代淘汰 了解即可)</li><li>ESModule用法详解</li><li>ESModule运行原理</li></ul><h3 id="模块化的初衷" tabindex="-1">模块化的初衷 <a class="header-anchor" href="#模块化的初衷" aria-hidden="true">#</a></h3><ul><li>将大的程序拆分成一个个小的易于维护的代码</li><li>每个模块负责程序中的一部分逻辑,拥有<strong>自己的作用域</strong>、<strong>定义变量名时不会发生冲突</strong></li><li>模块可以暴露<strong>变量、函数、对象</strong>等导出</li><li>模块可以导入其他模块的<strong>变量、函数、对象</strong></li></ul><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// moduleA.js</span></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> moduleA </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> (</span><span style="color:#C792EA;">function</span><span style="color:#89DDFF;">(){</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">name</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">"</span><span style="color:#C3E88D;">Ziu</span><span style="color:#89DDFF;">"</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">age</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">18</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">run</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=></span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">name</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">+</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">age</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">+</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">is running.</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">name</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">age</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">run</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)()</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#676E95;font-style:italic;">// moduleB.js</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(moduleA</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">name) </span><span style="color:#676E95;font-style:italic;">// 在其他模块中调用</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><h3 id="commonjs" tabindex="-1">CommonJS <a class="header-anchor" href="#commonjs" aria-hidden="true">#</a></h3><p>CommonJS是一种<strong>规范</strong>,当初命名为ServerJS,旨在浏览器以外的地方使用,后为体现其广泛性,改名为CommonJS,简称CJS</p><p><strong>规范 是用来指导 实现的</strong></p><ul><li><code>Node</code> 是CommonJS在服务端的代表<strong>实现</strong></li><li><code>Browserify</code> 是CommonJS在浏览器中的一种<strong>实现</strong> (正在被淘汰)</li><li><code>WebPack</code> 打包工具具备支持CommonJS的支持和转换</li></ul><p>所以,Node.js对CommonJS进行了支持和实现,让JavaScript在Node上运行时可以实现模块化开发</p><ul><li>每个<code>.js</code>文件都是一个单独的模块</li><li>每个模块中都包含变量<code>exports</code> <code>module.exports</code> <code>require</code></li></ul><div class="vp-code-group"><div class="tabs"><input type="radio" name="group-XAAzA" id="tab-vbwwoiz" checked="checked"><label for="tab-vbwwoiz">env.js</label><input type="radio" name="group-XAAzA" id="tab-o8FxUD-"><label for="tab-o8FxUD-">utils.js</label><input type="radio" name="group-XAAzA" id="tab-UOvbrPc"><label for="tab-UOvbrPc">index.js</label></div><div class="blocks"><div class="language-js active line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// env.js</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">exports.</span><span style="color:#A6ACCD;">name </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Ziu</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">exports.</span><span style="color:#A6ACCD;">age </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">18</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// utils.js</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">module.exports</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">sum</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">x</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">y</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">x</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">+</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">y</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// index.js</span></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> utils </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">require</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">utils.js</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">utils</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">sum</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">1</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">2</span><span style="color:#A6ACCD;">) </span><span style="color:#676E95;font-style:italic;">// 3</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> sum </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">require</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">utils.js</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"><span style="color:#82AAFF;">sum</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">1</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">2</span><span style="color:#A6ACCD;">) </span><span style="color:#676E95;font-style:italic;">// 3</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;"> name</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> age </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">require</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">env.js</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(name</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> age) </span><span style="color:#676E95;font-style:italic;">// Ziu 18</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div></div></div><h4 id="exports的本质" tabindex="-1"><code>exports</code>的本质 <a class="header-anchor" href="#exports的本质" aria-hidden="true">#</a></h4><p><code>exports</code>和<code>require</code>在Node中的本质</p><ul><li><code>exports</code>是一个对象,我们可以在这个对象中添加很多属性,添加的属性则会被导出 <ul><li>在没有向该对象添加任何属性之前,它是一个空对象</li></ul></li><li>当通过<code>require</code>导入时:<code>const env = require('env.js')</code><ul><li><code>env</code>这个变量等于<code>env.js</code>中的<code>exports</code>对象</li><li>本质上是<code>env</code>是<code>exports</code>对象的引用赋值</li><li><code>{ id: '...', exports: { ... }, loaded: true, ... }</code></li></ul></li><li>后续即使再次执行<code>require</code>导入模块,模块中的代码也不会重新执行(<code>module.loaded</code>属性) <ul><li>当从模块中取值时,会从已经加载的<code>exports</code>对象缓存上取值</li></ul></li></ul><div class="vp-code-group"><div class="tabs"><input type="radio" name="group-PJ4fi" id="tab-HLt88Yi" checked="checked"><label for="tab-HLt88Yi">utils.js</label><input type="radio" name="group-PJ4fi" id="tab-S24bxlN"><label for="tab-S24bxlN">index.js</label></div><div class="blocks"><div class="language-js active line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// utils.js</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">exports.</span><span style="color:#A6ACCD;">a </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#676E95;font-style:italic;">// 1s后修改a值</span></span>
|
||
<span class="line"><span style="color:#82AAFF;">setTimeout</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">exports.</span><span style="color:#A6ACCD;">a</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">1</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">},</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1000</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#676E95;font-style:italic;">// 2s后检查a值</span></span>
|
||
<span class="line"><span style="color:#82AAFF;">setTimeout</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">exports.</span><span style="color:#A6ACCD;">a</span><span style="color:#F07178;">) </span><span style="color:#676E95;font-style:italic;">// 2</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">},</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">2000</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// index.js</span></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> utils </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">require</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">./utils</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(utils</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">a) </span><span style="color:#676E95;font-style:italic;">// 0</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#82AAFF;">setTimeout</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">utils</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">a</span><span style="color:#F07178;">) </span><span style="color:#676E95;font-style:italic;">// 1</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">utils</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">a</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">2</span><span style="color:#F07178;"> </span><span style="color:#676E95;font-style:italic;">// 反过来修改a值</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">},</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1500</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div></div></div><p>在上述代码中,<code>utils</code>对象中的属性<code>a</code>在一秒后被赋值为<code>1</code>,因此在index.js中输出<code>utils.a</code>得到了两次不同的结果</p><p>反过来,在index.js中修改导入的<code>utils.a</code>的值后,修改结果也会反映在<code>exports.a</code>上,输出的值为<code>2</code></p><p>实际开发中不要修改导入模块中的变量,改变原模块中变量的值并不规范</p><h4 id="module-exports" tabindex="-1"><code>module.exports</code> <a class="header-anchor" href="#module-exports" aria-hidden="true">#</a></h4><p>在Node.js中,真正常用的导出方式是<code>module.exports</code></p><ul><li><code>module.exports</code>本质上就是<code>exports</code>对象(同一个内存地址)</li><li>可以直接给<code>exports</code>对象赋值,将需要导出的内容统一导出</li><li>给<code>module.exports</code>重新赋值,即改变了<code>exports</code>对象的指向,<strong>后续的修改不再影响原模块中的变量</strong></li></ul><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> name </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Ziu</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> run </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(name </span><span style="color:#89DDFF;">+</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">is running.</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;">module.exports</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> name</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> run</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><h4 id="二者的区别" tabindex="-1">二者的区别 <a class="header-anchor" href="#二者的区别" aria-hidden="true">#</a></h4><p>既然如此,为什么还要存在<code>exports</code>这个概念呢?</p><ul><li>在CommonJS中是没有<code>module.exports</code>的概念的</li><li>为了实现模块的导出,Node.js使用的是<code>Module</code>类,每一个模块都是<code>Module</code>的实例,也就是<code>module</code></li><li>所以在Node.js中真正用于导出的并不是<code>exports</code>,而是<code>module.exports</code></li><li><code>module</code>对象中的<code>exports</code>属性是<code>exports</code>对象的一个引用 <ul><li><code>module.exports === exports === utils</code></li></ul></li></ul><p>如果<code>module.exports</code>不再引用<code>exports</code>对象了,修改<code>exports</code>对象也就没有意义了</p><div class="vp-code-group"><div class="tabs"><input type="radio" name="group-4gW9S" id="tab-ei4J1t3" checked="checked"><label for="tab-ei4J1t3">utils.js</label><input type="radio" name="group-4gW9S" id="tab-Kn4P6Ew"><label for="tab-Kn4P6Ew">index.js</label></div><div class="blocks"><div class="language-js active line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// utils.js</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">module.exports</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">name</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Ziu</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">exports.</span><span style="color:#A6ACCD;">age </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">18</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// index.js</span></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> utils </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">require</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">utils.js</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(utils</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">name) </span><span style="color:#676E95;font-style:italic;">// Ziu</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(utils</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">age) </span><span style="color:#676E95;font-style:italic;">// undefined</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div></div></div><p>当使用<code>module.exports = { ... }</code>后,模块中原有的<code>exports</code>不再被导入识别,导入的内容将变为<code>module.exports</code>指定的对象内容</p><h4 id="require的本质" tabindex="-1"><code>require</code>的本质 <a class="header-anchor" href="#require的本质" aria-hidden="true">#</a></h4><p><code>require</code>是一个函数,可以帮助我们导入一个文件(模块)中导出的对象</p><ul><li>为什么可以省略掉<code>.js</code>后缀,直接使用<code>require('./utils')</code></li><li>为什么可以省略掉<code>index.js</code>,直接使用<code>require('./tools')</code>导入<code>tools/index.js</code></li></ul><p>这涉及到<code>require</code>在匹配路径后的查找规则:</p><p>分为三种情况:<strong>内置模块、自定义路径、包名</strong></p><ul><li>导入Node.js内置的模块,如<code>const path = require('path')</code><ul><li>直接返回该内置模块 并停止后续的查找</li></ul></li><li>根据路径导入自定义的模块,如<code>const utils = require('./{filename}')</code><ul><li>按照路径寻找该模块<code>./</code> <code>../</code> <code>/</code></li><li>如果指定了后缀名,则按照后缀名查找</li><li>如果未指定后缀名,则: <ol><li>直接查找该文件</li><li>查找<code>{filename}.js</code>文件</li><li>查找<code>{filename}.json</code>文件</li><li>查找<code>{filename}.node</code>文件</li></ol></li><li>如果按照上述方式没找到文件,则<strong>将<code>{filename}</code>作为路径继续查找</strong></li><li>查找目录下的<code>index</code>文件 <code>{filename}/index</code><ol><li>查找<code>{filename}/index.js</code>文件</li><li>··· ···</li></ol></li><li>没找到:报错<code>Cannot find module 'xxx'</code></li></ul></li><li>包名,如<code>const lodash = require('lodash')</code><ul><li>到项目根目录的<code>node_modules</code>中查找</li><li><code>node_modules/{package_name}/index.js</code></li><li>当前项目目录的<code>node_modules</code>找不到则继续向上查找,直到查找到根目录的<code>node_modules</code></li></ul></li></ul><h4 id="模块的加载过程" tabindex="-1">模块的加载过程 <a class="header-anchor" href="#模块的加载过程" aria-hidden="true">#</a></h4><ul><li>模块在被第一次引入时,模块中的JS代码会被运行一次 <ul><li>代码执行顺序与<code>require</code>的位置相关</li></ul></li><li>模块如果被多次引入,会被缓存,最终只加载一次 <ul><li>这是因为每个模块对象<code>module</code>上都有一个属性<code>loaded</code></li><li><code>loaded === false</code>表示该模块尚未被加载</li><li>第二次被<code>require</code>引入时会检查该属性是否为<code>true</code></li></ul></li><li>如果有循环引用,加载顺序如何? <ul><li>数据结构:图结构(graph)遍历时有深度优先搜索(DFS)、广度优先搜索(BFS)两种算法</li><li>Node采用的是深度优先算法</li></ul></li></ul><h4 id="commonjs的缺点" tabindex="-1">CommonJS的缺点 <a class="header-anchor" href="#commonjs的缺点" aria-hidden="true">#</a></h4><ul><li>加载模块是同步加载的 <ul><li>只有等到对应的模块加载完毕,当前模块中的内容才能被执行</li><li>当然,在服务器中加载JS文件都是本地文件,加载速度非常快,不会受影响</li></ul></li><li>但是在浏览器中使用CommonJS <ul><li>需要先从服务器下载JS文件,后加载运行</li><li>阻塞JS执行 阻塞页面加载</li></ul></li><li>在WebPack中使用CommonJS <ul><li>CommonJS会被WebPack解析</li><li>将CommonJS代码转化为bundle 浏览器可以直接运行</li></ul></li></ul><h3 id="esmodule" tabindex="-1">ESModule <a class="header-anchor" href="#esmodule" aria-hidden="true">#</a></h3><ul><li>ES6 模块采用<strong>编译时加载</strong>,使得<strong>编译时就能确定模块的依赖关系</strong>,有助于<strong>静态优化</strong></li><li>CommonJS模块在运行时加载,且必须借助对象加载模块内容</li></ul><h4 id="export和import用法概览" tabindex="-1"><code>export</code>和<code>import</code>用法概览 <a class="header-anchor" href="#export和import用法概览" aria-hidden="true">#</a></h4><p>ESModule借助<code>export</code>和<code>import</code>导入导出内容,需要注意的是导入导出的并不是对象</p><p><code>export</code>定义的是当前模块导出的<strong>接口</strong>,<code>import</code>可以导入来自其他不同模块的<strong>接口</strong></p><ul><li><code>export default</code>可以设置默认导出对象</li><li><code>export { ... }</code>可以统一导出多个内容</li><li><code>export</code>和<code>import</code>都可以使用<code>as</code>关键字重命名导出/导入的接口</li><li><code>import * from 'xxx'</code> <code>export * from 'xxx'</code>批量导入/导出</li></ul><div class="vp-code-group"><div class="tabs"><input type="radio" name="group-NZabR" id="tab-4NY8W7B" checked="checked"><label for="tab-4NY8W7B">utils.js</label><input type="radio" name="group-NZabR" id="tab-rCd8TAV"><label for="tab-rCd8TAV">index.js</label></div><div class="blocks"><div class="language-js active line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// utils.js</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">sum</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">a</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">b</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">a</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">+</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">b</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">sub</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;font-style:italic;">a</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;font-style:italic;">b</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">a</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">-</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">b</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">log</span><span style="color:#89DDFF;">(...</span><span style="color:#A6ACCD;font-style:italic;">args</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">...</span><span style="color:#A6ACCD;">args</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">name</span><span style="color:#F07178;">: '</span><span style="color:#A6ACCD;">Ziu</span><span style="color:#F07178;">'</span><span style="color:#89DDFF;">,</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">age</span><span style="color:#F07178;">: 18</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> ENV_VARIABLE </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Hello, World!</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// index.js</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">sum</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">sub</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">name</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">age</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">ENV_VARIABLE</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">./utils</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> log </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">./utils.js</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#82AAFF;">sum</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">1</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">2</span><span style="color:#A6ACCD;">) </span><span style="color:#676E95;font-style:italic;">// 3</span></span>
|
||
<span class="line"><span style="color:#82AAFF;">sub</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">2</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">3</span><span style="color:#A6ACCD;">) </span><span style="color:#676E95;font-style:italic;">// -1</span></span>
|
||
<span class="line"><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(name</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> age</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> ENV_VARIABLE) </span><span style="color:#676E95;font-style:italic;">// 'Ziu' 18 'Hello, World!'</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div></div></div><p>需要注意的是,在浏览器中要使用ESModule,需要为<code><script></code>标签添加<code>module</code>标记:</p><p><code><script src="index.js" type="module"></script></code></p><ul><li>当浏览器解析到<code>type="module"</code>的JS代码后,会<strong>分析模块中导入的ESModule模块</strong></li><li>每导入一个ESModule模块,<strong>浏览器都会发起一个HTTP请求去加载它</strong></li><li>在本地运行时加载不同协议头的文件会遇到跨域问题,需要开启本地Web服务器</li></ul><p>另外,<strong><code>export</code>与<code>import</code>必须位于模块的顶层</strong>,如果位于作用域内会报错,因为这就<strong>无法对代码进行静态分析优化了</strong></p><h4 id="export详解" tabindex="-1"><code>export</code>详解 <a class="header-anchor" href="#export详解" aria-hidden="true">#</a></h4><p><code>export</code>有两种导出方式:</p><ul><li>命名导出 <code>export const name = 'Ziu'</code> <code>export { v1, v2 } export * from 'xxx'</code><ul><li>导出时需要指定名字</li><li>导入时也需要知道对应的名字</li></ul></li><li>默认导出 <code>export default AGE = 18</code><ul><li>在从其他位置导入时需要为此默认导出指定新的名字</li><li>给用户方便:不必阅读文档就可以加载模块</li></ul></li></ul><h4 id="值的动态绑定" tabindex="-1">值的动态绑定 <a class="header-anchor" href="#值的动态绑定" aria-hidden="true">#</a></h4><ul><li>ESModule模块通过<code>export</code>语句输出的接口,与其对应的值是<strong>动态绑定关系</strong>,即通<strong>过该接口,可以取到模块内部实时的值</strong></li><li>CommonJS模块输出的是值的缓存,不存在动态更新</li></ul><p>我们援引之前介绍CJS时的案例,<strong>将后缀名改为<code>mjs</code>即可在Node中运行ESModule模块代码</strong></p><p>初始获得的<code>a</code>值为0,经过1s后,在<code>utils.mjs</code>中修改了a的值,这时导入<code>utils.mjs</code>模块的其他模块可以获取到<code>a</code>最新的值</p><div class="vp-code-group"><div class="tabs"><input type="radio" name="group-BU1Qd" id="tab-NEKy_NE" checked="checked"><label for="tab-NEKy_NE">utils.mjs</label><input type="radio" name="group-BU1Qd" id="tab-Ed7Mi3g"><label for="tab-Ed7Mi3g">index.mjs</label></div><div class="blocks"><div class="language-js active line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// utils.mjs</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> a </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#676E95;font-style:italic;">// 1s后修改a值</span></span>
|
||
<span class="line"><span style="color:#82AAFF;">setTimeout</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">a</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">1</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">},</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1000</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// index.mjs</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">a</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">./utils.mjs</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(a) </span><span style="color:#676E95;font-style:italic;">// 0</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#82AAFF;">setTimeout</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">a</span><span style="color:#F07178;">) </span><span style="color:#676E95;font-style:italic;">// 1</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">},</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1500</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div></div></div><ul><li>需要注意的是,导入的其他模块的变量是不允许被修改的,因为<code>index.mjs</code>导入的本质是一个接口</li><li>如果从其他模块导入的是一个对象,也不推荐修改导入内容的任何值,最好将其当做完全只读</li></ul><p>拓展阅读:CommonJS与ESModule加载模块的异同</p><h4 id="import详解" tabindex="-1"><code>import</code>详解 <a class="header-anchor" href="#import详解" aria-hidden="true">#</a></h4><p>检查下述代码:</p><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#82AAFF;">foo</span><span style="color:#A6ACCD;">()</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">foo</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">foo</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><ul><li><code>import</code>命令具有提升效果,会提升到整个模块的顶部</li><li><code>import</code>的执行早于函数的调用,<code>import</code>命令是在编译阶段执行的,在代码运行之前</li><li>由于<code>import</code>是静态执行,所以不能使用表达式和变量(只有运行时才有值)</li></ul><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">lodash</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">lodash</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><ul><li>如果仅仅导入了一个模块,那么该模块的代码会被执行,但是没有任何变量被导入</li><li>如果同一模块被导入多次,那么导入操作只会被执行一次</li></ul><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">*</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">utils</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"><span style="color:#82AAFF;">add</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">1</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">2</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">*</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">utils</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><ul><li>可以通过<code>*</code>一次性导入模块中所有导出的变量、函数、类</li><li>也可以实现二者的复合操作:导入全部模块的同时导出全部模块</li></ul><h4 id="import-函数" tabindex="-1"><code>import()</code>函数 <a class="header-anchor" href="#import-函数" aria-hidden="true">#</a></h4><p>通过<code>import</code>命令导入的模块是静态的,会被提升到模块顶部,并不支持条件导入</p><p>ES2020引入了<code>import()</code>函数,可以通过<code>import()</code>函数实现条件导入,动态加载ESModule模块</p><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> main </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">querySelector</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">main</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#89DDFF;">import</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">`</span><span style="color:#C3E88D;">./section-modules/</span><span style="color:#89DDFF;">${</span><span style="color:#A6ACCD;">someVariable</span><span style="color:#89DDFF;">}</span><span style="color:#C3E88D;">.js</span><span style="color:#89DDFF;">`</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">then</span><span style="color:#A6ACCD;">(</span><span style="color:#A6ACCD;font-style:italic;">module</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">module.</span><span style="color:#82AAFF;">loadPageInto</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">main</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">catch</span><span style="color:#A6ACCD;">(</span><span style="color:#A6ACCD;font-style:italic;">err</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">main</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">textContent</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">err</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">message</span><span style="color:#89DDFF;">;</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><ul><li>返回值是一个Promise对象,可以通过<code>await</code>同步地操作它</li><li><code>import()</code>函数可以在模块外的JS脚本中使用,用于<strong>在运行时加载外部模块</strong>,类似于<code>require()</code></li><li>区别于<code>require()</code>,<code>import()</code>是异步加载模块</li></ul><p>通过<code>.then</code>函数处理导入的模块时,行为和<code>import</code>是相同的:</p><ul><li>如果有默认导出对象,则<code>.then</code>入参为默认导出对象</li><li>可以通过解构直接取到模块中导出的变量或函数:<code>.then(({ add, sub }) => { ... })</code></li></ul><p><strong>应用场景</strong></p><p>按需加载:按钮点击后才加载相关的JS文件</p><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">btn</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">addEventListener</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">click</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">import</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">./dialogBox.js</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">then</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;font-style:italic;">dialogBox</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=></span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">dialogBox</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">open</span><span style="color:#F07178;">()</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">catch</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;font-style:italic;">err</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=></span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">err</span><span style="color:#F07178;">))</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p>条件加载:根据主题色加载不同JS文件</p><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#A6ACCD;">(darkMode) </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">import</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">dark.js</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">then</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=></span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">...</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">else</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">import</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">light.js</span><span style="color:#89DDFF;">'</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">then</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">()</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=></span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">...</span><span style="color:#F07178;">)</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p>传入动态值</p><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> moduleName </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=></span><span style="color:#A6ACCD;"> [</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">Home</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">History</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">User</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">][</span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;">]</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">import</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">`</span><span style="color:#C3E88D;">./</span><span style="color:#89DDFF;">${</span><span style="color:#82AAFF;">moduleName</span><span style="color:#A6ACCD;">()</span><span style="color:#89DDFF;">}</span><span style="color:#C3E88D;">.js</span><span style="color:#89DDFF;">`</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><h4 id="import-meta" tabindex="-1"><code>i<wbr>mport.meta</code> <a class="header-anchor" href="#import-meta" aria-hidden="true">#</a></h4><p>ES2020引入了<code>i<wbr>mport.meta</code>,它仅能在模块内部使用,包含一些模块自身的信息,即模块元信息</p><ul><li><code>i<wbr>mport.meta.url</code> 返回当前模块的URL路径 <ul><li>浏览器加载ESModule都是通过HTTP发起请求 <ul><li>例如当前模块为<code>fetchData.js</code>,要在模块内引入一个名为<code>data.json</code>的数据:</li><li><code>import( new URL('data.json', i<wbr>mport.meta.url) )</code></li></ul></li><li>Node.js环境下,该值都是<code>file://</code>协议的链接</li></ul></li><li><code>i<wbr>mport.meta.scriptElement</code><ul><li>浏览器特有的属性</li><li>返回加载模块的<code><script></code>标签,相当于<code>document.currentScript</code></li></ul></li></ul><p>规范中并未规定<code>i<wbr>mport.meta</code>中包含哪些属性,一般包括上面两个属性</p><h3 id="深入理解模块加载" tabindex="-1">深入理解模块加载 <a class="header-anchor" href="#深入理解模块加载" aria-hidden="true">#</a></h3><h4 id="esmodule的解析过程" tabindex="-1">ESModule的解析过程 <a class="header-anchor" href="#esmodule的解析过程" aria-hidden="true">#</a></h4><p>ESModule的解析过程可以分为三个阶段:</p><ul><li>构建 <code>Construction</code><ul><li>根据地址查找JS文件,并发起HTTP请求下载,将其解析为模块记录 <code>Module Record</code></li></ul></li><li>实例化 <code>Instatiation</code><ul><li>对模块记录进行实例化,并为其分配内存空间</li><li>解析ESModule模块的<strong>导入和导出</strong>语句,将模块指向对应的内存地址</li><li>例如<code>export const name = 'Ziu'</code>,会将变量<code>name</code>添加到模块环境记录中 <code>Module Enviroment Record</code></li></ul></li><li>运行 <code>Evaluation</code><ul><li>运行代码,计算值,并且将值填充到内存地址中</li><li>将导入导出的<strong>值</strong>赋给对应的变量<code>name = 'Ziu'</code></li></ul></li></ul><p><img src="https://hacks.mozilla.org/files/2018/03/07_3_phases.png" alt="ESModule解析过程"></p><p>文章推荐:<a href="https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/" target="_blank" rel="noreferrer">ES modules: A cartoon deep-dive</a></p><h4 id="mjs和cjs的区别" tabindex="-1">MJS和CJS的区别 <a class="header-anchor" href="#mjs和cjs的区别" aria-hidden="true">#</a></h4><ul><li><strong>CommonJS模块输出的是值的拷贝,而ESModule模块输出的是值的引用</strong><ul><li>CJS导出的变量,其值如果在模块内发生变化,外部导入是不会同步更新的,除非导出的是一个取值函数</li><li>MJS导出变量,外部模块每次访问时都会得到该变量最新的值,即使变量在模块内被修改了</li></ul></li><li><strong>CommonJS模块是运行时加载,而ESModule是编译时输出接口</strong><ul><li>CJS是<strong>通过对象实现</strong>的导入导出,它<strong>在运行时才被确定依赖关系</strong>和其值</li><li>MJS则是<strong>通过静态定义</strong>,在代码运行之前的<strong>静态解析阶段即可确定模块的导入导出内容</strong></li></ul></li><li><strong>CommonJS模块的<code>require()</code>是同步加载模块,而ESModule模块的<code>import</code>命令是异步加载模块</strong><ul><li><code>import</code>命令拥有一个独立的模块依赖的解析阶段</li></ul></li></ul><h4 id="cjs中的循环加载" tabindex="-1">CJS中的循环加载 <a class="header-anchor" href="#cjs中的循环加载" aria-hidden="true">#</a></h4><p>设想有以下两文件 <code>a.js</code>与<code>b.js</code>:</p><div class="vp-code-group"><div class="tabs"><input type="radio" name="group-X6fqn" id="tab-BvUxYTB" checked="checked"><label for="tab-BvUxYTB">a.js</label><input type="radio" name="group-X6fqn" id="tab-dquqOAo"><label for="tab-dquqOAo">b.js</label><input type="radio" name="group-X6fqn" id="tab-HYeE9Xd"><label for="tab-HYeE9Xd">main.js</label></div><div class="blocks"><div class="language-js active line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// a.js</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">exports.</span><span style="color:#A6ACCD;">done </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">false</span></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> b </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">require</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">./b.js</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">在 a.js 之中,b.done = %j</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> b</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">done)</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">exports.</span><span style="color:#A6ACCD;">done </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">true</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">a.js 执行完毕</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// b.js</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">exports.</span><span style="color:#A6ACCD;">done </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">false</span></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> a </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">require</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">./a.js</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">在 b.js 之中,a.done = %j</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> a</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">done)</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">exports.</span><span style="color:#A6ACCD;">done </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">true</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">b.js 执行完毕</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// main.js</span></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> a </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">require</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">./a</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> b </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">require</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">./b</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">在 main.js 之中, a.done=%j, b.done=%j</span><span style="color:#89DDFF;">'</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> a</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">done</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> b</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">done)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div></div></div><p>执行脚本<code>main.js</code>,先执行<code>a.js</code>:</p><ul><li>第一行 导出<code>done</code>值为<code>false</code></li><li>第二行 <code>a.js</code>的代码暂停执行 进入<code>b.js</code>并等待其执行完毕</li></ul><p>在<code>b.js</code>中:</p><ul><li>第一行 导出<code>done</code>值为<code>false</code></li><li>第二行 执行<code>a.js</code> 从<code>a.js</code>模块中取<code>exports</code>对象</li><li><strong>取到其缓存值为<code>false</code>(<code>a.js</code>执行已经执行的部分)</strong></li><li>随后<code>b.js</code>继续向下执行 执行完毕后 将执行权交还给<code>a.js</code></li></ul><p>回到<code>a.js</code>中:</p><ul><li>继续向后执行 直到代码执行完毕</li></ul><p>最终输出:</p><div class="language-sh line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">sh</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#FFCB6B;">在</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">b.js</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">之中,a.done</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">false</span></span>
|
||
<span class="line"><span style="color:#FFCB6B;">b.js</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">执行完毕</span></span>
|
||
<span class="line"><span style="color:#FFCB6B;">在</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">a.js</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">之中,b.done</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">true</span></span>
|
||
<span class="line"><span style="color:#FFCB6B;">a.js</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">执行完毕</span></span>
|
||
<span class="line"><span style="color:#FFCB6B;">在</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">main.js</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">之中,</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">a.done=</span><span style="color:#89DDFF;">true</span><span style="color:#C3E88D;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#C3E88D;">b.done=</span><span style="color:#89DDFF;">true</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p>总结:</p><ul><li>CJS的模块导出是输出值的拷贝,而不是引用,值的变化不是动态的,而是会被缓存的</li><li>循环加载时,CJS模块导出的值是当前已经执行部分代码产生的结果的值,而不是模块代码完全执行完后的最终值</li></ul><h4 id="mjs中的循环加载" tabindex="-1">MJS中的循环加载 <a class="header-anchor" href="#mjs中的循环加载" aria-hidden="true">#</a></h4><p>ESModule的导入和导出与CommonJS有本质不同:</p><div class="vp-code-group"><div class="tabs"><input type="radio" name="group-ijy5d" id="tab-FMSxdfJ" checked="checked"><label for="tab-FMSxdfJ">a.mjs</label><input type="radio" name="group-ijy5d" id="tab-8CO0rm_"><label for="tab-8CO0rm_">b.mjs</label></div><div class="blocks"><div class="language-js active line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// a.mjs</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">bar</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">./b.mjs</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">a.mjs</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(bar)</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> foo </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">foo</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// b.mjs</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">foo</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">./a.mjs</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">b.mjs</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(foo)</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">let</span><span style="color:#A6ACCD;"> bar </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">bar</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div></div></div><p>执行<code>a.mjs</code>后发现报错了:<code>ReferenceError: Cannot access 'foo' before initialization</code>,变量<code>foo</code>未定义</p><ul><li>MJS模块在代码执行前会进行静态分析</li><li>分析<code>a.mjs</code>的依赖关系时,发现其依赖了<code>b.mjs</code></li><li>于是加载<code>b.mjs</code>并解析它的依赖关系</li><li>解析<code>b.mjs</code>的过程中,发现它又依赖了<code>a.mjs</code></li><li>这时引擎不会再去加载<code>a.mjs</code> 而是认为<code>a.mjs</code>这个模块的<code>Module Record</code>已经存在了</li><li>继续向下执行,执行到<code>console.log(foo)</code>时发现<code>foo</code>未定义 抛出错误</li></ul><p>要实现预期效果,可以将<code>foo</code>与<code>bar</code>改写为取值函数,这时执行就不会报错了:</p><div class="vp-code-group"><div class="tabs"><input type="radio" name="group-DY0oJ" id="tab-Sx-FeMG" checked="checked"><label for="tab-Sx-FeMG">a.mjs</label><input type="radio" name="group-DY0oJ" id="tab-IzsdUCm"><label for="tab-IzsdUCm">b.mjs</label></div><div class="blocks"><div class="language-js active line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// a.mjs</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">bar</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">./b.mjs</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">a.mjs</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#82AAFF;">bar</span><span style="color:#A6ACCD;">())</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">foo</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">foo</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><div class="language-js line-numbers-mode"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">// b.mjs</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">foo</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;font-style:italic;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">./a.mjs</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">b.mjs</span><span style="color:#89DDFF;">'</span><span style="color:#A6ACCD;">)</span></span>
|
||
<span class="line"><span style="color:#A6ACCD;">console</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">log</span><span style="color:#A6ACCD;">(</span><span style="color:#82AAFF;">foo</span><span style="color:#A6ACCD;">())</span></span>
|
||
<span class="line"><span style="color:#89DDFF;font-style:italic;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">bar</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
|
||
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">'</span><span style="color:#C3E88D;">bar</span><span style="color:#89DDFF;">'</span></span>
|
||
<span class="line"><span style="color:#89DDFF;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers-wrapper" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div></div></div><p>这是因为函数<code>function</code>具有提升作用,在<code>a.mjs</code>中执行<code>import { bar } from './b.mjs'</code>之前,<code>foo</code>就有定义了。</p><p>因此在进入<code>b.mjs</code>执行<code>console.log(foo())</code>时可以取到<code>foo</code>,代码可以顺利执行</p><p>另:如果将<code>foo</code>定义为函数表达式<code>export const foo = () => 'foo'</code>,由于没有变量提升,代码仍然会报错</p><h4 id="内部变量差异" tabindex="-1">内部变量差异 <a class="header-anchor" href="#内部变量差异" aria-hidden="true">#</a></h4><p>ESModule和CommonJS另一个重要区别就是:</p><p>ESModule模块是在浏览器与服务端通用的,之前在解读CommonJS时介绍了它拥有的一些内部变量(模块变量):</p><ul><li><code>arguments</code></li><li><code>require</code></li><li><code>module</code></li><li><code>exports</code></li><li><code>__filename</code></li><li><code>_dirname</code></li></ul><p>这些变量在ESModule模块中都是不存在的,且顶层的<code>this</code>不再指向当前模块,而是<code>undefined</code></p><h3 id="拓展内容" tabindex="-1">拓展内容 <a class="header-anchor" href="#拓展内容" aria-hidden="true">#</a></h3><h4 id="在node-js中使用esmodule" tabindex="-1">在Node.js中使用ESModule <a class="header-anchor" href="#在node-js中使用esmodule" aria-hidden="true">#</a></h4><p>在Node.js中,普通的<code>.js</code>文件会被默认解析为CommonJS,要使用ESModule有两种方式:</p><ul><li>所有ESModule的后缀名都使用<code>.mjs</code>并且不可省略 <ul><li>这样引擎在解析到<code>.mjs</code>结尾的文件时,将按照ESModule的规则解析其导入导出关系</li></ul></li><li>将<code>package.json</code>中的<code>type</code>字段修改为<code>module</code><ul><li>此时项目中所有<code>.js</code>文件都将被作为ESModule模块解析</li><li>要在此项目中使用CommonJS,则需要将后缀名修改为<code>.cjs</code></li></ul></li></ul><h4 id="解读package-json中的字段" tabindex="-1">解读<code>package.json</code>中的字段 <a class="header-anchor" href="#解读package-json中的字段" aria-hidden="true">#</a></h4><ul><li><p><code>main</code>字段</p><ul><li>指定一个npm包的<code>main</code>字段为一个JS模块</li><li>当我们从其他位置通过<code>import { something } from 'es-module-package'</code>导入时</li><li>Node.js将从<code>main</code>字段指定的模块查找导出内容</li></ul></li><li><p><code>exports</code>字段</p><ul><li><code>exports</code>字段优先级高于<code>main</code>字段,它具有多种用法:</li><li>子目录别名 <ul><li>假设如是定义<code>exports</code>字段:<code>exports: { "./submodule": "./src/submodule.js" }</code></li><li>当执行<code>import submodule from 'es-module-package/submodule'</code>时,会按照以下路径查找模块:</li><li><code>./node_modules/es-module-package/src/submodule.js</code></li></ul></li><li><code>main</code>的别名</li><li>条件加载</li></ul></li></ul><p>参考:<a href="https://es6.ruanyifeng.com/#docs/module-loader#package-json-%E7%9A%84-exports-%E5%AD%97%E6%AE%B5" target="_blank" rel="noreferrer">package.json 的 exports 字段</a></p></div></div></main><!--[--><!--]--><footer class="VPDocFooter" data-v-30dabfe4 data-v-cc0f9778><div class="edit-info" data-v-cc0f9778><div class="edit-link" data-v-cc0f9778><a class="VPLink link edit-link-button" href="https://github.com/ZiuChen/ZiuChen.github.io/edit/main/docs/note/Front-end Engineering.md" target="_blank" rel="noreferrer" data-v-cc0f9778 data-v-8dd200cc><!--[--><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" class="edit-link-icon" data-v-cc0f9778><path d="M18,23H4c-1.7,0-3-1.3-3-3V6c0-1.7,1.3-3,3-3h7c0.6,0,1,0.4,1,1s-0.4,1-1,1H4C3.4,5,3,5.4,3,6v14c0,0.6,0.4,1,1,1h14c0.6,0,1-0.4,1-1v-7c0-0.6,0.4-1,1-1s1,0.4,1,1v7C21,21.7,19.7,23,18,23z"></path><path d="M8,17c-0.3,0-0.5-0.1-0.7-0.3C7,16.5,6.9,16.1,7,15.8l1-4c0-0.2,0.1-0.3,0.3-0.5l9.5-9.5c1.2-1.2,3.2-1.2,4.4,0c1.2,1.2,1.2,3.2,0,4.4l-9.5,9.5c-0.1,0.1-0.3,0.2-0.5,0.3l-4,1C8.2,17,8.1,17,8,17zM9.9,12.5l-0.5,2.1l2.1-0.5l9.3-9.3c0.4-0.4,0.4-1.1,0-1.6c-0.4-0.4-1.2-0.4-1.6,0l0,0L9.9,12.5z M18.5,2.5L18.5,2.5L18.5,2.5z"></path></svg> Edit this page on GitHub<!--]--><!----></a></div><div class="last-updated" data-v-cc0f9778><p class="VPLastUpdated" data-v-cc0f9778 data-v-de6a4e1f>Updated Date: <time datetime="2023-02-11T17:51:22.000Z" data-v-de6a4e1f></time></p></div></div><div class="prev-next" data-v-cc0f9778><div class="pager" data-v-cc0f9778><a class="pager-link prev" href="/note/JavaScriptEnhanced.html" data-v-cc0f9778><span class="desc" data-v-cc0f9778>Previous page</span><span class="title" data-v-cc0f9778>JavaScript进阶</span></a></div><div class="has-prev pager" data-v-cc0f9778><!----></div></div></footer><!--[--><!--]--></div></div></div></div></div><footer class="VPFooter has-sidebar" data-v-3af881ed data-v-8b655284><div class="container" data-v-8b655284><p class="message" data-v-8b655284>Released under the MIT License.</p><p class="copyright" data-v-8b655284>Copyright © 2019-present Ziu Chen</p></div></footer><!--[--><!--]--></div></div>
|
||
<script>__VP_HASH_MAP__ = JSON.parse("{\"article_一文读懂事件冒泡与事件捕获.md\":\"1fae2ef6\",\"article_深入vue3源码,看看vue.use后究竟发生了什么?.md\":\"e9cb7103\",\"index.md\":\"c44d84f3\",\"article_【2023】青训营 - 前端练习题汇总解析.md\":\"08daa7cb\",\"article_一文读懂伪类与伪元素.md\":\"f13fdfe2\",\"article_从0实现一个年度报告.md\":\"7889052b\",\"article_一文读懂函数中this指向问题.md\":\"3d26963f\",\"article_彻底搞懂对象的数据属性描述符、存储属性描述符.md\":\"a79489f6\",\"article_深入理解proxy与reflect.md\":\"29b5e84c\",\"article_深入理解浏览器缓存机制.md\":\"6cb4dc3b\",\"article_深入理解浏览器运行原理.md\":\"afa95ccd\",\"note_javascript.md\":\"274c2492\",\"note_front-end engineering.md\":\"3f047f08\",\"note_css.md\":\"7c0e34d6\",\"project_smartwordbreak_log_index.md\":\"dfc020de\",\"project_smartwordbreak_statement_index.md\":\"db452751\",\"self_index.md\":\"dd9eeb1d\",\"works_contribution.md\":\"fb91e133\",\"works_opensource.md\":\"48524035\",\"project_clipboardmanager_vip_index.md\":\"440f01a9\",\"project_clipboardmanager_statement_index.md\":\"d5066f69\",\"project_clipboardmanager_guide_index.md\":\"81ab619b\",\"project_clipboardmanager_log_index.md\":\"0a410da9\",\"project_smartwordbreak_index.md\":\"d5edfcd7\",\"project_clipboardmanager_index.md\":\"beb258ff\",\"note_javascriptenhanced.md\":\"ded85c98\"}")</script>
|
||
<script type="module" async src="/assets/app.f4e2d6d1.js"></script>
|
||
|
||
</body>
|
||
</html> |