<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>阮超民的网络日志</title>
  <subtitle type="text">阮超民的个人网站 - Ruan ChaoMin's Personal Website</subtitle>
  <id>https://www.ruanchaomin.com/</id>
  <updated>2026-04-30T11:40:57Z</updated>
  <entry>
    <title>2025｜风吹过钱塘江，我走过这一年</title>
    <link rel="alternate" href="https://www.ruanchaomin.com/blog/posts/247" />
    <category term="闲言碎语" scheme="https://www.ruanchaomin.com/blog/gossip" />
    <author>
      <name>阮超民</name>
      <uri>https://www.ruanchaomin.com/</uri>
    </author>
    <id>247</id>
    <updated>2026-04-30T11:40:57Z</updated>
    <published>2026-01-14T16:45:19Z</published>
    <content type="html">&lt;div class="markdown-body editormd-preview-container" previewcontainer="true"&gt;&lt;h1 id="前言"&gt;前言&lt;/h1&gt;&lt;p&gt;嘿嘿，好久没有更新博客了。一时间也不知道写什么，那就从今年的总结开始吧。虽然很久没写博客文章，但博客本身还是一直在维护。&lt;/p&gt;
&lt;p&gt;今年给博客加了新的&lt;a href="https://www.ruanchaomin.com/moments" target="_blank" title="「动态」"&gt;「动态」&lt;/a&gt;模块，可以随手记录一些照片；也新加了&lt;a href="https://www.ruanchaomin.com/about" target="_blank" title="「关于」"&gt;「关于」&lt;/a&gt;页面，放了一点自己的介绍。前几天还把博客里所有图片的图床统一迁移到了 Cloudflare。&lt;/p&gt;
&lt;h1 id="出行"&gt;出行&lt;/h1&gt;&lt;p&gt;今年一共请了 14.5 天假，把往年的假期和 2025 年的假期都用光了。真正出去玩的只有南京一趟，其余时间基本都在福州和杭州之间来回穿梭。下面是今年的出行记录：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;时间&lt;/th&gt;
&lt;th&gt;行程&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2025-01-24 → 2025-02-06&lt;/td&gt;
&lt;td&gt;杭州 ⇄ 南京 ⇄ 福州 ⇄ 杭州&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025-04-03 → 2025-04-06&lt;/td&gt;
&lt;td&gt;杭州 ⇄ 福州&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025-04-30 → 2025-05-06&lt;/td&gt;
&lt;td&gt;杭州 ⇄ 福州&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025-05-30 → 2025-06-03&lt;/td&gt;
&lt;td&gt;杭州 ⇄ 福州&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025-07-11 → 2025-07-14&lt;/td&gt;
&lt;td&gt;杭州 ⇄ 福州&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025-09-26 → 2025-10-08&lt;/td&gt;
&lt;td&gt;杭州 ⇄ 福州&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025-11-13 → 2025-11-17&lt;/td&gt;
&lt;td&gt;杭州 ⇄ 福州&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025-12-26 → 2026-01-03&lt;/td&gt;
&lt;td&gt;杭州 ⇄ 福州&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;高德地图的年度报告：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/高德地图_2026-01-09_000527_903.png" alt=""&gt;
&lt;/p&gt;&lt;h1 id="运动"&gt;运动&lt;/h1&gt;&lt;p&gt;2025 年，我最喜欢的运动是骑行。杭州滨江的樱花大道，在记忆里仍然盛放——那里，是我&lt;a href="https://www.ruanchaomin.com/moments/53" target="_blank" title="第一次骑行"&gt;第一次骑行&lt;/a&gt;的地方。也正是从那一刻开始，慢慢爱上了骑行。后来常常沿着钱塘江边骑上一圈，耳机里放着喜欢的音乐，夏日的微风从身侧掠过，心也变得轻快而自由。只是最近没再出发，冬日的杭州有些冷，车轮也需要休息。等春风再起的时候，再出发。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/keep_2026-01-09-23-37-16-111_com.gotokeep.keep.jpg" alt=""&gt;
&lt;/p&gt;&lt;h1 id="工作"&gt;工作&lt;/h1&gt;&lt;p&gt;工作之后，时间仿佛开始加速，一转眼已经在这家公司走过四年。依旧大小周，工作日大多从早上九点半到晚上九点。今年做了新的项目，日子被任务与项目填满，但也在不断积累经验与成长。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/Screenshot_work_four_year.jpg" alt=""&gt;
&lt;/p&gt;&lt;p&gt;2025 年通过了年度晋升，从“普通牛马”升级为“高级牛马”。称谓在变，责任也在变，手里的事情变得更多、更复杂了。有时候也挺累的，但在这一份忙碌里，也确实看到了自己逐渐成长与沉淀。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/Screenshot_work_2025_up.jpg" alt=""&gt;
&lt;/p&gt;&lt;h1 id="搬家"&gt;搬家&lt;/h1&gt;&lt;p&gt;2025 年的睡眠状态不算理想，经常失眠，工作之后也常常熬夜。在这个小区已经住了四年，中间第二年搬过一次，只是换到隔壁幢，那次还挺顺利。后来又在这里住了三年。&lt;/p&gt;
&lt;p&gt;今年十月份开始，楼上噪音不断。忍了两个月后，在到期前一周搬了家。算一算，在杭州已经待了四年多，这是第三次搬家：第一次从余杭到滨江，第二次搬到隔壁幢，而这一次，换了个新的小区，离公司更近就几百米。&lt;/p&gt;
&lt;p&gt;现在的新家，偶尔楼上也会有些声音，但整体环境已经好了不少，搬家前后的睡眠质量对比也记录了下来：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/Screenshot_2025-12-12-22-42-58-113_com.mi.health.jpg" alt=""&gt;
&lt;/p&gt;&lt;h1 id="周末"&gt;周末&lt;/h1&gt;&lt;p&gt;大小周的节奏里，单休大多用来补觉，把工作日欠下的睡眠还回来。双休的日子，要么去跑步、骑行，要么在城里闲逛，和朋友吃吃喝喝。西湖去了很多次，钱塘江边也走了无数遍。&lt;/p&gt;
&lt;p&gt;周末闲暇时，听着音乐下厨做点喜欢吃的东西，成了最治愈的时刻。只是——吃了那么多，好像还是很难长胖。&lt;/p&gt;
&lt;h1 id="后记"&gt;后记&lt;/h1&gt;&lt;p&gt;用最近看到的这段话作为结尾：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;目前时代的红利只有一个，身体保持健康。因为大家现在卷的不是工作，不是房和车，而是良好心态和深度睡眠。当所有人都在信息过载、焦虑失眠的泥潭里打滚时，你能吃得好，睡得着，情绪稳定，精力充沛，这本身就是一种降维打击，你的身体，才是你在这个时代最硬核的生产资料和安全资产。还有一个更关键的理由，科技爆炸带来的寿命红利，只留给那些能活到并能接得住的人。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;新的一年，少熬点夜，吃得香睡得好，健康快乐，比什么都重要。&lt;/p&gt;
&lt;p&gt;祝读到这里的你，2026年一切安好。&lt;/p&gt;
&lt;/div&gt;</content>
    <summary type="text">2025 年度总结</summary>
  </entry>
  <entry>
    <title>Chrome DevTools 奇技淫巧</title>
    <link rel="alternate" href="https://www.ruanchaomin.com/blog/posts/244" />
    <category term="浏览器" scheme="https://www.ruanchaomin.com/blog/browser" />
    <author>
      <name>阮超民</name>
      <uri>https://www.ruanchaomin.com/</uri>
    </author>
    <id>244</id>
    <updated>2026-05-02T09:20:54Z</updated>
    <published>2023-09-13T16:28:25Z</published>
    <content type="html">&lt;div class="markdown-body editormd-preview-container" previewcontainer="true"&gt;&lt;h1 id="前言"&gt;前言&lt;/h1&gt;&lt;p&gt;Chrome DevTools 是每位前端开发者的得力助手，它提供了丰富的功能和工具，帮助我们诊断和调试网页应用程序。本文将分享一些 Chrome DevTools 的调试技巧，在开发中提高效率。&lt;/p&gt;
&lt;p&gt;2023年9月12日，&lt;a href="https://chromereleases.googleblog.com/2023/09/stable-channel-update-for-desktop_12.html" target="_blank" title="Stable Channel Update for Desktop"&gt;Chrome 团队发布了 Chrome 117 桌面稳定版&lt;/a&gt;，本文将使用最新版本介绍。&lt;/p&gt;
&lt;h1 id="模拟接口响应和网页内容"&gt;模拟接口响应和网页内容&lt;/h1&gt;&lt;p&gt;通过本地覆盖可以模拟接口返回值和响应头，无需 mock 数据工具，无需等待后端支持，快速复现在一些数据下的 BUG 等。在 DevTools 可以直接修改你想要的 Fetch/XHR 接口数据，还可以修改响应头，解决跨域等问题，不仅可以覆盖 Fetch/XHR，JS、CSS 等资源也可以。&lt;/p&gt;
&lt;p&gt;本地覆盖其实在之前的版本就已经有了，需要在本地手动创建目录，步骤麻烦。&lt;strong&gt;Chrome 117&lt;/strong&gt; 对本地覆盖功能简化，现在可以直接在 &lt;code&gt;Network&lt;/code&gt; 面板快速模拟远程资源的内容和响应头！如下图演示：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/e028bfea0588443a95cfebd0fc323653.gif" alt=""&gt;
&lt;/p&gt;&lt;p&gt;设置本地覆盖步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;打开 DevTools，导航至 &lt;code&gt;Network&lt;/code&gt; 网络面板，右键单击要覆盖的请求，从下拉菜单中选择 Override content 或 Open in Sources panel。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;如果是首次使用，未设置过本地覆盖文件目录，DevTools 会在顶部的操作栏中提示您选择一个文件夹来存储覆盖文件，并 “允许” 授予 DevTools 对其的访问权限（在 window 下选择了系统盘的文件夹测试发现用不了，可能是权限问题，建议选个非系统盘的文件夹）。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;在 Sources 面板中修改数据，完成后按 Ctrl + S 保存，刷新页面，即可看见修改后的数据（被覆盖的资源在图标右下角会有个紫色的圆点）。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;若要恢复使用服务上的数据，请导航到 &lt;code&gt;Sources&lt;/code&gt; &amp;gt; &lt;code&gt;Overrides&lt;/code&gt;，可以点击取消 “Enable local overrides” 复选框，或者点击旁边的 Clear 图标，或者如上图演示中的单个删除。&lt;/p&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;它是怎么工作的？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;当你在 DevTools 中进行更改时，DevTools 会将修改后的文件的副本保存到您指定的文件夹中。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;当你重新加载页面时，DevTools 会提供本地修改后的文件，而不是网络资源。所以在旧版本支持 Override 的版本中，也可以手动创建一个文件来覆盖内容。&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;h1 id="快速重发请求"&gt;快速重发请求&lt;/h1&gt;&lt;p&gt;在联调接口或者排查 BUG 的时候，经常需要重新再发一次请求，如果要重新操作一次复杂的交互、重新输入一大堆参数时，这种方式会显得比较麻烦。&lt;/p&gt;
&lt;p&gt;这时候就可以通过 &lt;code&gt;Replay XHR&lt;/code&gt; 来快速重发请求，如下图演示：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/b3c417880bd64942a7f4b424f98471e7.gif" alt=""&gt;
&lt;/p&gt;&lt;p&gt;操作步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;导航至 &lt;code&gt;Network&lt;/code&gt; 网络面板，右击一个 XHR 请求，可以点击 Fetch/XHR 过滤。&lt;/li&gt;&lt;li&gt;点击 Replay XHR。&lt;/li&gt;&lt;/ol&gt;
&lt;h1 id="在 Console 中发请求"&gt;在 Console 中发请求&lt;/h1&gt;&lt;p&gt;针对上面同样的场景，有时候我们需要修改请求头、入参再重新发起请求，那么 Replay XHR 就不支持了。&lt;/p&gt;
&lt;p&gt;可以通过 Copy as fetch ，在控制台修改请求参数，发起请求，如下图演示：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/ee0d41be27654ae2a44bf78b42964983.gif" alt=""&gt;
&lt;/p&gt;&lt;p&gt;操作步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;导航至 &lt;code&gt;Network&lt;/code&gt; 网络面板，右击一个 XHR 请求，可以点击 Fetch/XHR 过滤。&lt;/li&gt;&lt;li&gt;点击 Copy -&amp;gt; Copy as fetch。&lt;/li&gt;&lt;li&gt;导航至 &lt;code&gt;Console&lt;/code&gt; 面板，Ctrl + v 粘贴。&lt;/li&gt;&lt;li&gt;修改内容，如接口 url、header、body， 然后按回车键即可发起请求。&lt;/li&gt;&lt;/ol&gt;
&lt;h1 id="条件断点"&gt;条件断点&lt;/h1&gt;&lt;p&gt;如果我们在某个循环中，希望循环到某个条件的时候在进入断点。&lt;br&gt;此时我们就可以使用 conditional breakpoint 如下图演示：
&lt;/p&gt;&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/1911e2260df14e45b1ee9c5011e6173b.gif" alt=""&gt;
&lt;/p&gt;&lt;p&gt;操作步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;右击代码行，点击 Add conditional breakpoint，或者按住 Ctrl + 鼠标左点击代码行。&lt;/li&gt;&lt;li&gt;输入条件表达式。&lt;/li&gt;&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt; Add log point 为条件日志，可以不用在代码中写 console.log。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id="Console 中的 $"&gt;Console 中的 $&lt;/h1&gt;&lt;h2 id="$0-$4"&gt;$0-$4&lt;/h2&gt;&lt;p&gt;当要在 Console 中在调试页面元素时，比如要获取元素的信息，此时就可以使用 $0-$4。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;$0：&lt;/strong&gt;当前选择的元素 ，&lt;strong&gt;$1：&lt;/strong&gt;上一次的引用，&lt;strong&gt;$2：&lt;/strong&gt;上上次的引用，一直到 &lt;strong&gt;$4&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;例如获得某个元素相对于其 &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetParent" target="_blank" title="offsetParent"&gt;offsetParent&lt;/a&gt; 元素的顶部内边距的距离，演示如下：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/2a461b6dfe8945c49c46ecfde45bce1d.gif" alt=""&gt;
&lt;/p&gt;&lt;p&gt;操作步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;点击菜单栏第一个选择图标，或者使用快捷键 Ctrl + Shift + C 选择元素。&lt;/li&gt;&lt;li&gt;导航至 &lt;code&gt;Console&lt;/code&gt; 面板，现在就可以使用 $0-$4，例如选择了两次，第一次选择的元素可以使用 $1 访问，第二次选择的元素使用 $0 访问。&lt;/li&gt;&lt;/ol&gt;
&lt;h2 id="$ 和 $$"&gt;$ 和 $$&lt;/h2&gt;&lt;p&gt;$(‘xxx’) 相当于 document.querySelector(‘xxx’)&lt;br&gt;$$(‘xxx’) 相当于 Array.form(document.querySelectorall(‘xxx’))
&lt;/p&gt;&lt;p&gt;如下图演示：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/4d9267f6f6a44251b568d1af714b2842.gif" alt=""&gt;
&lt;/p&gt;&lt;h2 id="$_"&gt;$_&lt;/h2&gt;&lt;p&gt;调试的过程中，经常需要打印一些变量值，但是如果想查看上一次执行的结果，使用 $_ 是对上次执行结果的引用。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/20f86a12a4924cae95a9e390ba8271a1.png" alt=""&gt;
&lt;/p&gt;&lt;h2 id="$i"&gt;$i&lt;/h2&gt;&lt;p&gt;现在的前端开发过程，离不开各种 npm 包，如果我们要测试一个 npm 包，需要先在本地npm init，然后再 npm install xxx。&lt;/p&gt;
&lt;p&gt;Console Importer 插件可以帮助我们，在控制台使用 $i(‘xxxx’) 进行装包，并进行调用。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/abf97451a25b4e61b12a227e8ea007e7.png" alt=""&gt;
&lt;/p&gt;&lt;h1 id="Element 面板"&gt;Element 面板&lt;/h1&gt;&lt;h2 id="隐藏 DOM Element"&gt;隐藏 DOM Element&lt;/h2&gt;&lt;p&gt;有时候我们想截图，但是想要隐藏图中的敏感信息，此时就可以隐藏元素，如下图演示：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/ba321ea536e546a79dcc3756d8c3da72.gif" alt=""&gt;
&lt;/p&gt;&lt;p&gt;操作步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;右键 DOM Element，点击 Hide Element。也可以使用键盘快捷键，点击选中 Element 后，按键盘 H 键。&lt;/li&gt;&lt;/ol&gt;
&lt;h2 id="一键展开所有 DOM"&gt;一键展开所有 DOM&lt;/h2&gt;&lt;p&gt;在调式 DOM Element 的时候，如果 DOM 层次比较深的情况下，一个个去展开就比较麻烦，我们可以使用快捷键 Alt + Click 一键展开该层下的所有 DOM，如下图演示：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/8c9de4618c7a480d9957db6b98f0a7ad.gif" alt=""&gt;
&lt;/p&gt;&lt;h2 id="拖拽移动 DOM Element"&gt;拖拽移动 DOM Element&lt;/h2&gt;&lt;p&gt;当我们想看页面某一部分元素在不同的位置显示效果的时候，可以直接拖拽 DOM 元素调整位置，也可以使用键盘快捷键 Ctrl + 上下箭头。如下图演示：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/bc295d9031a04ec18560c1bd82e4958e.gif" alt=""&gt;
&lt;/p&gt;&lt;h1 id="截图"&gt;截图&lt;/h1&gt;&lt;p&gt;如果想要截取多屏很长的整个页面内容，系统自带的截图软件显然不支持，此时可以使用 command 命令截图，如下图演示：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/398b3631ed66423ca10870776ee0d5de.gif" alt=""&gt;
&lt;/p&gt;&lt;p&gt;操作步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;按 Ctrl + Shift + P 调出 command 命令&lt;/li&gt;&lt;li&gt;输入命令 capture full size screenshot 后回车。&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;截图 command：&lt;br&gt;截框选区域：&lt;strong&gt;capture area screenshot&lt;/strong&gt;&lt;br&gt;截滚动全屏：&lt;strong&gt;capture full size screenshot&lt;/strong&gt;&lt;br&gt;截选中的节点：&lt;strong&gt;capture node screenshot&lt;/strong&gt;&lt;br&gt;截当前窗口内：&lt;strong&gt;capture screenshot &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;还有很多其他的命令，如切换主题 Switch to Dark theme，查看所有快捷键 Show shortcuts 等等。&lt;/p&gt;
&lt;h1 id="总结"&gt;总结&lt;/h1&gt;&lt;p&gt;本文介绍了 Chrome DevTools 的调试技巧和最新版本 Chrome 117 中的新功能，包括模拟接口响应和网页内容、快速重发请求、在 Console 中发请求、Console 中的快捷命令、条件断点、Element 面板以及截图命令，这些调试技巧有助于我们在开发中提高效率。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;参考&lt;br&gt;&lt;a href="https://developer.chrome.com/blog/new-in-devtools-117/?utm_source=devtools" target="_blank" title="What's New in DevTools (Chrome 117) "&gt;What’s New in DevTools (Chrome 117) &lt;/a&gt;&lt;br&gt;&lt;a href="https://developer.chrome.com/docs/devtools/overrides/" target="_blank" title="Override web content and HTTP response headers locally"&gt;Override web content and HTTP response headers locally&lt;/a&gt;&lt;br&gt;&lt;a href="https://developer.chrome.com/docs/devtools/" target="_blank" title="Chrome DevTools"&gt;Chrome DevTools&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;</content>
    <summary type="text">本文将分享一些 Chrome DevTools 的调试技巧，在前端开发中提高效率。</summary>
  </entry>
  <entry>
    <title>JavaScript 设计模式</title>
    <link rel="alternate" href="https://www.ruanchaomin.com/blog/posts/228" />
    <category term="JavaScript" scheme="https://www.ruanchaomin.com/blog/javascript" />
    <author>
      <name>阮超民</name>
      <uri>https://www.ruanchaomin.com/</uri>
    </author>
    <id>228</id>
    <updated>2026-04-28T09:30:02Z</updated>
    <published>2023-06-09T14:07:47Z</published>
    <content type="html">&lt;div class="markdown-body editormd-preview-container" previewcontainer="true"&gt;&lt;h1 id="引言"&gt;引言&lt;/h1&gt;&lt;p&gt;JavaScript 设计模式是一种解决特定问题的可复用解决方案，旨在提高代码的可维护性、可读性和可扩展性。设计模式是软件开发中的重要概念，它们为我们提供了一种组织和构建代码的方式，使代码更加优雅和可重用。&lt;/p&gt;
&lt;p&gt;示例代码： &lt;a href="https://github.com/ChaominRuan/examples/tree/main/javascript-design-patterns" target="_blank" title="javascript-design-patterns"&gt;javascript-design-patterns&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;在线运行： &lt;a href="https://chaominruan.github.io/examples/javascript-design-patterns/index.html" target="_blank" title="JavaScript design pattern"&gt;JavaScript design pattern&lt;/a&gt;&lt;/p&gt;
&lt;h1 id="设计模式分类"&gt;设计模式分类&lt;/h1&gt;&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/b5061bb0cabc461880c97005ddebc0e0.png" alt=""&gt;
&lt;/p&gt;&lt;h1 id="创建型设计模式"&gt;创建型设计模式&lt;/h1&gt;&lt;h2 id="单例模式（Singleton Pattern）"&gt;单例模式（Singleton Pattern）&lt;/h2&gt;&lt;p&gt;用于确保一个类只有一个实例，并提供一个全局访问点来访问该实例。它主要用于限制类的实例化次数，避免多个实例的创建和资源的浪费。&lt;/p&gt;
&lt;p&gt;下面是一个单例模式的示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Singleton&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(!&lt;/span&gt;&lt;span class="typ"&gt;Singleton&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;instance&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;data &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;[];&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      &lt;/span&gt;&lt;span class="typ"&gt;Singleton&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;instance &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Singleton&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;instance&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  addItem&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;item&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;data&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;push&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;item&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  getItems&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;data&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 示例使用&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; instance1 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Singleton&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;instance1&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addItem&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Item 1'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; instance2 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Singleton&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;instance2&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addItem&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Item 2'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;instance1&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getItems&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: ['Item 1', 'Item 2']&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;instance2&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getItems&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: ['Item 1', 'Item 2']&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;instance1 &lt;/span&gt;&lt;span class="pun"&gt;===&lt;/span&gt;&lt;span class="pln"&gt; instance2&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: true&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上述示例中，我们定义了一个 Singleton 类，它具有一个私有的静态属性 instance 来存储单例实例。构造函数中使用了一个条件判断，如果 instance 不存在，则创建实例并将其赋值给 instance，否则直接返回 instance。&lt;/p&gt;
&lt;p&gt;还可以使用 ES6 的 &lt;code&gt;Proxy&lt;/code&gt; 来封装实现单例模式：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code&gt;&lt;span class="kwd"&gt;export&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;default&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SingletonPattern&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;className&lt;/span&gt;&lt;span class="pun"&gt;){&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;let&lt;/span&gt;&lt;span class="pln"&gt; instance&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Proxy&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;className&lt;/span&gt;&lt;span class="pun"&gt;,{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code&gt;&lt;span class="pln"&gt;        construct&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;target&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; argArray&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code&gt;&lt;span class="pln"&gt;            &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pun"&gt;(!&lt;/span&gt;&lt;span class="pln"&gt;instance&lt;/span&gt;&lt;span class="pun"&gt;){&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code&gt;&lt;span class="pln"&gt;              instance &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; target&lt;/span&gt;&lt;span class="pun"&gt;(...&lt;/span&gt;&lt;span class="pln"&gt;argArray&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code&gt;&lt;span class="pln"&gt;            &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code&gt;&lt;span class="pln"&gt;            &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Object&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;freeze&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;instance&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;})&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code&gt;&lt;span class="kwd"&gt;import&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SingletonPattern&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;from&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;"./SingletonPattern"&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Person&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code&gt;&lt;span class="pln"&gt;    constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;name&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt;age&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;name &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; name&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;age &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; age&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code&gt;&lt;span class="kwd"&gt;export&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;default&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SingletonPattern&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="typ"&gt;Person&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code&gt;&lt;span class="kwd"&gt;import&lt;/span&gt;&lt;span class="pln"&gt; person &lt;/span&gt;&lt;span class="kwd"&gt;from&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;"./Person"&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; zs &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; person&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'zs'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="lit"&gt;18&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// Person {name: 'zs', age: 18}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; ls &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; person&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'ls'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="lit"&gt;20&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// Person {name: 'zs', age: 18}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;zs &lt;/span&gt;&lt;span class="pun"&gt;===&lt;/span&gt;&lt;span class="pln"&gt; ls&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// true&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;&lt;p&gt;通过使用单例模式，我们可以确保只有一个实例存在，并且可以通过全局访问点来访问该实例。这样可以实现对共享资源的统一管理和访问，并且能够避免重复创建实例。&lt;/p&gt;
&lt;h2 id="工厂模式（Factory Pattern）"&gt;工厂模式（Factory Pattern）&lt;/h2&gt;&lt;p&gt;用于封装对象的创建逻辑，并统一通过工厂方法创建对象。它通过将对象的实例化过程封装在一个工厂函数中，使得创建对象的代码与具体对象的实现解耦，提供了更灵活和可维护的对象创建方式。&lt;/p&gt;
&lt;p&gt;可以根据不同的条件或参数，返回不同的具体对象实例，实现了对象的多态性和可定制性。&lt;/p&gt;
&lt;p&gt;下面是一个工厂模式的示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 具体车辆类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SedanCar&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;type &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'sedan'&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SUVCar&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;type &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'suv'&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SportsCar&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;type &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'sports'&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 工厂类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;CarFactory&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  createCar&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;type&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;switch&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;type&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      &lt;/span&gt;&lt;span class="kwd"&gt;case&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'sedan'&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SedanCar&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      &lt;/span&gt;&lt;span class="kwd"&gt;case&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'suv'&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SUVCar&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      &lt;/span&gt;&lt;span class="kwd"&gt;case&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'sports'&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SportsCar&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      &lt;/span&gt;&lt;span class="kwd"&gt;default&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;throw&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Error&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Can only be sedan or suv or sports'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 示例使用&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; factory &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;CarFactory&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; sedan &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; factory&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;createCar&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'sedan'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; suv &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; factory&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;createCar&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'suv'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; sports &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; factory&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;createCar&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'sports'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;sedan&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;type&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: sedan&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;suv&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;type&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: suv&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;sports&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;type&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: sports&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上述示例中，我们定义了具体的车辆类包括 SedanCar、SUVCar 和 SportsCar，它们都具有一个 type 属性用于标识车辆类型，还有一个 CarFactory 工厂类，它具有一个 createCar 方法用于根据车型参数创建具体的车辆对象。&lt;/p&gt;
&lt;p&gt;通过调用 CarFactory 的 createCar 方法，并传入相应的参数，工厂类会根据参数返回相应类型的车辆对象。&lt;/p&gt;
&lt;p&gt;通过工厂模式，我们可以封装对象的创建过程，使得创建对象的代码与具体对象的实现解耦，提供更灵活和可维护的对象创建方式。&lt;/p&gt;
&lt;h2 id="抽象工厂模式（Abstract Factory Pattern）"&gt;抽象工厂模式（Abstract Factory Pattern）&lt;/h2&gt;&lt;p&gt;用于提供一个接口来创建一系列相关或依赖对象的工厂。它可以通过抽象工厂和具体工厂的组合，创建一组相互关联的对象，而无需指定具体的类。&lt;/p&gt;
&lt;p&gt;抽象工厂模式适用于需要创建一组相关对象的情况，这些对象在某种上下文中需要协同工作，或者需要保持一致的风格或主题。&lt;/p&gt;
&lt;p&gt;下面是一个抽象工厂模式的示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 抽象工厂类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;AbstractCarFactory&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  createSedanCar&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;throw&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Error&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'This method must be implemented.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  createSUVCar&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;throw&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Error&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'This method must be implemented.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 具体产品类 - 奔驰轿车&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;MercedesSedanCar&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;type &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'Mercedes Sedan'&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 具体产品类 - 奔驰SUV&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;MercedesSUVCar&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;type &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'Mercedes SUV'&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 具体产品类 - 宝马轿车&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;BMWSedanCar&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;type &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'BMW Sedan'&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 具体产品类 - 宝马SUV&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;BMWSUVCar&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;type &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'BMW SUV'&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 具体工厂类 - 奔驰车工厂&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;MercedesCarFactory&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;AbstractCarFactory&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  createSedanCar&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;MercedesSedanCar&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  createSUVCar&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;MercedesSUVCar&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 具体工厂类 - 宝马车工厂&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;BMWCarFactory&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;AbstractCarFactory&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  createSedanCar&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;BMWSedanCar&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  createSUVCar&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;BMWSUVCar&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 示例使用&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; mercedesFactory &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;MercedesCarFactory&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; mercedesSedan &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; mercedesFactory&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;createSedanCar&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; mercedesSUV &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; mercedesFactory&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;createSUVCar&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; bmwFactory &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;BMWCarFactory&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; bmwSedan &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; bmwFactory&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;createSedanCar&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; bmwSUV &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; bmwFactory&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;createSUVCar&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;mercedesSedan&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;type&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: Mercedes Sedan&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;mercedesSUV&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;type&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: Mercedes SUV&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;bmwSedan&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;type&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: BMW Sedan&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;bmwSUV&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;type&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: BMW SUV&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上述示例中，我们定义了一个抽象工厂类 AbstractCarFactory，它具有创建轿车和 SUV 车的抽象方法。&lt;/p&gt;
&lt;p&gt;具体的工厂类 MercedesCarFactory 和 BMWCarFactory 继承自抽象工厂类，并实现了创建奔驰车和宝马车的具体方法。&lt;/p&gt;
&lt;p&gt;具体的产品类包括 MercedesSedanCar、MercedesSUVCar、BMWSedanCar 和 BMWSUVCar，它们都具有一个 type 属性用于标识车辆类型。&lt;/p&gt;
&lt;p&gt;通过使用抽象工厂模式，我们可以通过具体的工厂类创建一组相关的产品对象，而无需指定具体的类。这样可以实现一组对象的统一管理和创建，并且能够轻松地扩展和修改工厂类和产品类的组合。&lt;/p&gt;
&lt;h2 id="建造者模式（Builder Pattern）"&gt;建造者模式（Builder Pattern）&lt;/h2&gt;&lt;p&gt;将复杂对象的构建过程与其表示分离。它允许使用相同的构建过程来创建不同的表示形式，并且可以逐步构建对象，使得构建过程更加灵活和可控。&lt;/p&gt;
&lt;p&gt;下面是一个有一些属性的 Car 类：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Car&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;#&lt;/span&gt;&lt;span class="pln"&gt;color&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;#&lt;/span&gt;&lt;span class="pln"&gt;fuelType&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;#&lt;/span&gt;&lt;span class="pln"&gt;productionDate&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;color&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; fuelType&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; productionDate&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;color &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; color&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;fuelType &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; fuelType&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;productionDate &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; productionDate&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    toString&lt;/span&gt;&lt;span class="pun"&gt;(){&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;`&lt;/span&gt;&lt;span class="pln"&gt;car info&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; color&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;color&lt;/span&gt;&lt;span class="pun"&gt;},&lt;/span&gt;&lt;span class="pln"&gt; fuelType&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt;$&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;fuelType&lt;/span&gt;&lt;span class="pun"&gt;},&lt;/span&gt;&lt;span class="pln"&gt; productionDate&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;productionDate&lt;/span&gt;&lt;span class="pun"&gt;}`;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; car &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Car&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'red'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'petrol'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Date&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'2023-05-01'&lt;/span&gt;&lt;span class="pun"&gt;)).&lt;/span&gt;&lt;span class="pln"&gt;toString&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;car&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// car info: color: red, fuelType:petrol, productionDate: Mon May 01 2023 08:00:00 GMT+0800 (中国标准时间)&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;可以看出来，如果要 new 一个 Car，需要记住参数的顺序，虽然这里的属性就 3 个，但是如果有更多属性的对象，就容易混淆。&lt;/p&gt;
&lt;p&gt;要为上面的示例创建一个 Builder 类，我们可以这么做：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;CarBuilder&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;#&lt;/span&gt;&lt;span class="pln"&gt;color&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;#&lt;/span&gt;&lt;span class="pln"&gt;fuelType&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;#&lt;/span&gt;&lt;span class="pln"&gt;productionDate&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    setColor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;color&lt;/span&gt;&lt;span class="pun"&gt;){&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;color &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; color&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    setFuelType&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;fuelType&lt;/span&gt;&lt;span class="pun"&gt;){&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;fuelType &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; fuelType&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    setProductionDate&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;date&lt;/span&gt;&lt;span class="pun"&gt;){&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;productionDate &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; date&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    build&lt;/span&gt;&lt;span class="pun"&gt;(){&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Car&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;color&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;fuelType&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;productionDate&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    toString&lt;/span&gt;&lt;span class="pun"&gt;(){&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;`&lt;/span&gt;&lt;span class="pln"&gt;car info&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; color&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;color&lt;/span&gt;&lt;span class="pun"&gt;},&lt;/span&gt;&lt;span class="pln"&gt; fuelType&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt;$&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;fuelType&lt;/span&gt;&lt;span class="pun"&gt;},&lt;/span&gt;&lt;span class="pln"&gt; productionDate&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;productionDate&lt;/span&gt;&lt;span class="pun"&gt;}`;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; car1 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;CarBuilder&lt;/span&gt;&lt;span class="pun"&gt;().&lt;/span&gt;&lt;span class="pln"&gt;setColor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'yellow'&lt;/span&gt;&lt;span class="pun"&gt;).&lt;/span&gt;&lt;span class="pln"&gt;setFuelType&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'battery'&lt;/span&gt;&lt;span class="pun"&gt;).&lt;/span&gt;&lt;span class="pln"&gt;setProductionDate&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Date&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'2023-06-02'&lt;/span&gt;&lt;span class="pun"&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; car2 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;CarBuilder&lt;/span&gt;&lt;span class="pun"&gt;().&lt;/span&gt;&lt;span class="pln"&gt;setFuelType&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'battery'&lt;/span&gt;&lt;span class="pun"&gt;).&lt;/span&gt;&lt;span class="pln"&gt;setProductionDate&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Date&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'2023-06-03'&lt;/span&gt;&lt;span class="pun"&gt;)).&lt;/span&gt;&lt;span class="pln"&gt;setColor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'blue'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;car1&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;toString&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// car info: color: yellow, fuelType:battery, productionDate: Fri Jun 02 2023 08:00:00 GMT+0800 (中国标准时间)&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;car2&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;toString&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// car info: color: blue, fuelType:battery, productionDate: Sat Jun 03 2023 08:00:00 GMT+0800 (中国标准时间)&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;通过链式调用，在设置不同的属性时更容易识别它们，我们更改调用构造器方法的顺序还可以获得相同的结果。&lt;/p&gt;
&lt;p&gt;以上是通过链式调用实现构造器模式，执行构造器模式的另一种方法是使用抽象类和具体类。&lt;/p&gt;
&lt;p&gt;下面是一个使用抽象类和具体类的建造者模式的示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Car&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;#&lt;/span&gt;&lt;span class="pln"&gt;doors&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  addParts&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;doors &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;4&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  say&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(`&lt;/span&gt;&lt;span class="pln"&gt;I am a $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;doors&lt;/span&gt;&lt;span class="pun"&gt;}-&lt;/span&gt;&lt;span class="pln"&gt;door car&lt;/span&gt;&lt;span class="pun"&gt;`);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Truck&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;#&lt;/span&gt;&lt;span class="pln"&gt;doors&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  addParts&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;doors &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;2&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  say&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(`&lt;/span&gt;&lt;span class="pln"&gt;I am a $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;doors&lt;/span&gt;&lt;span class="pun"&gt;}-&lt;/span&gt;&lt;span class="pln"&gt;door truck&lt;/span&gt;&lt;span class="pun"&gt;`);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;CarBuilder&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;#&lt;/span&gt;&lt;span class="pln"&gt;car&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  step1&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;car &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Car&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  step2&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;car&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addParts&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;get&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;car&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;TruckBuilder&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;#&lt;/span&gt;&lt;span class="pln"&gt;truck&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  step1&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;truck &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Truck&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  step2&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;truck&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addParts&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;get&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.#&lt;/span&gt;&lt;span class="pln"&gt;truck&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Shop&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  construct&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;builder&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    builder&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;step1&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    builder&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;step2&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; builder&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="kwd"&gt;get&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; shop &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Shop&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; carBuilder &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;CarBuilder&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; truckBuilder &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;TruckBuilder&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; car &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; shop&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;construct&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;carBuilder&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; truck &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; shop&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;construct&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;truckBuilder&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;car&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;say&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// I am a 4-door car&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;truck&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;say&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// I am a 2-door truck&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;上面代码中有两个 Builder 类：CarBuilder 和 TruckBuilder，它们有相同的方法，Shop 的 construct 方法接受一个 Builder 实例，然后执行一系列的组装步骤：step1 和 step2。&lt;/p&gt;
&lt;p&gt;所以，可以给 Shop 提供不同的 Builder 来控制实际对象构建过程。&lt;/p&gt;
&lt;h2 id="原型模式（Prototype Pattern）"&gt;原型模式（Prototype Pattern）&lt;/h2&gt;&lt;p&gt;在 JavaScript 中，每个对象都有一个原型（prototype），并且可以通过原型来共享属性和方法。原型设计模式通过复制现有对象的原型来创建新的对象，而不是通过使用类或构造函数来创建。&lt;/p&gt;
&lt;p&gt;下面是一个使用 &lt;code&gt;Object.create()&lt;/code&gt; 方法实现原型模式的示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 原型对象&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; carPrototype &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  color&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'red'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  getColor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(`&lt;/span&gt;&lt;span class="typ"&gt;The&lt;/span&gt;&lt;span class="pln"&gt; car color is $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;color&lt;/span&gt;&lt;span class="pun"&gt;}`);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 创建新对象并继承原型&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; car1 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Object&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;create&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;carPrototype&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;car1&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getColor&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// The car is red&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 自定义新对象的属性和方法&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;car1&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;doors &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;4&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;car1&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getDoors &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(`&lt;/span&gt;&lt;span class="typ"&gt;The&lt;/span&gt;&lt;span class="pln"&gt; car doors is $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;doors&lt;/span&gt;&lt;span class="pun"&gt;}`);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;car1&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getDoors&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// The car doors is 4&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 创建另一个新对象并继承原型&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; car2 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Object&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;create&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;carPrototype&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;car2&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;color &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'black'&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;car2&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getColor&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// The car color is black&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;利用 JavaScript 的原型继承来高效地创建新对象，可以减少内存使用并提高应用程序的性能。&lt;/p&gt;
&lt;h1 id="结构型设计模式"&gt;结构型设计模式&lt;/h1&gt;&lt;h2 id="代理模式（Proxy Pattern）"&gt;代理模式（Proxy Pattern）&lt;/h2&gt;&lt;p&gt;提供一个代理对象来控制对另一个对象的访问，代理对象充当了客户端和实际对象之间的中介，从而可以在访问对象之前或之后执行一些额外的操作。&lt;/p&gt;
&lt;p&gt;下面是一个代理模式的示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;RealSubject&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  request&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'RealSubject: Handing request'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ProxySubject&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;realSubject&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;realSubject &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; realSubject&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  checkAccess&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;true&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  request&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;checkAccess&lt;/span&gt;&lt;span class="pun"&gt;())&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;realSubject&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;request&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; realSubject &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;RealSubject&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; proxy &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ProxySubject&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;realSubject&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;proxy&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;request&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// RealSubject: Handing request&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;使用 ES6 的 &lt;code&gt;Proxy&lt;/code&gt; 示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; person &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code&gt;&lt;span class="pln"&gt;  name&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'John Doe'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code&gt;&lt;span class="pln"&gt;  age&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;42&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code&gt;&lt;span class="pln"&gt;  nationality&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'American'&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code&gt;&lt;span class="pun"&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; personProxy &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Proxy&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;person&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;get&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;target&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; prop&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;`The value of ${prop} is ${Reflect.get(target, prop)}`&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;},&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;set&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;target&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; prop&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; value&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;`Changed ${prop} from ${target[prop]} to ${value}`&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Reflect&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="kwd"&gt;set&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;target&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; prop&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; value&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code&gt;&lt;span class="pun"&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code&gt;&lt;span class="pln"&gt;personProxy&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;name&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// The value of name is John Doe&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code&gt;&lt;span class="pln"&gt;personProxy&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;age &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;43&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// Changed age from 42 to 43&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code&gt;&lt;span class="pln"&gt;personProxy&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;name &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'Jane Doe'&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// Changed name from John Doe to Jane Doe&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;&lt;p&gt;通过使用 ES6 的 &lt;code&gt;Proxy&lt;/code&gt; 对象，我们可以在代理对象上拦截和处理对目标对象的操作。这种方式提供了更灵活的控制和操作对象的能力，并可以用于实现许多不同的代理行为，如数据验证、缓存、日志记录等。&lt;/p&gt;
&lt;h2 id="装饰者模式（Decorator Pattern）"&gt;装饰者模式（Decorator Pattern）&lt;/h2&gt;&lt;p&gt;在不修改现有对象的情况下，动态地将新功能附加到对象上。通过创建一个装饰者对象，将新功能逐层地包装在原始对象周围，从而扩展其功能。这种方式可以在运行时动态地添加、修改或删除对象的行为。&lt;/p&gt;
&lt;p&gt;下面是一个装饰者模式示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 抽象组件&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Coffee&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  getCost&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;10&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  getDescription&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'Coffee'&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 具体组件&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Espresso&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;Coffee&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  getCost&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;15&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  getDescription&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'Espresso'&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 抽象装饰者&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;CoffeeDecorator&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;Coffee&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;coffee&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    super&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;coffee &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; coffee&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  getCost&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;coffee&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getCost&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  getDescription&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;coffee&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getDescription&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 具体装饰者&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;MilkDecorator&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;CoffeeDecorator&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;coffee&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    super&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;coffee&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  getCost&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;coffee&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getCost&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;+&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;5&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  getDescription&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;`&lt;/span&gt;&lt;span class="pln"&gt;$&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;coffee&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getDescription&lt;/span&gt;&lt;span class="pun"&gt;()},&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Milk&lt;/span&gt;&lt;span class="pun"&gt;`;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 具体装饰者&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SugarDecorator&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;CoffeeDecorator&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;coffee&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    super&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;coffee&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  getCost&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;coffee&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getCost&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;+&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;2&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  getDescription&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;`&lt;/span&gt;&lt;span class="pln"&gt;$&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;coffee&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getDescription&lt;/span&gt;&lt;span class="pun"&gt;()},&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Sugar&lt;/span&gt;&lt;span class="pun"&gt;`;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; coffee &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Espresso&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; coffeeWithMilk &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;MilkDecorator&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;coffee&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; coffeeWithMilkAndSugar &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SugarDecorator&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;coffeeWithMilk&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;coffee&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getCost&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: 15&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;coffee&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getDescription&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: Espresso&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;coffeeWithMilk&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getCost&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: 20&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;coffeeWithMilk&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getDescription&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: Espresso, Milk&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;coffeeWithMilkAndSugar&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getCost&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: 22&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;coffeeWithMilkAndSugar&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getDescription&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: Espresso, Milk, Sugar&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上述示例中，我们有一个抽象组件 Coffee，它定义了咖啡的基本功能。然后，我们创建了具体组件 Espresso，它是一种具体类型的咖啡。&lt;/p&gt;
&lt;p&gt;接下来，我们定义了一个抽象装饰者 CoffeeDecorator，它继承自抽象组件，并持有一个抽象组件的引用。然后，我们创建了两个具体装饰者 MilkDecorator 和 SugarDecorator，它们分别在咖啡上添加了牛奶和糖的额外功能。&lt;/p&gt;
&lt;p&gt;我们首先创建了一个具体组件的实例 coffee，然后使用装饰者 MilkDecorator 和 SugarDecorator 逐层包装这个具体组件。最后，我们可以通过调用装饰后的对象的方法来获取添加了额外功能的咖啡的成本和描述信息。&lt;/p&gt;
&lt;p&gt;装饰者模式的优势在于它提供了一种灵活的方式来扩展对象的功能,通过组合不同的装饰者，可以动态地添加或移除对象的功能，同时保持代码的可维护性和可扩展性。&lt;/p&gt;
&lt;h2 id="适配器模式（Adapter Pattern）"&gt;适配器模式（Adapter Pattern）&lt;/h2&gt;&lt;p&gt;允许将一个类的接口转换为另一个接口，以满足客户端的需求。适配器模式使得原本不兼容的接口能够一起工作。&lt;/p&gt;
&lt;p&gt;适配器模式可以用于以下情况：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;当我们使用一个已有的对象或类时，发现它的接口与我们的需求不匹配，无法直接使用。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;当我们希望复用已有的对象或类，但其接口与我们的系统要求的接口不一致。&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;下面是一个关于充电器的适配器模式示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 目标接口&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Charger&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  connect&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;throw&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Error&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;"Method 'connect' must be implemented."&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  charge&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;throw&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Error&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;"Method 'charge' must be implemented."&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 原始类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;OldCharger&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  plugIn&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Plugging in old charger.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  electricCharge&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Charging with old charger.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 适配器类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ChargerAdapter&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;Charger&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;oldCharger&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    super&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;oldCharger &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; oldCharger&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  connect&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;oldCharger&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;plugIn&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  charge&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;oldCharger&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;electricCharge&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 客户端代码&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; chargeDevice&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;charger&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  charger&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;connect&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  charger&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;charge&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; oldCharger &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;OldCharger&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; chargerAdapter &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ChargerAdapter&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;oldCharger&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;chargeDevice&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;chargerAdapter&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 输出:&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Plugging in old charger.&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Charging with old charger.&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上述示例中，我们定义了一个目标接口 Charger，其中包含了两个抽象方法 connect 和 charge。&lt;/p&gt;
&lt;p&gt;然后，我们创建了一个原始类 OldCharger，它具有两个方法 plugIn 和 electricCharge，但它的接口与目标接口不匹配。&lt;/p&gt;
&lt;p&gt;接下来，我们实现了适配器类 ChargerAdapter，它继承自目标接口 Charger，并持有一个原始类的引用。在适配器类中，我们实现了目标接口的方法 connect 和 charge，并在方法中调用原始类的方法进行充电操作。&lt;/p&gt;
&lt;p&gt;最后，我们在客户端代码中，创建了原始类的实例 oldCharger，并将其传递给适配器类的构造函数来创建适配器实例 chargerAdapter。通过调用适配器的方法 connect 和 charge，实际上会调用原始类的方法 plugIn 和 electricCharge，从而实现了接口的适配。&lt;/p&gt;
&lt;h2 id="桥接模式（Bridge Pattern）"&gt;桥接模式（Bridge Pattern）&lt;/h2&gt;&lt;p&gt;将抽象部分与实现部分分离，使它们可以独立变化。桥接模式的关键思想是将一个大类或多个紧密关联的类分为两个独立的层次结构，从而降低它们之间的耦合性。&lt;/p&gt;
&lt;p&gt;桥接模式可以用于以下情况：&lt;/p&gt;
&lt;p&gt;当一个类存在多个变化维度时，可以通过桥接模式将这些维度分离，使得它们可以独立变化。&lt;/p&gt;
&lt;p&gt;当需要在抽象部分和实现部分之间建立一个稳定的连接，以便能够动态地切换和扩展它们。&lt;/p&gt;
&lt;p&gt;下面是一个桥接模式的示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="com"&gt;// 抽象部分&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="kwd"&gt;abstract&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Shape&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;protected&lt;/span&gt;&lt;span class="pln"&gt; color&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Color&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-typescript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;color&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Color&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;color &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; color&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-typescript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;abstract&lt;/span&gt;&lt;span class="pln"&gt; draw&lt;/span&gt;&lt;span class="pun"&gt;():&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;string&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-typescript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="com"&gt;// 实现部分&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="kwd"&gt;interface&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Color&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;  fill&lt;/span&gt;&lt;span class="pun"&gt;():&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;string&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-typescript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="com"&gt;// 具体实现部分&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;RedColor&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;implements&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Color&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;  fill&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;"red"&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-typescript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;BlueColor&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;implements&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Color&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;  fill&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;"blue"&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-typescript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="com"&gt;// 具体抽象部分&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Circle&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;extends&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Shape&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;color&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Color&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;super&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;color&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-typescript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;  draw&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;`Drawing a ${this.color.fill()} circle.`&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-typescript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Square&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;extends&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Shape&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;color&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Color&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;super&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;color&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-typescript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;  draw&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;`Drawing a ${this.color.fill()} square.`&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-typescript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="com"&gt;// 客户端代码&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; redColor&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Color&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;RedColor&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; blueColor&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Color&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;BlueColor&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-typescript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; redCircle&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Shape&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Circle&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;redColor&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; blueSquare&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Shape&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Square&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;blueColor&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-typescript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;redCircle&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;draw&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: Drawing a red circle.&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-typescript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;blueSquare&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;draw&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: Drawing a blue square.&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上述示例中，我们定义了两个独立的层次结构：抽象部分（Shape）和实现部分（Color）。&lt;/p&gt;
&lt;p&gt;抽象部分包含一个抽象方法 draw，并持有一个实现部分的引用（color）。&lt;/p&gt;
&lt;p&gt;实现部分包含一个抽象方法 fill，用于表示不同的颜色。&lt;/p&gt;
&lt;p&gt;然后，我们创建了两个具体的实现部分类：RedColor 和 BlueColor，它们分别实现了颜色的填充方法。&lt;/p&gt;
&lt;p&gt;接下来，我们创建了两个具体的抽象部分类：Circle 和 Square，它们继承自抽象部分 Shape。这些具体的抽象部分类在绘制时会调用实现部分的方法来获取填充的颜色。&lt;/p&gt;
&lt;p&gt;最后，我们在客户端代码中，创建了具体实现部分的实例（redColor 和 blueColor），并将其传递给具体抽象部分类的构造函数来创建具体抽象部分的实例（redCircle 和 blueSquare）。通过调用具体抽象部分的 draw 方法，实际上会调用实现部分的 fill 方法，从而实现了抽象部分和实现部分的桥接。&lt;/p&gt;
&lt;p&gt;这个示例展示了桥接模式的一种用法，通过将形状和颜色分离，我们可以在两个维度上独立地扩展它们，而不需要修改现有的代码。这种分离使得我们可以根据需要动态地选择不同的颜色来绘制不同的形状，同时保持代码的可扩展性和灵活性。&lt;/p&gt;
&lt;h2 id="外观模式（Facade Pattetn）"&gt;外观模式（Facade Pattetn）&lt;/h2&gt;&lt;p&gt;提供了一个统一的接口，用于访问复杂子系统中的一组接口。外观模式通过隐藏底层系统的复杂性，简化了客户端与子系统之间的交互，并提供了一个简单而统一的接口。&lt;/p&gt;
&lt;p&gt;外观模式可以用于以下情况：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;当一个系统或库有多个复杂的子组件，并且希望提供一个简化的接口供客户端使用时。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;当需要对底层系统进行解耦，使得客户端不需要了解和直接操作底层组件。&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;下面是一个外观模式的示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 子系统A&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SubsystemA&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  operationA&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'Subsystem A operation'&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 子系统B&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SubsystemB&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  operationB&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'Subsystem B operation'&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 子系统C&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SubsystemC&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  operationC&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'Subsystem C operation'&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 外观类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Facade&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;subsystemA &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SubsystemA&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;subsystemB &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SubsystemB&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;subsystemC &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SubsystemC&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  operation&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; resultA &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;subsystemA&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;operationA&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; resultB &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;subsystemB&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;operationB&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; resultC &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;subsystemC&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;operationC&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;`&lt;/span&gt;&lt;span class="pln"&gt;$&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;resultA&lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;span class="pln"&gt;\n$&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;resultB&lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;span class="pln"&gt;\n$&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;resultC&lt;/span&gt;&lt;span class="pun"&gt;}`;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 客户端代码&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; facade &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Facade&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; result &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; facade&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;operation&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;result&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 输出:&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Subsystem A operation&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Subsystem B operation&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Subsystem C operation&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上述示例中，我们有三个子系统：SubsystemA、SubsystemB 和 SubsystemC。每个子系统都有自己的一些操作。&lt;/p&gt;
&lt;p&gt;然后，我们定义了一个外观类 Facade，它持有子系统的实例，并提供了一个操作方法 operation。在该方法中，我们调用了子系统的操作，并返回它们的结果。&lt;/p&gt;
&lt;p&gt;最后，我们在客户端代码中创建了外观类的实例 facade，并调用了它的 operation 方法。通过外观类，客户端可以使用简单的接口来访问底层复杂子系统的功能，而无需直接与子系统进行交互。&lt;/p&gt;
&lt;p&gt;外观模式的优点在于简化了客户端的调用过程，封装了底层复杂性，并提供了一个高层次的接口。这样一来，客户端只需与外观类进行交互，而无需了解底层子系统的细节，从而提高了代码的可读性和可维护性。&lt;/p&gt;
&lt;h2 id="组合模式（Composite Pattern）"&gt;组合模式（Composite Pattern）&lt;/h2&gt;&lt;p&gt;将对象组织成树形结构，并且能够以相同的方式处理单个对象和组合对象。组合模式允许客户端使用统一的方式处理对象的层次结构，而无需关心对象是单个对象还是组合对象。&lt;/p&gt;
&lt;p&gt;组合模式可以用于以下情况：&lt;/p&gt;
&lt;p&gt;当有一个对象树结构，且希望以统一的方式处理树中的所有对象。&lt;/p&gt;
&lt;p&gt;当希望客户端能够一致地对待单个对象和组合对象，而不需要进行特殊处理。&lt;/p&gt;
&lt;p&gt;下面是一个组合模式的示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 定义 ItemNode 类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ItemNode&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;name&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;children &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;[];&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 存储子节点的数组&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;name &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; name&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 节点名称&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// 添加子节点&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  add&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;child&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;children&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;push&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;child&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// 移除子节点&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  remove&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;child&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; index &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;children&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;indexOf&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;child&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;index &lt;/span&gt;&lt;span class="pun"&gt;!==&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="lit"&gt;1&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;children&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;splice&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;index&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;1&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// 获取指定索引的子节点&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  getChild&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;i&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;children&lt;/span&gt;&lt;span class="pun"&gt;[&lt;/span&gt;&lt;span class="pln"&gt;i&lt;/span&gt;&lt;span class="pun"&gt;];&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// 检查节点是否有子节点&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  hasChildren&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;children&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;length &lt;/span&gt;&lt;span class="pun"&gt;&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;0&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 递归遍历树节点&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; traverse&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;indent&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; node&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="typ"&gt;Array&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;indent&lt;/span&gt;&lt;span class="pun"&gt;).&lt;/span&gt;&lt;span class="pln"&gt;join&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'--'&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;+&lt;/span&gt;&lt;span class="pln"&gt; node&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;name&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 打印节点名称，根据缩进级别输出层次结构&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;for&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;let i &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;0&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; len &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; node&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;children&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;length&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;span class="pln"&gt; i &lt;/span&gt;&lt;span class="pun"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pln"&gt; len&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;span class="pln"&gt; i&lt;/span&gt;&lt;span class="pun"&gt;++)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    traverse&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;indent &lt;/span&gt;&lt;span class="pun"&gt;+&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;1&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; node&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getChild&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;i&lt;/span&gt;&lt;span class="pun"&gt;));&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 递归遍历子节点&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 创建树结构并执行遍历&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; run&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; tree &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ItemNode&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'root'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; left &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ItemNode&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'left'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; right &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ItemNode&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'right'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; leftleft &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ItemNode&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'leftleft'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; leftright &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ItemNode&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'leftright'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; rightleft &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ItemNode&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'rightleft'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; rightright &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ItemNode&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'rightright'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  tree&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;add&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;left&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  tree&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;add&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;right&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  tree&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;remove&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;right&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 移除并重新添加 right 节点&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  tree&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;add&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;right&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  left&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;add&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;leftleft&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  left&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;add&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;leftright&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  right&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;add&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;rightleft&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  right&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;add&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;rightright&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  traverse&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="lit"&gt;1&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; tree&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 从根节点开始遍历树&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;run&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 输出&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// root&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// --left&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// ----leftleft&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// ----leftright&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// --right&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// ----rightleft&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// ----rightright&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上述示例中，定义了一个名为 ItemNode 的类，用于表示树节点。每个节点具有一个名称和一个存储子节点的数组。&lt;/p&gt;
&lt;p&gt;然后，ItemNode 类提供了几个方法来操作节点。add 方法用于向节点添加子节点，remove 方法用于移除指定的子节点。getChild 方法用于获取指定索引位置的子节点，hasChildren 方法用于检查节点是否具有子节点。&lt;/p&gt;
&lt;p&gt;最后，还有一个 traverse 函数，用于递归遍历树节点并打印节点名称。该函数接受两个参数，缩进级别和当前节点，通过递归调用 traverse 函数来遍历子节点。&lt;/p&gt;
&lt;p&gt;在 run 函数中，创建了一个根节点 tree，以及其他节点。通过调用 add 方法，构建了一个树结构。最后，调用 traverse 函数，从根节点开始遍历并输出每个节点的名称和层次结构。&lt;/p&gt;
&lt;p&gt;这段代码展示了组合模式的应用，通过使用递归结构来管理复杂的树状数据，并提供了一种便捷的方式来操作和遍历树节点。&lt;/p&gt;
&lt;h2 id="享元模式（Flyweight Pattern）"&gt;享元模式（Flyweight Pattern）&lt;/h2&gt;&lt;p&gt;用于通过共享对象以减少内存消耗和提高性能。它通过将对象的状态分为内部状态（Intrinsic State）和外部状态（Extrinsic State），并共享内部状态来实现对象的共享。&lt;/p&gt;
&lt;p&gt;内部状态是对象的不变部分，可以被多个对象共享，而外部状态是对象的可变部分，需要在运行时通过参数传递给对象。享元模式的目标是通过共享尽可能多的内部状态来减少对象的数量。&lt;/p&gt;
&lt;p&gt;下面是一个享元模式示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 定义享元对象&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Flyweight&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;key&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;key &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; key&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  operation&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;extrinsicState&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(`&lt;/span&gt;&lt;span class="typ"&gt;Flyweight&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;key&lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;span class="pln"&gt; operation &lt;/span&gt;&lt;span class="kwd"&gt;with&lt;/span&gt;&lt;span class="pln"&gt; extrinsic state&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;extrinsicState&lt;/span&gt;&lt;span class="pun"&gt;}`);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 具体享元对象&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ConcreteFlyweight&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;Flyweight&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;key&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    super&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;key&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 创建享元工厂&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;FlyweightFactory&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;flyweights &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{};&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  getFlyweight&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;key&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(!&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;flyweights&lt;/span&gt;&lt;span class="pun"&gt;[&lt;/span&gt;&lt;span class="pln"&gt;key&lt;/span&gt;&lt;span class="pun"&gt;])&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;flyweights&lt;/span&gt;&lt;span class="pun"&gt;[&lt;/span&gt;&lt;span class="pln"&gt;key&lt;/span&gt;&lt;span class="pun"&gt;]&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ConcreteFlyweight&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;key&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;flyweights&lt;/span&gt;&lt;span class="pun"&gt;[&lt;/span&gt;&lt;span class="pln"&gt;key&lt;/span&gt;&lt;span class="pun"&gt;];&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  getFlyweightsCount&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Object&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;keys&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;flyweights&lt;/span&gt;&lt;span class="pun"&gt;).&lt;/span&gt;&lt;span class="pln"&gt;length&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 客户端代码&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; factory &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;FlyweightFactory&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; flyweight1 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; factory&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getFlyweight&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'key1'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;flyweight1&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;operation&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'state1'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; flyweight2 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; factory&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getFlyweight&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'key2'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;flyweight2&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;operation&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'state2'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; flyweight3 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; factory&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getFlyweight&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'key1'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;flyweight3&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;operation&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'state3'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(`&lt;/span&gt;&lt;span class="typ"&gt;Total&lt;/span&gt;&lt;span class="pln"&gt; flyweights&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;factory&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getFlyweightsCount&lt;/span&gt;&lt;span class="pun"&gt;()}`);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 输出&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Flyweight key1 operation with extrinsic state: state1&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Flyweight key2 operation with extrinsic state: state2&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Flyweight key1 operation with extrinsic state: state3&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Total flyweights: 2&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上面的代码中，Flyweight 是享元对象的抽象类，定义了共享对象的接口。operation 方法是享元对象的操作方法，接受外部状态作为参数。&lt;/p&gt;
&lt;p&gt;FlyweightFactory 充当享元工厂，负责创建和管理享元对象。getFlyweight 方法用于获取享元对象，如果对象不存在则创建一个新的享元对象并将其存储在工厂中。getFlyweightsCount 方法用于获取当前创建的享元对象数量。&lt;/p&gt;
&lt;p&gt;ConcreteFlyweight 是具体的享元对象类，实现了抽象享元对象的接口。&lt;/p&gt;
&lt;p&gt;在客户端代码中，通过享元工厂创建了几个享元对象，并调用它们的 operation 方法来执行操作。注意到对于相同的内部状态（例如，’key1’），只会创建一个享元对象，其他对象将共享同一个实例。最后，通过 getFlyweightsCount 方法获取创建的享元对象数量。&lt;/p&gt;
&lt;p&gt;享元模式的核心思想是共享对象以节省内存和提高性能。它适用于需要大量相似对象的场景，通过共享内部状态来减少对象数量，从而节省系统资源。&lt;/p&gt;
&lt;h1 id="行为型设计模式"&gt;行为型设计模式&lt;/h1&gt;&lt;h2 id="观察者模式（Observer Pattern）"&gt;观察者模式（Observer Pattern）&lt;/h2&gt;&lt;p&gt;用于在对象之间定义一对多的依赖关系，当一个对象状态发生变化时，所有依赖它的对象都会收到通知并自动更新。&lt;/p&gt;
&lt;p&gt;下面是一个观察者模式示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 主题&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Subject&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;observers &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;[];&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// 添加观察者&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  addObserver&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;observer&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;observers&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;push&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;observer&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// 删除观察者&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  removeObserver&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;observer&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; index &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;observers&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;indexOf&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;observer&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;index &lt;/span&gt;&lt;span class="pun"&gt;!==&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="lit"&gt;1&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;observers&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;splice&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;index&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;1&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// 通知观察者&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  notify&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;for&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;let i &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;0&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;span class="pln"&gt; i &lt;/span&gt;&lt;span class="pun"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;observers&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;length&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;span class="pln"&gt; i&lt;/span&gt;&lt;span class="pun"&gt;++)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;observers&lt;/span&gt;&lt;span class="pun"&gt;[&lt;/span&gt;&lt;span class="pln"&gt;i&lt;/span&gt;&lt;span class="pun"&gt;].&lt;/span&gt;&lt;span class="pln"&gt;update&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 观察者&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Observer&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;name&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;name &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; name&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// 更新方法&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  update&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(`&lt;/span&gt;&lt;span class="typ"&gt;Observer&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;name&lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;span class="pln"&gt; received notification&lt;/span&gt;&lt;span class="pun"&gt;.`);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 客户端代码&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; subject &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Subject&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; observer1 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Observer&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Observer 1'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; observer2 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Observer&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Observer 2'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; observer3 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Observer&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Observer 3'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;subject&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addObserver&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;observer1&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;subject&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addObserver&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;observer2&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;subject&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addObserver&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;observer3&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;subject&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;notify&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Observer Observer 1 received notification.&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Observer Observer 2 received notification.&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Observer Observer 3 received notification.&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上面的代码中，Subject 是主题类，维护了一个观察者数组，并提供了添加观察者、删除观察者和通知观察者的方法。&lt;/p&gt;
&lt;p&gt;Observer 是观察者类，每个观察者具有一个名称，并实现了 update 方法来处理接收到的通知。&lt;/p&gt;
&lt;p&gt;在客户端代码中，我们创建了一个主题对象 subject，以及三个观察者对象 observer1、observer2 和 observer3。通过调用 addObserver 方法将观察者注册到主题中，然后调用 notify 方法来通知所有观察者。&lt;/p&gt;
&lt;p&gt;观察者模式非常有用，特别适用于对象之间存在一对多的依赖关系的情况。它提供了一种松耦合的方式，让主题和观察者之间的关系灵活，并且使得对象之间的通信更加简单和可维护。&lt;/p&gt;
&lt;h2 id="模版模式（Template Pattern）"&gt;模版模式（Template Pattern）&lt;/h2&gt;&lt;p&gt;用于定义算法的骨架，将一些步骤的具体实现延迟到子类中。模板模式通过定义一个模板方法，该方法定义了算法的结构，而具体的实现细节由子类来实现。&lt;/p&gt;
&lt;p&gt;模板模式的核心思想是通过将通用的算法流程定义在父类中，将具体实现交给子类。这样可以在不改变算法结构的情况下，通过不同的子类来定制具体的步骤实现。&lt;/p&gt;
&lt;p&gt;下面是一个模板模式示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 抽象模板类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Template&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  templateMethod&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;step1&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;step2&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;step3&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  step1&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;throw&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Error&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Abstract method step1() must be overridden.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  step2&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;throw&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Error&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Abstract method step2() must be overridden.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  step3&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;throw&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Error&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Abstract method step3() must be overridden.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 具体模板类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ConcreteClass&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;Template&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  step1&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'ConcreteClass: Step 1'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  step2&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'ConcreteClass: Step 2'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  step3&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'ConcreteClass: Step 3'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 客户端代码&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; concreteClass &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ConcreteClass&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;concreteClass&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;templateMethod&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// ConcreteClass: Step 1&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// ConcreteClass: Step 2&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// ConcreteClass: Step 3&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上面的代码中，Template 是抽象模板类，它定义了模板方法 templateMethod，该方法定义了算法的结构，包含了一系列的步骤。每个步骤都是抽象方法，由子类来实现具体的细节。&lt;/p&gt;
&lt;p&gt;ConcreteClass 是具体模板类，继承自抽象模板类 AbstractClass。它实现了抽象模板类中的抽象方法，并提供了具体的步骤实现。&lt;/p&gt;
&lt;p&gt;在客户端代码中，我们创建了一个具体模板类的实例 concreteClass，然后调用它的 templateMethod 方法来执行算法。由于模板方法已经定义了算法的结构，具体步骤的实现会被自动调用。&lt;/p&gt;
&lt;p&gt;模板模式的优势在于它提供了一种统一的算法结构，并且能够在不修改模板方法的情况下，通过子类来定制具体的步骤实现。这种设计模式在许多情况下都能简化代码，提高代码的可维护性和扩展性，特别适用于需要共享算法结构但具体实现略有不同的场景。&lt;/p&gt;
&lt;h2 id="策略模式（Strategy Pattern）"&gt;策略模式（Strategy Pattern）&lt;/h2&gt;&lt;p&gt;用于将一组可互换的算法封装成独立的对象，并使它们能够在运行时动态地切换。策略模式将算法的选择与算法的实现分离，使得它们可以独立变化，从而提供了更好的灵活性和可维护性。&lt;/p&gt;
&lt;p&gt;下面是一个使用对象实现策略模式的示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 定义策略对象&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; strategies &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  add&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;a&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; b&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; a &lt;/span&gt;&lt;span class="pun"&gt;+&lt;/span&gt;&lt;span class="pln"&gt; b&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;},&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  subtract&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;a&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; b&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; a &lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="pln"&gt; b&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;},&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  multiply&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;a&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; b&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; a &lt;/span&gt;&lt;span class="pun"&gt;*&lt;/span&gt;&lt;span class="pln"&gt; b&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 定义环境对象&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Context&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;strategy&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;strategy &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; strategy&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  setStrategy&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;strategy&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;strategy &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; strategy&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  executeStrategy&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;a&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; b&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;strategy&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;a&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; b&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 使用示例&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; context &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Context&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;strategies&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;add&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;context&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;executeStrategy&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="lit"&gt;5&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;3&lt;/span&gt;&lt;span class="pun"&gt;));&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: 8&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;context&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;setStrategy&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;strategies&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;subtract&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;context&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;executeStrategy&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="lit"&gt;5&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;3&lt;/span&gt;&lt;span class="pun"&gt;));&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: 2&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;context&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;setStrategy&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;strategies&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;multiply&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;context&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;executeStrategy&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="lit"&gt;5&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;3&lt;/span&gt;&lt;span class="pun"&gt;));&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: 15&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上面的代码中，我们定义了一个策略对象 strategies，其中包含了三种算法：add、subtract 和 multiply。每个算法都是一个函数，接收两个参数并返回计算结果。&lt;/p&gt;
&lt;p&gt;然后，我们定义了一个环境对象 Context，它接收一个策略作为参数，并通过 executeStrategy 方法来执行算法。setStrategy 方法用于在运行时切换策略。&lt;/p&gt;
&lt;p&gt;最后，我们创建了一个 Context 实例，并初始时将 strategies.add 作为策略。然后通过 executeStrategy 方法来执行算法，输出结果。&lt;/p&gt;
&lt;p&gt;通过策略模式，我们可以根据不同的需求和条件选择不同的算法来解决问题，而无需修改使用算法的代码。这样可以增强代码的灵活性和可维护性，并将算法的选择与具体的实现分离开来。&lt;/p&gt;
&lt;h2 id="职责链模式（Chain of Responsibility Pattern）"&gt;职责链模式（Chain of Responsibility Pattern）&lt;/h2&gt;&lt;p&gt;允许将请求从一个处理者传递到另一个处理者，直到请求被处理或达到链的末尾。职责链模式解耦了发送者和接收者之间的关系，并允许多个对象都有机会处理请求，将请求的发送和处理解耦，提高了代码的灵活性和可扩展性。&lt;/p&gt;
&lt;p&gt;下面是一个使用对象实现职责链模式的示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 定义处理者对象&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Handler&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;nextHandler &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;null&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  setNextHandler&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;handler&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;nextHandler &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; handler&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  handleRequest&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;request&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;canHandleRequest&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;request&lt;/span&gt;&lt;span class="pun"&gt;))&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;processRequest&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;request&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;else&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;nextHandler&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;nextHandler&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;handleRequest&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;request&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;else&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'No handler found for the request.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  canHandleRequest&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;request&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;throw&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Error&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Abstract method canHandleRequest() must be overridden.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  processRequest&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;request&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;throw&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Error&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Abstract method processRequest() must be overridden.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 具体处理者对象&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ConcreteHandler1&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;Handler&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  canHandleRequest&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;request&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; request &lt;/span&gt;&lt;span class="pun"&gt;===&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'type1'&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  processRequest&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;request&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'ConcreteHandler1 is handling the request.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ConcreteHandler2&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;Handler&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  canHandleRequest&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;request&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; request &lt;/span&gt;&lt;span class="pun"&gt;===&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'type2'&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  processRequest&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;request&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'ConcreteHandler2 is handling the request.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 使用示例&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; handler1 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ConcreteHandler1&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; handler2 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ConcreteHandler2&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;handler1&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;setNextHandler&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;handler2&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;handler1&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;handleRequest&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'type1'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: ConcreteHandler1 is handling the request.&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;handler1&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;handleRequest&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'type2'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: ConcreteHandler2 is handling the request.&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;handler1&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;handleRequest&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'type3'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: No handler found for the request.&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上面的代码中，我们定义了一个处理者对象 Handler，它包含了一个指向下一个处理者的引用 nextHandler，以及处理请求的方法 handleRequest。canHandleRequest 方法用于判断处理者是否能够处理特定的请求，processRequest 方法用于处理请求的具体逻辑。&lt;/p&gt;
&lt;p&gt;然后，我们定义了两个具体的处理者对象 ConcreteHandler1 和 ConcreteHandler2，它们分别实现了 canHandleRequest 和 processRequest 方法来处理不同类型的请求。&lt;/p&gt;
&lt;p&gt;在使用示例中，我们创建了一个 ConcreteHandler1 实例和一个 ConcreteHandler2 实例，并通过 setNextHandler 方法将它们链接在一起形成职责链。然后，我们调用 handleRequest 方法，并传入不同的请求类型，看看每个处理者是否能够处理该请求。&lt;/p&gt;
&lt;p&gt;通过职责链模式，我们可以将请求发送方与接收方解耦，并允许多个对象都有机会处理请求。这样可以动态地组织和拓展处理流程，提高代码的灵活性和可维护性。&lt;/p&gt;
&lt;h2 id="迭代器模式（Interator Pattern）"&gt;迭代器模式（Interator Pattern）&lt;/h2&gt;&lt;p&gt;用于提供一种统一的方式来遍历集合对象的元素，而不暴露集合对象的内部结构。迭代器模式将遍历操作封装在一个独立的迭代器对象中，使得客户端可以通过迭代器对象逐个访问集合中的元素，而不需要关注底层集合的实现细节。&lt;/p&gt;
&lt;p&gt;在 JavaScript 中，迭代器模式通常通过使用迭代器对象来实现。迭代器对象提供了一组标准的方法，如 next、hasNext 等，用于遍历集合并获取元素。&lt;/p&gt;
&lt;p&gt;下面是一个迭代器模式的示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Iterator&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;collection&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;collection &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; collection&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;index &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;0&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  next&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;collection&lt;/span&gt;&lt;span class="pun"&gt;[&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;index&lt;/span&gt;&lt;span class="pun"&gt;++];&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  hasNext&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;index &lt;/span&gt;&lt;span class="pun"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;collection&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;length&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 使用示例&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; names &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;[&lt;/span&gt;&lt;span class="str"&gt;'Alice'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'Bob'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'Charlie'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'Dave'&lt;/span&gt;&lt;span class="pun"&gt;];&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; iterator &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Iterator&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;names&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;while&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;iterator&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;hasNext&lt;/span&gt;&lt;span class="pun"&gt;())&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;iterator&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;next&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 输出：&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Alice&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Bob&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Charlie&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Dave&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上面的示例中，我们定义了一个 Iterator 类作为迭代器对象。该类接收一个集合对象作为参数，并在构造函数中初始化了当前索引 index。&lt;/p&gt;
&lt;p&gt;迭代器对象提供了两个方法：next 方法用于获取集合中的下一个元素，hasNext 方法用于检查是否还有下一个元素。&lt;/p&gt;
&lt;p&gt;在使用示例中，我们创建了一个名为 names 的字符串数组，并创建了一个迭代器对象 iterator，将该数组传递给迭代器的构造函数。&lt;/p&gt;
&lt;p&gt;然后，我们使用 while 循环和迭代器的 hasNext 方法来遍历集合，并使用 next 方法逐个获取集合中的元素，并将其打印出来。&lt;/p&gt;
&lt;p&gt;迭代器模式使得集合对象和迭代逻辑的实现分离，提供了一种统一的方式来遍历集合。它增强了代码的可读性和可维护性，并允许在不改变集合结构的情况下，通过修改迭代器对象来改变遍历行为。&lt;/p&gt;
&lt;h2 id="状态模式（State Pattern）"&gt;状态模式（State Pattern）&lt;/h2&gt;&lt;p&gt;用于根据对象的内部状态改变其行为。状态模式将对象的行为封装在不同的状态类中，并使用一个上下文对象来管理状态的切换。&lt;/p&gt;
&lt;p&gt;在 JavaScript 中，状态模式通常使用对象和多态性来实现。&lt;/p&gt;
&lt;p&gt;下面是一个订单状态模式的示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 抽象订单状态类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;OrderState&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;order&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;order &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; order&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  pay&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;throw&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Error&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'pay() must be implemented.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  ship&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;throw&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Error&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'ship() must be implemented.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  complete&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;throw&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Error&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'complete() must be implemented.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;CompletedState&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;OrderState&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// 可以不实现任何方法，表示订单已完成且没有更改的操作&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ShippedState&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;OrderState&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  complete&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Order is completed.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;order&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;setState&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;CompletedState&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;order&lt;/span&gt;&lt;span class="pun"&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;PaidState&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;OrderState&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  ship&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Order is shipped.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;order&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;setState&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ShippedState&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;order&lt;/span&gt;&lt;span class="pun"&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 具体订单状态类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;PendingPaymentState&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;OrderState&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  pay&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Payment received. Order is now paid.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;order&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;setState&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;PaidState&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;order&lt;/span&gt;&lt;span class="pun"&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 订单类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Order&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;state &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;PendingPaymentState&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  setState&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;state&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;state &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; state&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  pay&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;state&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;pay&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  ship&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;state&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;ship&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  complete&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;state&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;complete&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 使用示例&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; order &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Order&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;order&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;pay&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: Payment received. Order is now paid.&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;order&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;ship&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: Order is shipped.&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;order&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;complete&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: Order is completed.&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上面的示例中，我们模拟了一个订单管理系统，订单类 Order 包含了状态对象，并提供了支付（pay）、发货（ship）和完成（complete）等方法，这些方法会委托给当前状态对象进行处理。&lt;/p&gt;
&lt;p&gt;我们定义了抽象的订单状态类 OrderState，其中包含了共同的方法。然后，我们创建了具体的订单状态类，如待支付状态（PendingPaymentState）、已支付状态（PaidState）、已发货状态（ShippedState）和已完成状态（CompletedState），它们分别继承自抽象状态类并实现了相应的行为。&lt;/p&gt;
&lt;p&gt;在使用示例中，我们创建了一个订单对象 order，初始状态为待支付。然后依次调用支付、发货和完成方法，订单对象会委托给当前状态对象进行处理，并根据当前状态执行相应的行为。&lt;/p&gt;
&lt;p&gt;这个示例展示了状态模式在订单管理系统中的应用。通过状态模式，可以根据订单的不同状态，实现不同的行为，并且可以灵活地添加新的状态和相关行为，而不需要修改订单类的代码。这提供了更好的可维护性、可扩展性和灵活性，同时避免了大量的条件语句和代码重复。&lt;/p&gt;
&lt;h2 id="访问者模式（Visitor Pattern）"&gt;访问者模式（Visitor Pattern）&lt;/h2&gt;&lt;p&gt;用于将数据结构与其上的操作解耦，使得操作可以独立变化而不影响数据结构。它通过在数据结构中引入一个访问者对象，让访问者对象在不修改数据结构的情况下，定义新的操作并应用于数据结构中的元素。&lt;/p&gt;
&lt;p&gt;下面是一个访问者模式的示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 元素类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Element&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  accept&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;visitor&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;throw&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Error&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'accept() must be implemented.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 具体元素类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ConcreteElementA&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;Element&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  accept&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;visitor&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    visitor&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;visitElementA&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  operationA&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Operation A performed on ConcreteElementA.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ConcreteElementB&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;Element&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  accept&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;visitor&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    visitor&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;visitElementB&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  operationB&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Operation B performed on ConcreteElementB.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 访问者类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Visitor&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  visitElementA&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;element&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;throw&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Error&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'visitElementA() must be implemented.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  visitElementB&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;element&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;throw&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Error&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'visitElementB() must be implemented.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 具体访问者类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ConcreteVisitor&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;Visitor&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  visitElementA&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;element&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    element&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;operationA&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  visitElementB&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;element&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    element&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;operationB&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 使用示例&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; elements &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;[&lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ConcreteElementA&lt;/span&gt;&lt;span class="pun"&gt;(),&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ConcreteElementB&lt;/span&gt;&lt;span class="pun"&gt;()];&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; visitor &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ConcreteVisitor&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;elements&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;forEach&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;element &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  element&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;accept&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;visitor&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 输出&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Operation A performed on ConcreteElementA.&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Operation B performed on ConcreteElementB.&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上面的示例中，我们定义了一个抽象元素类 Element，其中包含了一个抽象方法 accept，用于接受访问者对象。具体元素类 ConcreteElementA 和 ConcreteElementB 继承自抽象元素类，并实现了 accept 方法。&lt;/p&gt;
&lt;p&gt;访问者类 Visitor 定义了访问者对象的接口，其中包含了访问具体元素的方法 visitElementA 和 visitElementB。&lt;/p&gt;
&lt;p&gt;具体访问者类 ConcreteVisitor 继承自访问者类，并实现了访问具体元素的方法，这些方法在访问具体元素时执行相应的操作。&lt;/p&gt;
&lt;p&gt;在使用示例中，我们创建了一个包含具体元素的数组 elements，以及一个具体访问者对象 visitor。&lt;/p&gt;
&lt;p&gt;然后，我们使用 forEach 循环遍历元素数组，并调用元素的 accept 方法，将访问者对象应用于元素。元素根据接受的访问者对象，调用相应的访问者方法。&lt;/p&gt;
&lt;p&gt;输出结果显示了访问者模式的工作原理。访问者对象可以访问不同类型的元素，并根据元素类型执行相应的操作。通过访问者模式，我们可以将数据结构与操作进行解耦，使得操作可以独立变化，并且可以方便地添加新的操作，而无需修改元素类的代码。&lt;/p&gt;
&lt;p&gt;访问者模式适用于处理复杂的数据结构，其中元素类型较多且经常变化，同时操作类型也较多且可能频繁变化的情况。它提供了一种灵活和可扩展的方式来处理复杂的数据结构，同时遵循开闭原则，使得增加新的操作或元素类型更加方便。&lt;/p&gt;
&lt;h2 id="备忘录模式（Memento Pattern）"&gt;备忘录模式（Memento Pattern）&lt;/h2&gt;&lt;p&gt;用于捕捉对象的内部状态并在之后恢复到该状态，而无需暴露对象的实现细节。备忘录模式允许你将对象的状态封装到备忘录对象中，并在需要时进行保存和恢复。&lt;/p&gt;
&lt;p&gt;下面是一个备忘录模式的示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 备忘录对象类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Memento&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;state&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;state &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; state&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  getState&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;state&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 原始对象类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Originator&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;state &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;null&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  setState&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;state&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;state &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; state&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  getState&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;state&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  createMemento&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Memento&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;state&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  restoreMemento&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;memento&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;state &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; memento&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getState&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 管理者类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Caretaker&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;mementos &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;[];&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  addMemento&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;memento&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;mementos&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;push&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;memento&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  getMemento&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;index&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;mementos&lt;/span&gt;&lt;span class="pun"&gt;[&lt;/span&gt;&lt;span class="pln"&gt;index&lt;/span&gt;&lt;span class="pun"&gt;];&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 使用示例&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; originator &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Originator&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; caretaker &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Caretaker&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 设置初始状态&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;originator&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;setState&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'State 1'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Current state:'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; originator&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getState&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 创建备忘录并保存状态&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; memento1 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; originator&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;createMemento&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;caretaker&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addMemento&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;memento1&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 修改状态&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;originator&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;setState&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'State 2'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Current state:'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; originator&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getState&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 创建备忘录并保存状态&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; memento2 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; originator&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;createMemento&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;caretaker&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addMemento&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;memento2&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 恢复到第一个备忘录的状态&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;originator&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;restoreMemento&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;caretaker&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getMemento&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="lit"&gt;0&lt;/span&gt;&lt;span class="pun"&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Restored state:'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; originator&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;getState&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 输出&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Current state: State 1&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Current state: State 2&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Restored state: State 1&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上面的示例中，我们定义了备忘录对象类 Memento 用于存储原始对象的状态，原始对象类 Originator，它包含了状态的设置和获取方法，以及创建备忘录和恢复状态的方法。&lt;/p&gt;
&lt;p&gt;管理者类 Caretaker 用于管理备忘录对象，它可以添加备忘录并获取指定索引的备忘录。&lt;/p&gt;
&lt;p&gt;在使用示例中，我们创建了原始对象 originator 和管理者对象 caretaker。&lt;/p&gt;
&lt;p&gt;首先，我们设置初始状态并打印当前状态。&lt;/p&gt;
&lt;p&gt;然后，我们创建一个备忘录对象 memento1，将原始对象的状态保存到备忘录中，并将备忘录添加到管理者中。&lt;/p&gt;
&lt;p&gt;接着，我们修改状态为 “State 2” 并打印当前状态。&lt;/p&gt;
&lt;p&gt;然后，我们创建另一个备忘录对象 memento2，保存当前状态，并将备忘录添加到管理者中。&lt;/p&gt;
&lt;p&gt;最后，我们从管理者中获取第一个备忘录，并使用 restoreMemento 方法将状态恢复到该备忘录的状态，然后打印恢复后的状态。&lt;/p&gt;
&lt;p&gt;原始对象可以创建备忘录并将其保存到管理者中，备忘录对象存储了原始对象的状态。当需要恢复到之前的状态时，可以从管理者中获取相应的备忘录，并使用原始对象的 restoreMemento 方法将状态恢复到备忘录中保存的状态。&lt;/p&gt;
&lt;p&gt;备忘录模式提供了一种简单且有效的方式来实现对象的状态保存和恢复。它将状态的保存和恢复操作封装在备忘录对象中，使得原始对象不需要暴露其内部细节。备忘录模式提供了一种可靠的机制来管理对象的状态历史，并支持撤销和恢复操作。&lt;/p&gt;
&lt;h2 id="命令模式（Command Pattern）"&gt;命令模式（Command Pattern）&lt;/h2&gt;&lt;p&gt;用于将请求封装成对象，使得可以将请求的发送者与接收者解耦。它将请求的操作封装在命令对象中，并将其作为参数传递给调用者，调用者通过执行命令对象来触发请求的执行。&lt;/p&gt;
&lt;p&gt;下面是一个命令模式的示例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 命令接口&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Command&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  execute&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;throw&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Error&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;"execute() must be implemented."&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 具体命令类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ConcreteCommandA&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;Command&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;receiver&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    super&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;receiver &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; receiver&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  execute&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;receiver&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;actionA&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ConcreteCommandB&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;Command&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;receiver&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    super&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;receiver &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; receiver&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  execute&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;receiver&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;actionB&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 接收者类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Receiver&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  actionA&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;"Receiver: Action A executed."&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  actionB&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;"Receiver: Action B executed."&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 调用者类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Invoker&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;commands &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;[];&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  addCommand&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;command&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;commands&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;push&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;command&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  executeCommands&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;commands&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;forEach&lt;/span&gt;&lt;span class="pun"&gt;((&lt;/span&gt;&lt;span class="pln"&gt;command&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      command&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;execute&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;commands &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;[];&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 使用示例&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; receiver &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Receiver&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; invoker &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Invoker&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; commandA &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ConcreteCommandA&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;receiver&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; commandB &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;ConcreteCommandB&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;receiver&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;invoker&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addCommand&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;commandA&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;invoker&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addCommand&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;commandB&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;invoker&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;executeCommands&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 输出&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Receiver: Action A executed.&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// Receiver: Action B executed.&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上面的示例中，我们定义了一个命令接口 Command，其中包含了一个抽象的执行方法 execute。&lt;/p&gt;
&lt;p&gt;具体命令类 ConcreteCommandA 和 ConcreteCommandB 继承自命令接口，并实现了 execute 方法。这些具体命令类持有一个接收者对象 Receiver 的引用，并在执行方法中调用接收者的相应方法。&lt;/p&gt;
&lt;p&gt;接收者类 Receiver 包含了具体的操作方法，如 actionA 和 actionB。&lt;/p&gt;
&lt;p&gt;调用者类 Invoker 负责管理命令对象，它可以添加命令到命令列表中，并通过执行命令列表来触发请求的执行。&lt;/p&gt;
&lt;p&gt;在使用示例中，我们创建了一个接收者对象 receiver 和调用者对象 invoker。&lt;/p&gt;
&lt;p&gt;然后，我们创建了具体命令对象 commandA 和 commandB，并将接收者对象传递给它们。&lt;/p&gt;
&lt;p&gt;接下来，我们将命令对象添加到调用者的命令列表中，并调用 executeCommands 方法来执行命令列表中的所有命令。&lt;/p&gt;
&lt;p&gt;命令对象封装了具体的操作和接收者，并通过调用者来触发请求的执行。通过使用命令模式，可以将请求的发送者与接收者解耦，同时可以方便地扩展和组合不同的命令，而不需要修改调用者的代码。&lt;/p&gt;
&lt;p&gt;命令模式适用于需要将请求和操作进行解耦的场景。它提供了一种灵活的方式来设计和组织代码，同时支持撤销和重做操作。命令模式还可以用于实现日志和事务处理等功能。&lt;/p&gt;
&lt;h2 id="解释器模式（Interpreter Pattern）"&gt;解释器模式（Interpreter Pattern）&lt;/h2&gt;&lt;p&gt;定义了一种语言的文法表示，并使用解释器来解释执行这些语法结构。解释器模式通过将语法规则表示为对象，并提供解释方法来执行这些对象，使得可以根据特定的语法规则解析和执行复杂的表达式或语言。&lt;/p&gt;
&lt;p&gt;下面是一个解释器模式的示例，用于解释和计算简单的数学表达式：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 抽象表达式类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Expression&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  interpret&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;throw&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Error&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'interpret() must be implemented.'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 终结符表达式类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;NumberExpression&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;Expression&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;value&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    super&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;value &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; value&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  interpret&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;value&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 非终结符表达式类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;AddExpression&lt;/span&gt;&lt;span class="pln"&gt; extends &lt;/span&gt;&lt;span class="typ"&gt;Expression&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;leftExpression&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; rightExpression&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    super&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;leftExpression &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; leftExpression&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;rightExpression &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; rightExpression&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  interpret&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;leftExpression&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;interpret&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;+&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;rightExpression&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;interpret&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 上下文类&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Context&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;expressionStack &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;[];&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  pushExpression&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;expression&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;expressionStack&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;push&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;expression&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  popExpression&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;expressionStack&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;pop&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 使用示例&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; context &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Context&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; expression1 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;NumberExpression&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="lit"&gt;10&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; expression2 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;NumberExpression&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="lit"&gt;5&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; expression3 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;NumberExpression&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="lit"&gt;2&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; addExpression &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;AddExpression&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;expression1&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; expression2&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; finalExpression &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;AddExpression&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;addExpression&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; expression3&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;context&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;pushExpression&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;finalExpression&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; result &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; context&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;popExpression&lt;/span&gt;&lt;span class="pun"&gt;().&lt;/span&gt;&lt;span class="pln"&gt;interpret&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Result:'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; result&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: Result: 17&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上述示例中，我们定义了几个关键的类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Expression 是抽象表达式类，定义了 interpret 方法。&lt;/li&gt;&lt;li&gt;NumberExpression 是终结符表达式类，表示一个数字。&lt;/li&gt;&lt;li&gt;AddExpression 是非终结符表达式类，表示两个表达式的相加操作。&lt;/li&gt;&lt;li&gt;Context 是上下文类，用于存储表达式的执行上下文。&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;在示例中，我们创建了一些数字表达式对象和相加表达式对象，并将它们组合成一个复杂的表达式树。然后，我们将最终的表达式对象推入上下文中，并通过解释器模式执行该表达式。最终，我们得到了计算结果并将其打印出来。&lt;/p&gt;
&lt;h2 id="中介模式（Mediator Pattern）"&gt;中介模式（Mediator Pattern）&lt;/h2&gt;&lt;p&gt;用于降低多个对象之间的直接通信，通过引入一个中介者对象来协调对象之间的交互。中介者模式促进了对象之间的解耦，使得它们可以独立地改变和复用。&lt;/p&gt;
&lt;p&gt;下面是一个中介模式的示例，用于协调多个同事对象之间的通信：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 中介者&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Mediator&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;colleagues &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;[];&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  addColleague&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;colleague&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;colleagues&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;push&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;colleague&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  sendMessage&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;message&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; sender&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;for&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; colleague of &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;colleagues&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;colleague &lt;/span&gt;&lt;span class="pun"&gt;!==&lt;/span&gt;&lt;span class="pln"&gt; sender&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        colleague&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;receiveMessage&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;message&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 同事对象&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;class&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Colleague&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  constructor&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;name&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; mediator&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;name &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; name&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;mediator &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; mediator&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  sendMessage&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;message&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;mediator&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;sendMessage&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;message&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  receiveMessage&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;message&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(`&lt;/span&gt;&lt;span class="pln"&gt;$&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;this&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;name&lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;span class="pln"&gt; received message&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;message&lt;/span&gt;&lt;span class="pun"&gt;}`);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 使用示例&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; mediator &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Mediator&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; colleague1 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Colleague&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;"Colleague 1"&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; mediator&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; colleague2 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Colleague&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;"Colleague 2"&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; mediator&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; colleague3 &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Colleague&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;"Colleague 3"&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; mediator&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;mediator&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addColleague&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;colleague1&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;mediator&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addColleague&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;colleague2&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;mediator&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addColleague&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;colleague3&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;colleague1&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;sendMessage&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;"Hello, everyone!"&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: Colleague 2 received message: Hello, everyone!，Colleague 3 received message: Hello, everyone!&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;colleague2&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;sendMessage&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;"How are you?"&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: Colleague 1 received message: How are you?，Colleague 3 received message: How are you?&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;colleague3&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;sendMessage&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;"Nice to meet you!"&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 输出: Colleague 1 received message: Nice to meet you!，Colleague 2 received message: Nice to meet you!&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;在上述示例中，我们创建了一个中介者对象 Mediator 和多个同事对象 Colleague。&lt;/p&gt;
&lt;p&gt;中介者负责管理同事对象之间的通信，它维护了一个同事对象的列表，并提供了添加同事对象和发送消息的方法。&lt;/p&gt;
&lt;p&gt;同事对象可以通过调用中介者的 sendMessage 方法来发送消息，而不需要直接与其他同事对象进行通信。&lt;/p&gt;
&lt;p&gt;当一个同事对象发送消息时，中介者会接收到该消息并根据需要的逻辑将消息转发给其他同事对象。&lt;/p&gt;
&lt;p&gt;通过使用中介者模式，我们可以将对象之间的通信逻辑集中管理，降低了对象之间的耦合性，并提供了更灵活和可扩展的设计。这种模式常用于需要协调和管理多个对象之间复杂交互的场景。&lt;/p&gt;
&lt;h1 id="总结"&gt;总结&lt;/h1&gt;&lt;p&gt;JavaScript 的设计模式对于开发人员来说具有许多重要的作用，总结如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;提供解决方案：设计模式为常见的软件设计问题提供了经过验证和可行的解决方案。通过学习和掌握设计模式，开发人员可以更快速、更有效地解决问题，避免从头开始设计和实现复杂的解决方案。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;代码复用和可维护性：设计模式鼓励代码的模块化和组件化，使得代码更具可重用性。通过使用设计模式，开发人员可以将通用的功能封装成可复用的模块，并在不同的项目中重复使用，从而减少重复代码的编写。此外，设计模式还提供了一种结构化的方式来组织代码，使得代码更易于理解和维护。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;可扩展性和灵活性：设计模式通过将系统的各个部分解耦，降低了组件之间的依赖性，使得系统更具可扩展性和灵活性。通过使用设计模式，可以轻松地添加、修改或替换系统中的组件，而无需修改其他部分的代码。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;促进团队协作：设计模式提供了一种共享的设计和通信语言，使得团队成员之间可以更好地理解和沟通。团队成员熟悉设计模式可以更快地理解代码，提高协作效率，减少沟通成本。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;最佳实践指南：设计模式代表了一些经过验证的最佳实践，它们是从实际项目和经验中总结出来的。学习和遵循设计模式可以帮助开发人员遵循一些最佳实践，提高代码的质量和可维护性，减少错误和bug的出现。&lt;/p&gt;
&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;综上所述，熟悉 JavaScript 的设计模式对于开发人员来说非常重要。它们提供了一种通用的解决方案和最佳实践，可以提高代码的可复用性、可维护性和可扩展性，促进团队协作，帮助开发人员更高效地解决问题和编写高质量的代码。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;参考&lt;br&gt;&lt;a href="https://www.dofactory.com/javascript/design-patterns" target="_blank"&gt;JavaScript Design Patterns - Dofactory&lt;/a&gt;&lt;br&gt;&lt;a href="https://javascriptpatterns.vercel.app/patterns" target="_blank"&gt;JavaScript Patterns Workshop | JavaScript Patterns&lt;/a&gt;&lt;br&gt;&lt;a href="https://www.patterns.dev/" target="_blank"&gt;Patterns.dev - Modern Web App Design Patterns&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;</content>
    <summary type="text">JavaScript 设计模式是一种解决特定问题的可复用解决方案，旨在提高代码的可维护性、可读性和可扩展性。</summary>
  </entry>
  <entry>
    <title>浏览器中跨标签页通信</title>
    <link rel="alternate" href="https://www.ruanchaomin.com/blog/posts/227" />
    <category term="浏览器" scheme="https://www.ruanchaomin.com/blog/browser" />
    <author>
      <name>阮超民</name>
      <uri>https://www.ruanchaomin.com/</uri>
    </author>
    <id>227</id>
    <updated>2026-04-28T09:30:01Z</updated>
    <published>2023-05-28T09:44:25Z</published>
    <content type="html">&lt;div class="markdown-body editormd-preview-container" previewcontainer="true"&gt;&lt;h1 id="前言"&gt;前言&lt;/h1&gt;&lt;p&gt;Web 应用程序通常有时候需要打开多个标签页同时使用，在某些情况下，我们可能希望在多个标签页之间共享数据或同步状态。例如，当用户在一个标签页中进行某项操作时，我们可能希望在其他相关的标签页能够及时更新以反映这些变化。但是，这些标签页之间如何进行通信呢？在本文中，我们将探索浏览器中的不同窗口、标签页或 iframe 下的不同文档之间相互通信。&lt;/p&gt;
&lt;p&gt;示例代码： &lt;a href="https://github.com/ChaominRuan/examples/tree/main/cross-tab-communication" target="_blank" title="Cross-Tab Communication 示例代码"&gt;Cross-Tab Communication&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;在线运行： &lt;a href="https://chaominruan.github.io/examples/cross-tab-communication/index.html" target="_blank" title="Cross-Tab Communication"&gt;Cross-Tab Communication&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;演示：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/c3a0293a24e24a6d8b5f84a8f257b4f3.gif" alt=""&gt;
&lt;/p&gt;&lt;h1 id="1. LocalStorage"&gt;1. LocalStorage&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;写入数据&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;使用 localStorage.setItem(key, value) 方法将数据存储到 LocalStorage 中：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  localStorage&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;setItem&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    STORAGE_KEY&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;`&lt;/span&gt;&lt;span class="pln"&gt;$&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Date&lt;/span&gt;&lt;span class="pun"&gt;().&lt;/span&gt;&lt;span class="pln"&gt;toLocaleString&lt;/span&gt;&lt;span class="pun"&gt;()}&lt;/span&gt;&lt;span class="pln"&gt; from page&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;id&lt;/span&gt;&lt;span class="pun"&gt;}:&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;input&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;value&lt;/span&gt;&lt;span class="pun"&gt;}`&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;监听数据变化&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;通过监听 LocalStorage 的 storage 事件来检测数据的变化，并进行相应的处理：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code&gt;&lt;span class="pln"&gt;window&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addEventListener&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'storage'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;e&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;e&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;key &lt;/span&gt;&lt;span class="pun"&gt;===&lt;/span&gt;&lt;span class="pln"&gt; STORAGE_KEY&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code&gt;&lt;span class="pln"&gt;    creatMessageElement&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;e&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;newValue&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code&gt;&lt;span class="pun"&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;&lt;p&gt;e 指的是 &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/StorageEvent" target="_blank" title="StorageEvent"&gt;StorageEvent&lt;/a&gt;，有以下几个特有的只读属性：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;属性名&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;key&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;该属性代表被修改的键值。当被 clear() 方法清除之后该属性值为 null。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;newValue&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;该属性代表修改后的新值。当被 clear() 方法清理后或者该键值对被移除，&lt;code&gt;newValue&lt;/code&gt; 的值为 &lt;code&gt;null&lt;/code&gt; 。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;oldValue&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;该属性代表修改前的原值。在设置新键值对时由于没有原始值，该属性值为 &lt;code&gt;null&lt;/code&gt;。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;storageArea&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;被操作的 storage 对象。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;url&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;key 发生改变的对象所在文档的 URL 地址。&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;storage 事件仅在 &lt;strong&gt;不同标签页间&lt;/strong&gt; 的 LocalStorage &lt;strong&gt;数据变化&lt;/strong&gt; 时才会触发，同一标签页内的LocalStorage 变化不会触发该事件，所以上面的写入数据和监听数据变化代码可以写在同一个页面中，并不会陷入死循环。&lt;/p&gt;
&lt;p&gt;需要注意的是，LocalStorage 的大小限制通常在 &lt;strong&gt;5MB&lt;/strong&gt; 左右，而且数据存储在本地，可能会受到 &lt;strong&gt;安全性&lt;/strong&gt; 的影响。因此，在使用 LocalStorage 进行跨标签页通信时，应注意数据的大小和安全性问题。&lt;/p&gt;
&lt;h1 id="2. BroadcastChannel"&gt;2. BroadcastChannel&lt;/h1&gt;&lt;p&gt;BroadcastChannel 用于在不同标签页之间广播消息。它使用类似于广播电台的模式，&lt;strong&gt;发送者将消息广播到所有订阅该频道的标签页&lt;/strong&gt;，&lt;strong&gt;该频道在同源下的所有浏览器上下文共用，一个名称只对应一个频道。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/f12871caabff4704a893c96ef518c886.png" alt=""&gt;
&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;以下是一个简单的示例代码：&lt;/li&gt;&lt;/ul&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 创建一个监听“channel-name”频道的新频道&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; channel &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;BroadcastChannel&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'channel-name'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; buttonFun &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// 发送消息&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  channel&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;postMessage&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;`&lt;/span&gt;&lt;span class="pln"&gt;$&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Date&lt;/span&gt;&lt;span class="pun"&gt;().&lt;/span&gt;&lt;span class="pln"&gt;toLocaleString&lt;/span&gt;&lt;span class="pun"&gt;()}&lt;/span&gt;&lt;span class="pln"&gt; from page&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;id&lt;/span&gt;&lt;span class="pun"&gt;}:&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;input&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;value&lt;/span&gt;&lt;span class="pun"&gt;}`&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 监听频道 message 事件，频道收到消息时触发 message 事件&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;channel&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addEventListener&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'message'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;e&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  creatMessageElement&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;e&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;data&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;window&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;onbeforeunload &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// 断开与频道的连接&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  channel&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;close&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;h1 id="3. SharedWorker"&gt;3. SharedWorker&lt;/h1&gt;&lt;p&gt;&lt;a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API/Using_web_workers#web_workers_api" target="_blank" title="使用 Web Workers"&gt;使用 Web Workers&lt;/a&gt;，可以在后台线程中运行 JavaScript。这样做的好处是可以在独立线程中执行费时的处理任务，渲染主线程不会被阻塞。在 worker 内，不能直接操作 DOM 节点，也不能使用 window 对象的默认方法和属性。然而你可以使用大量 window 对象之下的东西，包括 WebSockets，IndexedDB 以及 FireFox OS 专用的 Data Store API 等数据存储机制。&lt;/p&gt;
&lt;p&gt;Web Workers 分为两种：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;专用线程 Dedicated worker&lt;/p&gt;
&lt;p&gt;  一个专用 worker 仅能被生成它的脚本所使用，也就是只能在当前窗口当前页面使用。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;共享线程 Shared worker&lt;/p&gt;
&lt;p&gt;  一个共享 worker 可以被多个脚本使用，即使这些脚本正在被不同的 window、iframe 或者 worker 访问，所以 SharedWorker 允许不同标签页之间共享一个后台线程，从而实现数据和消息的共享。&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;SharedWorker 使用语法：&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SharedWorker&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;URL&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; name&lt;/span&gt;&lt;span class="pun"&gt;|&lt;/span&gt;&lt;span class="pln"&gt;options&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;参数&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;URL&lt;br&gt;  worker 将执行的脚本URL，必须是同源。&lt;/li&gt;&lt;li&gt;name (可选)&lt;br&gt;  worker 的名称标识，主要用于调试。&lt;/li&gt;&lt;li&gt;options（可选）&lt;br&gt;  创建实例时设定的可选属性的对象，可用的属性包括：&lt;ul&gt;
&lt;li&gt;type:  worker 类型，可设定的值为 classic 或者 module. 若不指定，默认值为 classic。&lt;/li&gt;&lt;li&gt;credentials:  一个指定要用于工作程序的凭据类型，可设定的值为&lt;em&gt; omit、&lt;/em&gt;same-origin 或 &lt;em&gt;include。 &lt;/em&gt;若不指定，或者 type 设定为 classic, 默认值为 omit （无需凭据）。&lt;/li&gt;&lt;li&gt;name： worker 的名称标识，主要用于调试。&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;以下是一个简单的示例代码：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(!!&lt;/span&gt;&lt;span class="pln"&gt;window&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="typ"&gt;SharedWorker&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; myWorker &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;SharedWorker&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'./worker.js'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'share-worker-name'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; buttonFun &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; message &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;`&lt;/span&gt;&lt;span class="pln"&gt;$&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Date&lt;/span&gt;&lt;span class="pun"&gt;().&lt;/span&gt;&lt;span class="pln"&gt;toLocaleString&lt;/span&gt;&lt;span class="pun"&gt;()}&lt;/span&gt;&lt;span class="pln"&gt; from page&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;id&lt;/span&gt;&lt;span class="pun"&gt;}:&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      input&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;value&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}`;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="com"&gt;// 发送消息&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    myWorker&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;port&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;postMessage&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;message&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// 监听消息&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  myWorker&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;port&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;onmessage &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;e&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    creatMessageElement&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;e&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;data&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// 关闭窗口时&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  window&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;onbeforeunload &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    myWorker&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;port&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;postMessage&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'CLOSE'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;else&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  alert&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'Your browser does not support SharedWorker'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;worker.js 这个文件会被多个页面加载，但却可以共享数据，类似于 &lt;strong&gt;单例模式&lt;/strong&gt;，虽然使用了 new 操作符，但最后获取到的数据却是一样的。&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 所有页面共享的数据&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; listOfPort &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;[];&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;onconnect &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;e&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// port 属性返回一个用于通信和控制共享 worker 的 MessagePort 对象&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; port &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; e&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;ports&lt;/span&gt;&lt;span class="pun"&gt;[&lt;/span&gt;&lt;span class="lit"&gt;0&lt;/span&gt;&lt;span class="pun"&gt;];&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// 如果当前页面不存在该 port 则加到列表中&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(!&lt;/span&gt;&lt;span class="pln"&gt;listOfPort&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;includes&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;port&lt;/span&gt;&lt;span class="pun"&gt;))&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    listOfPort&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;push&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;port&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// 监听返回的消息&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  port&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;onmessage &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;e&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; data &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; e&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;data&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="com"&gt;// 窗口关闭时删除该窗口的 port&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;data &lt;/span&gt;&lt;span class="pun"&gt;===&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'CLOSE'&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; portIndex &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; listOfPort&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;findIndex&lt;/span&gt;&lt;span class="pun"&gt;((&lt;/span&gt;&lt;span class="pln"&gt;p&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; p &lt;/span&gt;&lt;span class="pun"&gt;===&lt;/span&gt;&lt;span class="pln"&gt; port&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;portIndex &lt;/span&gt;&lt;span class="pun"&gt;&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="lit"&gt;1&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        listOfPort&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;splice&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;portIndex&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;1&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;return&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;      &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="com"&gt;// 过滤掉当前页面的 port，不给自己发送消息&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    listOfPort&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;filter&lt;/span&gt;&lt;span class="pun"&gt;((&lt;/span&gt;&lt;span class="pln"&gt;p&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; p &lt;/span&gt;&lt;span class="pun"&gt;!==&lt;/span&gt;&lt;span class="pln"&gt; port&lt;/span&gt;&lt;span class="pun"&gt;).&lt;/span&gt;&lt;span class="pln"&gt;forEach&lt;/span&gt;&lt;span class="pun"&gt;((&lt;/span&gt;&lt;span class="pln"&gt;p&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; p&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;postMessage&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;data&lt;/span&gt;&lt;span class="pun"&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// 如果使用  port.addEventListener('message',()=&amp;gt;{}) 方式监听则需要使用 start 来启动。&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// port.start();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;如果 worker 中使用 console.log() 将不会被打印在当前窗口的 console 中。&lt;br&gt;以 chrome 为例，需要在&lt;strong&gt; chrome://inspect/#service-workers &lt;/strong&gt; 中点击 inspect 打开的开发者工具才会打印 worker 中的 console，如下图所示： &lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/1778630a165f41b99e1a7def1ad83d51.png" alt=""&gt;
&lt;/p&gt;&lt;h1 id="4. window.open + window.opener"&gt;4. window.open + window.opener&lt;/h1&gt;&lt;p&gt;当我们使用 window.open 打开页面时，将返回一个被打开页面 window 的引用。被打开的页面可以通过 window.opener 获取到打开它的页面的引用，通过这种方式我们就将这些页面建立起联系。&lt;/p&gt;
&lt;p&gt;以下是一个简单的示例代码：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="com"&gt;// 点击按钮通过新窗口打开页面，并收集打开过的页面的window对象&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;openButton&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addEventListener&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'click'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;e&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; otherWindow &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; window&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;open&lt;/span&gt;&lt;span class="pun"&gt;(`&lt;/span&gt;&lt;span class="pln"&gt;$&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;url&lt;/span&gt;&lt;span class="pun"&gt;}/&lt;/span&gt;&lt;span class="typ"&gt;WindowOpen&lt;/span&gt;&lt;span class="pun"&gt;/&lt;/span&gt;&lt;span class="typ"&gt;WindowOpen&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;html&lt;/span&gt;&lt;span class="pun"&gt;`);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  listOfOtherWindows&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;push&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;otherWindow&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; buttonFun &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; mseegae &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;`&lt;/span&gt;&lt;span class="pln"&gt;$&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Date&lt;/span&gt;&lt;span class="pun"&gt;().&lt;/span&gt;&lt;span class="pln"&gt;toLocaleString&lt;/span&gt;&lt;span class="pun"&gt;()}&lt;/span&gt;&lt;span class="pln"&gt; from page&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;id&lt;/span&gt;&lt;span class="pun"&gt;}:&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    input&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;value&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}`;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// 过滤掉已关闭的窗口，给未关闭的窗口发送消息&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  listOfOtherWindows&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;filter&lt;/span&gt;&lt;span class="pun"&gt;((&lt;/span&gt;&lt;span class="pln"&gt;window&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;!&lt;/span&gt;&lt;span class="pln"&gt;window&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;closed&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;forEach&lt;/span&gt;&lt;span class="pun"&gt;((&lt;/span&gt;&lt;span class="pln"&gt;window&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; window&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;postMessage&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;mseegae&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; url&lt;/span&gt;&lt;span class="pun"&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="com"&gt;// 给打开该窗口的窗口发送消息&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(!!&lt;/span&gt;&lt;span class="pln"&gt;window&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;opener&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    window&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;opener&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;postMessage&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;mseegae&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; url&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;window&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addEventListener&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'message'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;e&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;e&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;origin &lt;/span&gt;&lt;span class="pun"&gt;===&lt;/span&gt;&lt;span class="pln"&gt; url&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    creatMessageElement&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;e&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;data&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;显然，这种强关联模式存在一个问题：如果页面不是通过在另一个页面内的 window.open 打开（例直接在地址栏输入），那这个联系就被打破了。&lt;/p&gt;
&lt;h1 id="5. WebSocket"&gt;5. WebSocket&lt;/h1&gt;&lt;p&gt;WebSocket 是一种在浏览器和服务器之间建立持久连接的协议，可以实现双向通信。通过WebSocket，我们可以在不同的标签页之间进行实时的数据传输和通信。&lt;/p&gt;
&lt;p&gt;在跨标签通信方面，我们可以在每个标签页中都创建一个 WebSocket 连接，并通过 WebSocket 发送和接收消息。当一个标签页发送消息时，其他标签页可以通过监听 WebSocket 事件来接收消息，并做出相应的处理。&lt;/p&gt;
&lt;p&gt;以下是一个简单的示例代码：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; ws &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;WebSocket&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;WS_SERVER&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; buttonFun &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; message &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;`&lt;/span&gt;&lt;span class="pln"&gt;$&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Date&lt;/span&gt;&lt;span class="pun"&gt;().&lt;/span&gt;&lt;span class="pln"&gt;toLocaleString&lt;/span&gt;&lt;span class="pun"&gt;()}&lt;/span&gt;&lt;span class="pln"&gt; from page&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt;id&lt;/span&gt;&lt;span class="pun"&gt;}:&lt;/span&gt;&lt;span class="pln"&gt; $&lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    input&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;value&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}`;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  ws&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;send&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;JSON&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;stringify&lt;/span&gt;&lt;span class="pun"&gt;({&lt;/span&gt;&lt;span class="pln"&gt; id&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; message &lt;/span&gt;&lt;span class="pun"&gt;}));&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-javascript"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;ws&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;onmessage &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;e&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; data &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; JSON&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;parse&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;e&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;data&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;data&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;id &lt;/span&gt;&lt;span class="pun"&gt;!==&lt;/span&gt;&lt;span class="pln"&gt; id&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;    creatMessageElement&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;data&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;message&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-javascript"&gt;&lt;span class="pun"&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;h1 id="浏览器兼容性"&gt;浏览器兼容性&lt;/h1&gt;&lt;p&gt;浏览器兼容性最低版本：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align:center"&gt;API&lt;/th&gt;
&lt;th style="text-align:center"&gt;Chrome&lt;/th&gt;
&lt;th style="text-align:center"&gt;Edge&lt;/th&gt;
&lt;th style="text-align:center"&gt;Safari&lt;/th&gt;
&lt;th style="text-align:center"&gt;Firefox&lt;/th&gt;
&lt;th style="text-align:center"&gt;Opera&lt;/th&gt;
&lt;th style="text-align:center"&gt;IE&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align:center"&gt;LocalStorage&lt;/td&gt;
&lt;td style="text-align:center"&gt;4&lt;/td&gt;
&lt;td style="text-align:center"&gt;12&lt;/td&gt;
&lt;td style="text-align:center"&gt;4&lt;/td&gt;
&lt;td style="text-align:center"&gt;3.5&lt;/td&gt;
&lt;td style="text-align:center"&gt;11.5&lt;/td&gt;
&lt;td style="text-align:center"&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:center"&gt;BroadcastChannel&lt;/td&gt;
&lt;td style="text-align:center"&gt;54&lt;/td&gt;
&lt;td style="text-align:center"&gt;79&lt;/td&gt;
&lt;td style="text-align:center"&gt;15.4&lt;/td&gt;
&lt;td style="text-align:center"&gt;38&lt;/td&gt;
&lt;td style="text-align:center"&gt;41&lt;/td&gt;
&lt;td style="text-align:center"&gt;不支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:center"&gt;SharedWorker&lt;/td&gt;
&lt;td style="text-align:center"&gt;5&lt;/td&gt;
&lt;td style="text-align:center"&gt;79&lt;/td&gt;
&lt;td style="text-align:center"&gt;5-6.1, 16&lt;/td&gt;
&lt;td style="text-align:center"&gt;29&lt;/td&gt;
&lt;td style="text-align:center"&gt;11.5&lt;/td&gt;
&lt;td style="text-align:center"&gt;不支持&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:center"&gt;window.open&lt;/td&gt;
&lt;td style="text-align:center"&gt;4&lt;/td&gt;
&lt;td style="text-align:center"&gt;12&lt;/td&gt;
&lt;td style="text-align:center"&gt;3.1&lt;/td&gt;
&lt;td style="text-align:center"&gt;2&lt;/td&gt;
&lt;td style="text-align:center"&gt;10&lt;/td&gt;
&lt;td style="text-align:center"&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:center"&gt;WebSocket&lt;/td&gt;
&lt;td style="text-align:center"&gt;5&lt;/td&gt;
&lt;td style="text-align:center"&gt;12&lt;/td&gt;
&lt;td style="text-align:center"&gt;5&lt;/td&gt;
&lt;td style="text-align:center"&gt;7&lt;/td&gt;
&lt;td style="text-align:center"&gt;12.1&lt;/td&gt;
&lt;td style="text-align:center"&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="优缺点"&gt;优缺点&lt;/h1&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align:center"&gt;API&lt;/th&gt;
&lt;th style="text-align:center"&gt;跨域&lt;/th&gt;
&lt;th style="text-align:center"&gt;优点&lt;/th&gt;
&lt;th style="text-align:center"&gt;缺点&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align:center"&gt;LocalStorage&lt;/td&gt;
&lt;td style="text-align:center"&gt;不支持&lt;/td&gt;
&lt;td style="text-align:center"&gt;1.支持存储和共享数据&lt;/td&gt;
&lt;td style="text-align:center"&gt;1.需要数据存储在本地，可能会受到安全性的影响&lt;br&gt;2.不适用于实时通信，只能通过事件监听来传递数据
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:center"&gt;BroadcastChannel&lt;/td&gt;
&lt;td style="text-align:center"&gt;不支持&lt;/td&gt;
&lt;td style="text-align:center"&gt;1.支持实时通信，可以广播消息给所有订阅者&lt;/td&gt;
&lt;td style="text-align:center"&gt;1.需要浏览器支持，不适用于老旧浏览器&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:center"&gt;SharedWorker&lt;/td&gt;
&lt;td style="text-align:center"&gt;不支持&lt;/td&gt;
&lt;td style="text-align:center"&gt;1.支持多个标签页共享同一个后台 线程，实现数据和消息的共享&lt;br&gt;2.不会占用渲染主线程
&lt;/td&gt;&lt;td style="text-align:center"&gt;1.需要额外的开发工作，包括在后台线程中处理消息和同步数据&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:center"&gt;window.open&lt;/td&gt;
&lt;td style="text-align:center"&gt;支持&lt;/td&gt;
&lt;td style="text-align:center"&gt;1.适用于各种浏览器，不受兼容性限制。&lt;/td&gt;
&lt;td style="text-align:center"&gt;1.需要从当前窗口打开另一个窗口&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align:center"&gt;WebSocket&lt;/td&gt;
&lt;td style="text-align:center"&gt;支持&lt;/td&gt;
&lt;td style="text-align:center"&gt;1.支持实时双向通信，可以在不同标签页之间进行消息传递&lt;/td&gt;
&lt;td style="text-align:center"&gt;1.需要服务器端的支持来处理 WebSocket 连接&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id="总结"&gt;总结&lt;/h1&gt;&lt;p&gt;我们讨论了五种浏览器跨标签通信方法，选择合适的方法取决于具体需求和场景。如果仅需要实时通信使用 BroadcastChannel 通信是一个不错的选择，如果需要存储数据和共享数据，且不需要实时通信，可以使用 LocalStorage，对于需要复杂的协调工作和高性能的应用程序，Shared Web Workers 可能更适合，如果需要支持跨域，且仅在该窗口打开另一个窗口的情况下，适合使用  window.open + window.opener，如果有 WebSocket 服务端的支持，使用 WebSocket 实现实时通信和双向数据传递。&lt;/p&gt;
&lt;p&gt;通过这些方法，我们可以在不同的标签页之间进行数据传递和实时通信。根据具体的需求和场景，选择适合的方法来实现跨标签通信。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;参考&lt;br&gt;&lt;a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API/Using_web_workers#web_workers_api" target="_blank" title="Web Workers API"&gt;Web Workers API | MDN&lt;/a&gt;&lt;br&gt;&lt;a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Broadcast_Channel_API" target="_blank" title="Broadcast Channel API | MDN"&gt;Broadcast Channel API | MDN&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;</content>
    <summary type="text">Web 应用程序通常有时候需要打开多个标签页同时使用，本文讨论了五种浏览器跨标签通信方法。</summary>
  </entry>
  <entry>
    <title>浏览器渲染原理</title>
    <link rel="alternate" href="https://www.ruanchaomin.com/blog/posts/226" />
    <category term="浏览器" scheme="https://www.ruanchaomin.com/blog/browser" />
    <author>
      <name>阮超民</name>
      <uri>https://www.ruanchaomin.com/</uri>
    </author>
    <id>226</id>
    <updated>2026-05-02T14:29:17Z</updated>
    <published>2023-05-09T16:06:48Z</published>
    <content type="html">&lt;div class="markdown-body editormd-preview-container" previewcontainer="true"&gt;&lt;h1 id="前言"&gt;前言&lt;/h1&gt;&lt;p&gt;浏览器渲染原理是网页开发中重要的基础知识之一，了解浏览器的渲染过程，可以帮助我们更好地优化网页性能，提升用户体验。&lt;/p&gt;
&lt;h1 id="浏览器渲染引擎"&gt;浏览器渲染引擎&lt;/h1&gt;&lt;p&gt;浏览器渲染引擎是浏览器中最核心的部分。它负责将 HTML、CSS、JavaScript 等网页元素转换成可视化的页面，我们称之为文档对象模型（DOM）。渲染引擎将这些元素解析、计算、布局、绘制等等，最终呈现在屏幕上。&lt;/p&gt;
&lt;p&gt;不同浏览器使用不同的渲染引擎。例如，Google Chrome 使用 Blink 渲染引擎，Firefox 使用 Gecko 渲染引擎，Safari 使用 WebKit 渲染引擎等等。这些渲染引擎可能会有不同的实现方式，但它们的目标都是相同的：将网页元素转换成可视化的页面。&lt;/p&gt;
&lt;h1 id="浏览器渲染流程"&gt;浏览器渲染流程&lt;/h1&gt;&lt;p&gt;下面我们将详细介绍浏览器的渲染流程。通常来说，浏览器渲染流程包括以下几个步骤：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/757f8d97aa074b529c77a3b344cb254a.png" alt=""&gt;
&lt;/p&gt;&lt;h2 id="1. 解析 HTML"&gt;1. 解析 HTML&lt;/h2&gt;&lt;p&gt;当浏览器向服务器获取 HTML 文档的请求时，服务器返回二进制流格式的 HTML 页面，响应头 Content-Type 值为 text/html，这里 text/html 是 &lt;a href="https://en.wikipedia.org/wiki/Media_type" target="_blank" title="MIME 类型"&gt;MIME 类型&lt;/a&gt;，它告诉浏览器它是一个 HTML 文档。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/2e4316ac17b5452996e5f87e9aa0d869.png" alt=""&gt;
&lt;/p&gt;&lt;p&gt;当浏览器收到 HTML 数据时，主线程开始解析文本字符串（HTML）并将其转换为文档对象模型（DOM），在浏览器开发者工具 console 中 输入 document 即可看到一个完整的 DOM 树结构。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/10426b03f6d244d28fc804678e5b1ed3.png" alt=""&gt;
&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;当 HTML 解析器发现 &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; 标签时，会暂停 HTML 文档的解析，并必须加载、解析和执行JavaScript代码，即&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; 标签会阻塞 DOM 的解析和渲染。&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/28c8eebda03049778a9f0f6c369cc81e.png" alt=""&gt;
&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt;标签不会阻塞 DOM 的解析，但是会阻塞 DOM 的渲染，同时还会阻塞之后的 &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;  标签的执行。&lt;/li&gt;&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;&amp;lt;link rel="preload"&amp;gt;&lt;/code&gt; &lt;a href="https://html.spec.whatwg.org/multipage/links.html#link-type-preload" target="_blank" title="preload 属性"&gt;preload 属性&lt;/a&gt; 会预加载资源。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;&amp;lt;link rel="dns-prefetch"&amp;gt;&lt;/code&gt; &lt;a href="https://html.spec.whatwg.org/multipage/links.html#link-type-dns-prefetch" target="_blank" title="dns-prefetch 属性"&gt;dns-prefetch 属性&lt;/a&gt; (DNS 预获取) 是尝试在请求资源之前解析域名，仅对跨域域上的 DNS 查找有效。&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id="2. 样式计算（Style）"&gt;2. 样式计算（Style）&lt;/h2&gt;&lt;p&gt;主线程解析 CSS 并确定每个 DOM 节点的计算样式，目的是为了计算出 DOM 节点中每个元素的具体样式。经过计算，每个元素节点都会有一个最终样式，在浏览器开发者工具 Elements -&amp;gt; Computed 即可查看。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/39b8a81376f34fa283e3d9698587f5ad.png" alt=""&gt;
&lt;/p&gt;&lt;p&gt;样式计算主要有以下三个步骤：&lt;/p&gt;
&lt;h3 id="2.1 把 CSS 转换为 styleSheets"&gt;2.1 把 CSS 转换为 styleSheets&lt;/h3&gt;&lt;p&gt;CSS 样式主要来源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; 标签&lt;/li&gt;&lt;li&gt;&lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; 标签&lt;/li&gt;&lt;li&gt;元素的 Style 属性&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;浏览器无法直接理解纯文本的CSS样式，当渲染引擎接收到 CSS 文本时，会将 CSS 文本转换为浏览器可以理解的 styleSheets 结构。&lt;/p&gt;
&lt;p&gt;在浏览器开发者工具 console 中 输入 document.styleSheets 即可看到所有解析后 CSS 样式。&lt;/p&gt;
&lt;p&gt;如果不提供任何 CSS，也会有默认样式。 如 &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; 标签显示大于  &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; 标签，这是因为浏览器具有默认样式表。如果你想知道 Chrome 的默认 CSS 是什么样的，你可以&lt;a href="https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/html/resources/html.css" target="_blank" title="在这里看到源代码"&gt;在这里看到源代码&lt;/a&gt;。&lt;/p&gt;
&lt;h3 id="2.2 标准化样式表中的属性值"&gt;2.2 标准化样式表中的属性值&lt;/h3&gt;&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code&gt;&lt;span class="pln"&gt;body &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt; font&lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="pln"&gt;size&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;2em&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code&gt;&lt;span class="pln"&gt;p &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt; color&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; blue &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code&gt;&lt;span class="pln"&gt;span &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt; display&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; none &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code&gt;&lt;span class="pln"&gt;div &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt; font&lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="pln"&gt;weight&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; bold &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code&gt;&lt;span class="pln"&gt;div p &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt; color&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; green &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code&gt;&lt;span class="pln"&gt;div &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;span class="pln"&gt; color&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; red &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;&lt;p&gt;可以看到上面的 CSS 文本中有很多属性值，如 2em、blue、bold，这些属性值不被渲染引擎理解，需要将所有值转换为渲染引擎容易理解的、标准化的计算值，这个过程就是属性值标准化。&lt;br&gt;如 2em 被解析成 32px，red 被解析成了 rgb(255, 0, 0)，bold  被解析为 700。
&lt;/p&gt;&lt;h3 id="2.3 计算出每个 DOM 节点的具体样式"&gt;2.3 计算出每个 DOM 节点的具体样式&lt;/h3&gt;&lt;p&gt;每个 DOM 节点的样式属性，是 CSS 继承规则和层叠规则 进行叠加计算的结果。层叠是 CSS 的一个基本特征，继承指的是某些样式属性会从父元素传递给子元素，而层叠则是指当多个样式规则应用到同一个元素时，浏览器根据一定的规则确定最终的样式值。&lt;/p&gt;
&lt;h2 id="3. 布局（Layout）"&gt;3. 布局（Layout）&lt;/h2&gt;&lt;p&gt;现在，我们知道文档的结构和每个节点的样式，但这还不足以显示页面，因为我们还不知道 DOM 元素的几何位置信息。&lt;/p&gt;
&lt;p&gt;布局阶段是浏览器确定每个元素在页面中的位置和大小的过程。在布局过程中，浏览器会根据元素的盒模型、样式属性等计算出每个元素的位置和尺寸。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/27724067c34540ac9988019d57ccf0ce.png" alt=""&gt;&lt;br&gt;Chrome 在布局阶段需要完成两个任务：创建布局树和布局计算。
&lt;/p&gt;&lt;h3 id="3.1 创建布局树"&gt;3.1 创建布局树&lt;/h3&gt;&lt;p&gt;遍历 DOM 树中的每一个节点，过滤不可见的元素（比如  head  标签，比如具有  display:none  样式的元素），将所有的可见元素构建一棵只包含可见元素布局树（具有 visibility: hidden 的元素会在布局树中）。&lt;/p&gt;
&lt;h3 id="3.2 布局计算"&gt;3.2 布局计算&lt;/h3&gt;&lt;p&gt;有了布局树之后，就需要对布局树中各节点的几何坐标位置进行计算，其中包含 x，y 坐标和边界框大小等信息。&lt;/p&gt;
&lt;h2 id="4. 分层（Layer）"&gt;4. 分层（Layer）&lt;/h2&gt;&lt;p&gt;主线程遍历布局树，根据策略对布局树进行分层，并生成一棵对应的图层树。Chrome 引入了分层和合成的机制就是为了提升每帧的渲染效率。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/fbddaa241bc149d795a3e09ec570f45b.png" alt=""&gt;
&lt;/p&gt;&lt;p&gt;在浏览器开发者工具 （Layers） 可以查看可视化页面的分层情况，如下图所示：&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/1f23adba71d346038d3da0d41339b843.png" alt=""&gt;
&lt;/p&gt;&lt;h3 id="什么样的节点会创建独立的图层？"&gt;什么样的节点会创建独立的图层？&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;display 属性值为 fixed 或者 sticky&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;opacity 属性值小于 1&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;z-index 属性值不为 auto&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;transform、filter、perspective、clip-path 属性值不为 none&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;在 will-change 中指定了任意CSS属性&lt;/p&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id="5. 绘制（Paint）"&gt;5. 绘制（Paint）&lt;/h2&gt;&lt;p&gt;有了图层树后，主线程会为每个图层单独绘制指令集，用于描述这一层的内容该如何画出来。如把画笔移到某个位置，先画什么再画什么，把一个图层的绘制拆分成很多小的 绘制指令 ，然后再把这些指令按照顺序组成一个 待绘制列表。&lt;/p&gt;
&lt;p&gt;主线程将每个图层的绘制信息提交给&lt;strong&gt;合成线程(compositor thread)&lt;/strong&gt; ，剩余工作将由合成线程完成。&lt;/p&gt;
&lt;h2 id="6. 分块（Tiling）"&gt;6. 分块（Tiling）&lt;/h2&gt;&lt;p&gt;浏览器渲染分块用于将页面分割为多个独立的块，然后分别渲染这些块。每个块都是独立的渲染区域，并且可以单独更新和绘制，以提高渲染性能和响应速度。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;页面分割： 浏览器将页面划分为多个独立的块。通常，这些块的大小是固定的，例如 256x256 像素。每个块都有自己的位置和尺寸。&lt;/li&gt;&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;多线程处理： 浏览器可以使用多个线程来并行处理分块。这使得浏览器能够更高效地利用硬件资源。&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id="7. 光栅化（Raster）"&gt;7. 光栅化（Raster）&lt;/h2&gt;&lt;p&gt;光栅化是将页面上的图形、文本和其他可见元素转换为像素的过程。在浏览器中，页面的可视内容通常以矢量形式表示，但在显示器上呈现时需要将其转换为光栅图像（由像素组成的位图）。&lt;/p&gt;
&lt;p&gt;合成线程将分块信息交给 GPU 进程，GPU 进程会开启多个线程来完成光栅化，并且优先处理靠近视口区域的块，将&lt;strong&gt;块&lt;/strong&gt;生成&lt;strong&gt;位图&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/856e045decf44f7ca4b72eb2ac5a8a8f.png" alt=""&gt;
&lt;/p&gt;&lt;h1 id="8. 画（Draw）"&gt;8. 画（Draw）&lt;/h1&gt;&lt;p&gt;合成线程拿到每个图层、块的位图后，生产一个个 &lt;strong&gt;指引(quad)&lt;/strong&gt; 信息，指引会标识出每个位图应该画在屏幕的哪个位置，以及会考虑旋转，缩放等变形。&lt;/p&gt;
&lt;p&gt;变形发生在合成线程，与渲染主线程无关，所以这就是 transform 效率高的本质原因。&lt;/p&gt;
&lt;h1 id="重排（reflow）"&gt;重排（reflow）&lt;/h1&gt;&lt;p&gt;reflow 的本质是重新计算 layout 树，以下的操作都会导致页面 reflow ：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;页面首次渲染。&lt;/li&gt;&lt;li&gt;浏览器窗口大小发生变化。&lt;/li&gt;&lt;li&gt;元素的内容发生变化。&lt;/li&gt;&lt;li&gt;元素的尺寸或者位置发生变化。&lt;/li&gt;&lt;li&gt;元素的字体大小发生变化。&lt;/li&gt;&lt;li&gt;激活 CSS 伪类。&lt;/li&gt;&lt;li&gt;查询某些属性或者调用某些方法。&lt;/li&gt;&lt;li&gt;添加或者删除可见的 DOM 元素。&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;为了避免连续的多次操作导致布局树反复计算，浏览器会合并这些操作，当 JS 代码全部完成后再进行计算，所以改动属性造成的 reflow 是异常完成，也因此 当 JS 获取布局属性时，可能无法获取到最新的布局信息。&lt;/p&gt;
&lt;p&gt;浏览器在反复权衡下，最终决定获取属性立即 reflow。 如调用 dom.clientWidth。&lt;/p&gt;
&lt;h1 id="重绘（repaint）"&gt;重绘（repaint）&lt;/h1&gt;&lt;p&gt;repaint 的本质就是重新根据分层信息计算绘制指令，以下的操作会导致 repaint：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;改变 color、background 相关属性：background-color、background-image。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;&lt;p&gt;改变 outline 相关属性：outline-color、outline-width 、text-decoration。&lt;/p&gt;
&lt;/li&gt;&lt;li&gt;改变 border-radius、visibility、box-shadow。&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;当改动了可见样式后，就需要重新计算，会引发 repaint。&lt;/p&gt;
&lt;p&gt;元素的布局信息也属于可见样式，所以 reflow 一定会引起 repaint。&lt;/p&gt;
&lt;h1 id="为什么 transform 效率高"&gt;为什么 transform 效率高&lt;/h1&gt;&lt;p&gt;因为 transform 既不会影响布局也不会影响绘制指令，它只会影响渲染流程的最后一步 draw 阶段，由于 draw 在合成线程中，所以 transform 的变化几乎不会影响到渲染主线程。&lt;/p&gt;
&lt;h1 id="总结"&gt;总结&lt;/h1&gt;&lt;p&gt;在本文中，我们介绍了浏览器的渲染过程，包括文档解析、样式计算、布局、分层、绘制和合成等步骤。我们还介绍 reflow 和 repaint。以及 transform 效率，这些可以帮助我们优化网页性能，为用户带来更好的浏览体验。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;参考：&lt;/p&gt;
&lt;p&gt;&lt;a href="https://developer.chrome.com/blog/inside-browser-part3/" target="_blank" title="Inside look at modern web browser (part 3)"&gt;Inside look at modern web browser (part 3)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://docs.google.com/document/d/1aitSOucL0VHZa9Z2vbRJSyAIsAz24kX8LFByQ5xQnUg/edit" target="_blank" title="How Blink works"&gt;How Blink works&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.logrocket.com/how-browser-rendering-works-behind-scenes" target="_blank" title="How browser rendering works — behind the scenes"&gt;How browser rendering works — behind the scenes&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://medium.com/jspoint/how-the-browser-renders-a-web-page-dom-cssom-and-rendering-df10531c9969" target="_blank" title="How the browser renders a web page? — DOM, CSSOM, and Rendering"&gt;How the browser renders a web page? — DOM, CSSOM, and Rendering&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://juejin.cn/post/6906470997898362894" target="_blank" title="浏览器原理系列-浏览器渲染流程详解"&gt;浏览器原理系列-浏览器渲染流程详解&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;</content>
    <summary type="text">浏览器渲染原理是网页开发中重要的基础知识之一，本文介绍了浏览器的渲染流程：解析、样式计算、布局、分层、绘制、分块、光栅化和画几个步骤。</summary>
  </entry>
  <entry>
    <title>浏览器事件循环</title>
    <link rel="alternate" href="https://www.ruanchaomin.com/blog/posts/225" />
    <category term="浏览器" scheme="https://www.ruanchaomin.com/blog/browser" />
    <author>
      <name>阮超民</name>
      <uri>https://www.ruanchaomin.com/</uri>
    </author>
    <id>225</id>
    <updated>2026-04-30T22:54:24Z</updated>
    <published>2023-03-26T16:07:23Z</published>
    <content type="html">&lt;div class="markdown-body editormd-preview-container" previewcontainer="true"&gt;&lt;h1 id="1.事件循环的概念"&gt;1.事件循环的概念&lt;/h1&gt;&lt;p&gt;JavaScript 是一种单线程语言，意味着它只有一个主线程，它运行在浏览器的渲染主线程中，渲染主线程承担着很多的工作，渲染页面、执行 JS 都在其中运行。这意味着如果我们在渲染主线程上执行了一个长时间的任务，那么 UI 将被锁定，无法响应用户的任何操作。为了避免这种情况发生，我们需要使用事件循环。&lt;/p&gt;
&lt;h1 id="2.JS为何会阻碍页面渲染"&gt;2.JS为何会阻碍页面渲染&lt;/h1&gt;&lt;p&gt;以这段  Html 为例：&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code&gt;&lt;span class="tag"&gt;&amp;lt;h1&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="atn"&gt;id&lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="atv"&gt;"text"&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt;Hi there, I'm Chaomin Ruan&lt;/span&gt;&lt;span class="tag"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code&gt;&lt;span class="tag"&gt;&amp;lt;button&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="atn"&gt;id&lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="atv"&gt;"change-text-button"&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt;change text&lt;/span&gt;&lt;span class="tag"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code&gt;&lt;span class="tag"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;var&lt;/span&gt;&lt;span class="pln"&gt; text &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; document&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;querySelector&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'#text'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;var&lt;/span&gt;&lt;span class="pln"&gt; button &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; document&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;querySelector&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'#change-text-button'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;var&lt;/span&gt;&lt;span class="pln"&gt; delay &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;duration&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="kwd"&gt;var&lt;/span&gt;&lt;span class="pln"&gt; start &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Date&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;now&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;while&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="typ"&gt;Date&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;now&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="pln"&gt; start &lt;/span&gt;&lt;span class="pun"&gt;&amp;lt;&lt;/span&gt;&lt;span class="pln"&gt; duration&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{};&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code&gt;&lt;span class="pln"&gt;  button&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addEventListener&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'click'&lt;/span&gt;&lt;span class="pun"&gt;,()=&amp;gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code&gt;&lt;span class="pln"&gt;    text&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;textContent &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;'嘿，你好，我是阮超民'&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code&gt;&lt;span class="pln"&gt;    delay&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="lit"&gt;3000&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code&gt;&lt;span class="tag"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;&lt;p&gt;有一句文本和一个按钮，点击按钮时先改变文本内容，然后延迟3秒。&lt;br&gt;但实际是3秒后文本才会变化。
&lt;/p&gt;&lt;h1 id="text"&gt;Hi there, I’m Chaomin Ruan&lt;/h1&gt;

&lt;h3&gt;试一试:&lt;/h3&gt;

&lt;p&gt;点击按钮： &lt;button id="change-text-button"&gt;change text&lt;/button&gt; (点击后观察上方文字)&lt;/p&gt;
&lt;script&gt;
  var text = document.querySelector('#text');
  var button = document.querySelector('#change-text-button');

  var delay = (duration) =&gt; {
  var start = Date.now();
    while (Date.now() - start &lt; duration) {};
  };

  button.addEventListener('click',()=&gt;{
    text.textContent = '嘿，你好，我是阮超民';
    delay(3000);
 });
&lt;/script&gt;

&lt;p&gt;这是因为 JS 执行与 Paint 任务都发生在渲染主线程，Paint 任务没有及时执行，即绘制列表没有及时提交给合成线程。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/7602df95ffc443db803e8140cc9e5f82.png" alt=""&gt;
&lt;/p&gt;&lt;h1 id="3.同步和异步"&gt;3.同步和异步&lt;/h1&gt;&lt;p&gt;事件循环的基本思想是将任务分为两类：同步和异步任务和异步任务。同步任务在主线程上执行，而异步任务（网络请求，定时器、事件监听等）交给其他线程去处理，自身立即结束任务的执行，转而执行后续代码，当其他线程完成时，将事先传递的回调函数包装成任务，加入到消息队列的末尾排队，等待主线程调度执行。这允许主线程继续执行其他任务，而不必等待长时间运行的任务完成。&lt;/p&gt;
&lt;p&gt;在这种异步模式下，浏览器永不阻塞，从而最大限度的保证了单线程的流畅运行。&lt;/p&gt;
&lt;h1 id="4.处理模型"&gt;4.处理模型&lt;/h1&gt;&lt;p&gt;&lt;a href="https://html.spec.whatwg.org/#event-loop-processing-model" target="_blank" title="HTML事件循环处理模型"&gt;HTML事件循环处理模型&lt;/a&gt;大致可以这样描述:&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code&gt;&lt;span class="kwd"&gt;while&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;true&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; taskStartTime &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; performance&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;now&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="com"&gt;// It's unspecified where UI events fit in. Should each have their own task?&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;const&lt;/span&gt;&lt;span class="pln"&gt; task &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; eventQueue&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;pop&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;task&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code&gt;&lt;span class="pln"&gt;        task&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;run&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;performance&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;now&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="pln"&gt; taskStartTime &lt;/span&gt;&lt;span class="pun"&gt;&amp;gt;&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;50&lt;/span&gt;&lt;span class="pun"&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code&gt;&lt;span class="pln"&gt;        reportLongTask&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;if&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(!&lt;/span&gt;&lt;span class="pln"&gt;hasRenderingOpportunity&lt;/span&gt;&lt;span class="pun"&gt;())&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code&gt;&lt;span class="pln"&gt;        &lt;/span&gt;&lt;span class="kwd"&gt;continue&lt;/span&gt;&lt;span class="pun"&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code&gt;&lt;span class="pln"&gt;    invokeAnimationFrameCallbacks&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="kwd"&gt;while&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;needsStyleAndLayout&lt;/span&gt;&lt;span class="pun"&gt;())&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code&gt;&lt;span class="pln"&gt;        styleAndLayout&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code&gt;&lt;span class="pln"&gt;        invokeResizeObservers&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code&gt;&lt;span class="pln"&gt;    &lt;/span&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code&gt;&lt;span class="pln"&gt;    markPaintTiming&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code&gt;&lt;span class="pln"&gt;    render&lt;/span&gt;&lt;span class="pun"&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;&lt;p&gt;事件循环不是 JavaScript 引擎的一部分，而是浏览器运行时中的一个组件，它使用单个执行线程不断异步等待下一条消息在某个时刻进入队列，如图所示&lt;br&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/c5479c365cf84f26b886cee9c0292edb.png" alt=""&gt;
&lt;/p&gt;&lt;p&gt;详细步骤如下：&lt;/p&gt;
&lt;p&gt;1、所有同步任务都在主线程上执行，形成一个调用栈&lt;/p&gt;
&lt;p&gt;2、主线程之外，还存在一个”消息队列”。只要异步任务执行完成，就到消息队列中排队&lt;/p&gt;
&lt;p&gt;3、一旦调用栈中的所有同步任务执行完毕，系统就会按次序读取消息队列中的异步任务，于是被读取的异步任务结束等待状态，进入执行栈，开始执行&lt;/p&gt;
&lt;p&gt;4、主线程不断重复上面的第三步&lt;/p&gt;
&lt;h1 id="5.任务有优先级吗"&gt;5.任务有优先级吗&lt;/h1&gt;&lt;p&gt;任务没有优先级，在消息队列中是一个 FIFO（先进先出）的队列。&lt;/p&gt;
&lt;p&gt;但&lt;strong&gt;消息队列是有优先级的&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint" target="_blank" title="根据 W3C 的最新解释:"&gt;根据 W3C 的最新解释:&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每个任务都有一个任务类型，同一个类型的任务必须在一个任务队列，不同类型的任务可以分属于不同的队列。&lt;br&gt;在一次事件循环中，浏览器可以根据实际情况从不同的队列中取出任务执行。&lt;/li&gt;&lt;li&gt;但&lt;strong&gt;微任务队列&lt;/strong&gt;中的任务优先所有其他任务执行，一旦调用栈变空，微任务就会被执行。&lt;/li&gt;&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;随着浏览器的复杂度急剧提升，W3C 不再使用宏队列的说法&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在目前 chrome 的实现中，至少包含了下面的队列：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;延时队列：用于存放定时器到达后的回调任务，优先级「中」&lt;/li&gt;&lt;li&gt;交互队列：用于存放用户操作后产生的事件处理任务，优先级「高」&lt;/li&gt;&lt;li&gt;微队列：用户存放需要最快执行的任务，优先级「最高」&lt;/li&gt;&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;添加任务到微队列的主要方式主要是使用 Promise、MutationObserver&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1 id="6.代码片段"&gt;6.代码片段&lt;/h1&gt;&lt;h2 id="demo1"&gt;demo1&lt;/h2&gt;&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'script start'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-js"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;setTimeout&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'setTimeout'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-js"&gt;&lt;span class="pun"&gt;},&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;0&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-js"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-js"&gt;&lt;span class="typ"&gt;Promise&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;resolve&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;then&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'promise1'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;})&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;then&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'promise2'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-js"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'script end'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;日志的输出顺序会是什么呢？&lt;/p&gt;
&lt;h3&gt;试一试:&lt;/h3&gt;

&lt;button class="btn test-1"&gt;Run test&lt;/button&gt; &lt;button class="btn clear-log-1"&gt;Clear log&lt;/button&gt;

&lt;style&gt;
.log-output {
  width: 100%;
  box-sizing: border-box;
  height: 12.7rem;
  font: inherit;
  line-height: 1.5;
  margin-top: 10px;
}
&lt;/style&gt;

&lt;p&gt;&lt;textarea class="log-output log-output-1" readonly="readonly"&gt;&lt;/textarea&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;输出的结果是：script start, script end, promise1, promise2, setTimeout&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;为什么会这样？我们来一步步分析（点击箭头试一试）：&lt;/p&gt;
&lt;h3 id="分析："&gt;分析：&lt;/h3&gt;&lt;script&gt;
function log1(str) {
  console.log(str);
  var logEl = document.querySelector('.log-output-1');
  logEl.value += (logEl.value ? '\n' : '') + str;
}

document.querySelector('.clear-log-1').addEventListener('click', function() {
  document.querySelector('.log-output-1').value = '';
});

document.querySelector('.test-1').addEventListener('click', function() {
  log1('script start');

  setTimeout(function() {
    log1('setTimeout');
  }, 0);

  Promise.resolve().then(function() {
    log1('promise1');
  }).then(function() {
    log1('promise2');
  });

  log1('script end');
});
&lt;/script&gt;

&lt;style&gt;
  .event-loop-walkthrough {
    overflow: hidden;
    max-width: 710px;
    background: #eee;
    display: -webkit-flex;
    display: flex;
    -webkit-flex-flow: column;
    flex-flow: column;
    max-height: 90vh;
    height: 430px;
    position: relative;
  }

  @media screen and (min-width: 530px) {
    .event-loop-walkthrough {
      margin: 0;
    }
  }

  .event-loop-walkthrough .code-example {
    position: relative;
    -webkit-transform: translateY(-50px);
    transform: translateY(-50px);
  }

  .event-loop-walkthrough table {
    border-collapse: collapse;
    width: 100%;
    table-layout: fixed;
  }

  .event-loop-walkthrough td {
    padding: 0;
  }

  .task-queue,
  .microtask-queue,
  .js-stack,
  .event-loop-log {
    line-height: 1;
    border-top: 1px solid #fff;
  }

  .task-queue th,
  .microtask-queue th,
  .js-stack th,
  .event-loop-log th {
    font-weight: normal;
    text-align: left;
    padding: 10px 8px !important;
    background: var(--border-secondary);
    vertical-align: top;``
    width: 5.1rem;
  }

  .event-loop-items {
    display: -webkit-flex;
    display: flex;
    overflow: hidden;
    padding-left: 5px;
  }

  .event-loop-rail {
    position: relative;
    display: -webkit-flex;
    display: flex;
  }

  .event-loop-log .event-loop-items {
    -webkit-flex-flow: row wrap;
    flex-flow: row wrap;
  }

  .event-loop-item {
    background: var(--border-secondary);
    margin: 5px;
    padding: 5px;
    margin-left: 0;
    opacity: 0;
    white-space: nowrap;
  }

  .event-loop-item.active {
    background-color: var(--active-color);
  }

  .event-loop-commentary {
    pointer-events: none;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    display: -webkit-flex;
    display: flex;
    -webkit-justify-content: center;
    justify-content: center;
    -webkit-align-items: center;
    align-items: center;
    font-size: 1.3rem;
    color: #fff;
    line-height: 1.2;
    padding: 0 7%;
  }

  @media screen and (min-width: 530px) {
    .event-loop-commentary {
      font-size: 1.7rem;
    }
  }

  .event-loop-commentary-item {
    background: rgba(0, 0, 0, 0.77);
    border-radius: 7px;
    padding: 0.8rem 1.2rem;
    opacity: 0;
  }

  .js-source {
    -webkit-flex: 1;
    flex: 1;
    overflow: hidden;
    position: relative;
  }

  .js-source .line-highlight {
    position: absolute;
    left: 0;
    right: 0;
    top: 4.1rem;
    background: rgba(255, 255, 255, 0.2);
    z-index: 1;
    opacity: 0;
    line-height: 1.45;
    font-size: 1rem;
    font-family: Inconsolata, monospace;
  }

  .js-source .line-highlight::before {
    content: '.Hello';
    color: transparent;
  }

  @media screen and (min-width: 530px) {
    .js-source .line-highlight::before {
      font-size: 1.1rem;
    }
  }

  .event-loop-controls {
    background: var(--border-secondary);
    fill: #6d6d6d;
    padding: 0.2rem;
    height: 2.2rem;
    border-top: 1px solid #fff;
  }

  .event-loop-controls svg {
    height: 100%;
    display: block;
    margin-right: 0;
    margin-left: auto;
  }

  .event-loop-walkthrough .prev-btn,
  .event-loop-walkthrough .next-btn {
    fill: rgba(0, 0, 0, 0);
    cursor: pointer;
  }

  .event-loop-walkthrough table {
    margin-bottom: 0 !important;
  }
  .event-loop-walkthrough table td {
    padding: 0 !important;
    width: 100% !important;
  }
&lt;/style&gt;

&lt;div class="editormd-preview-container markdown-body"&gt;&lt;div class="event-loop-walkthrough event-loop-walkthrough-1"&gt;&lt;div class="js-source"&gt;&lt;div class="line-highlight"&gt;&lt;/div&gt;&lt;div class="code-example" style="transform:translateY(0)"&gt;&lt;div class="language-js"&gt;&lt;pre class="linenums prettyprint prettyprinted"&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;‘script start’&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;setTimeout&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;‘setTimeout’&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-js"&gt;&lt;span class="pun"&gt;},&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;0&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-js"&gt;&lt;span class="typ"&gt;Promise&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;resolve&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;then&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;‘promise1’&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;})&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;then&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;‘promise2’&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;‘script end’&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr class="task-queue"&gt;&lt;th&gt;Tasks&lt;/th&gt;&lt;td&gt;&lt;div class="event-loop-items"&gt;&lt;div class="event-loop-rail"&gt;&lt;div class="event-loop-item"&gt;Run script&lt;/div&gt;&lt;div class="event-loop-item"&gt;setTimeout callback&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr class="microtask-queue"&gt;&lt;th&gt;Microtasks&lt;/th&gt;&lt;td&gt;&lt;div class="event-loop-items"&gt;&lt;div class="event-loop-rail"&gt;&lt;div class="event-loop-item"&gt;Promise then&lt;/div&gt;&lt;div class="event-loop-item"&gt;Promise then&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr class="js-stack"&gt;&lt;th&gt;JS stack&lt;/th&gt;&lt;td&gt;&lt;div class="event-loop-items"&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr class="event-loop-log"&gt;&lt;th&gt;Log&lt;/th&gt;&lt;td&gt;&lt;div class="event-loop-items"&gt;&lt;div class="event-loop-item"&gt;script start&lt;/div&gt;&lt;div class="event-loop-item"&gt;script end&lt;/div&gt;&lt;div class="event-loop-item"&gt;promise1&lt;/div&gt;&lt;div class="event-loop-item"&gt;promise2&lt;/div&gt;&lt;div class="event-loop-item"&gt;setTimeout&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="event-loop-controls"&gt;&lt;svg viewBox="0 0 5 2"&gt;&lt;path d="M2,0 L2,2 L0,1 z"&gt;&lt;/path&gt;&lt;path d="M3,0 L5,1 L3,2 z"&gt;&lt;/path&gt;&lt;path d="M0,0 H2.5V2H0z" class="prev-btn"&gt;&lt;/path&gt;&lt;path d="M2.5,0 H5V2H2.5z" class="next-btn"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;div class="event-loop-commentary"&gt;&lt;div class="event-loop-commentary-item"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;script&gt;
  (function () {
    function transition(el, obj, duration, easing) {
      return new Promise(function (resolve, reject) {
        resolve();
        if (obj.transform) {
          obj['-webkit-transform'] = obj.transform;
        }

        var objKeys = Object.keys(obj);

        if (duration) {
          el.style.transitionProperty = objKeys.join();
          el.style.transitionTimingFunction = easing;
          el.style.transitionDuration = duration + 's';
          el.offsetLeft;

          el.addEventListener('transitionend', function te() {
            el.style.transitionProperty = '';
            el.style.transitionTimingFunction = '';
            el.style.transitionDuration = '';
            resolve();
            el.removeEventListener('transitionend', te);
          });
        } else {
          resolve();
        }

        objKeys.forEach(function (key) {
          el.style.setProperty(key, obj[key]);
        });
      });
    }

    function EventLoopAnimation(el) {
      this._initalState = el;
      this._states = [];
      this._el = el;
      this._queue = Promise.resolve();
      this._reset();
    }

    EventLoopAnimation.prototype._reset = function () {
      var newEl = this._initalState.cloneNode(true);
      this._tasksShown = 0;
      this._microtasksShown = 0;
      this._tasksRemoved = 0;
      this._microtasksRemoved = 0;
      this._logsShown = 0;
      this._currentPos = 0;

      this._el.parentNode.insertBefore(newEl, this._el);
      this._el.parentNode.removeChild(this._el);
      this._el = newEl;
      this._taskRail = this._el.querySelector('.task-queue .event-loop-rail');
      this._microtaskRail = this._el.querySelector('.microtask-queue .event-loop-rail');
      this._jsStack = this._el.querySelector('.js-stack .event-loop-items');
      this._log = this._el.querySelector('.event-loop-log .event-loop-items');
      this._codeBar = this._el.querySelector('.line-highlight');
      this._codePane = this._el.querySelector('.code-example');
      this._commentary = this._el.querySelector('.event-loop-commentary-item');

      var onClick = function (event) {
        var className = event.target.getAttribute('class');
        if (className === 'prev-btn') {
          event.preventDefault();
          if (event.type == 'click') {
            this.back();
          }
        } else if (className === 'next-btn') {
          event.preventDefault();
          if (event.type == 'click') {
            this.forward(true);
          }
        }
      }.bind(this);

      this._el.addEventListener('click', onClick);
      this._el.addEventListener('mousedown', onClick);
    };

    EventLoopAnimation.prototype.forward = function (animate) {
      this._queue = this._queue.then(
        function () {
          var state = this._states[this._currentPos];
          if (!state) return this.goTo(0);
          this._currentPos++;
          return Promise.all(
            state.map(function (func) {
              return func(animate);
            })
          );
        }.bind(this)
      );
    };

    EventLoopAnimation.prototype.goTo = function (pos) {
      this._queue = this._queue.then(
        function () {
          this._reset();
          while (pos--) {
            this.forward(false);
          }
        }.bind(this)
      );
    };

    EventLoopAnimation.prototype.back = function () {
      this._queue = this._queue.then(
        function () {
          if (this._currentPos === 0) return this.goTo(this._states.length);
          return this.goTo(this._currentPos - 1);
        }.bind(this)
      );
    };

    EventLoopAnimation.prototype.state = function () {
      this._states.push([]);
      return this;
    };

    EventLoopAnimation.prototype.action = function (func) {
      this._states[this._states.length - 1].push(func);
      return this;
    };

    EventLoopAnimation.prototype.pushTask = function (activated) {
      return this.action(
        function (animate) {
          var newTask = this._taskRail.children[this._tasksShown];
          this._tasksShown++;

          if (activated) {
            newTask.style.backgroundColor = 'var(--active-color)';
          }

          return transition(
            newTask,
            {
              opacity: 1
            },
            0.2 * animate,
            'ease-in-out'
          );
        }.bind(this)
      );
    };

    EventLoopAnimation.prototype.pushMicrotask = function () {
      return this.action(
        function (animate) {
          var newTask = this._microtaskRail.children[this._microtasksShown];
          this._microtasksShown++;

          return transition(
            newTask,
            {
              opacity: 1
            },
            0.2 * animate,
            'ease-in-out'
          );
        }.bind(this)
      );
    };

    EventLoopAnimation.prototype.pushStack = function (text) {
      return this.action(
        function (animate) {
          var div = document.createElement('div');
          div.className = 'event-loop-item';
          div.textContent = text;
          div.style.backgroundColor = 'var(--active-color)';
          this._jsStack.appendChild(div);
          return transition(
            div,
            {
              opacity: 1
            },
            0.2 * animate,
            'ease-in-out'
          );
        }.bind(this)
      );
    };

    EventLoopAnimation.prototype.popStack = function (text) {
      return this.action(
        function (animate) {
          var div = this._jsStack.children[this._jsStack.children.length - 1];
          return transition(
            div,
            {
              opacity: 0
            },
            0.2 * animate,
            'ease-in-out'
          ).then(
            function () {
              this._jsStack.removeChild(div);
            }.bind(this)
          );
        }.bind(this)
      );
    };

    EventLoopAnimation.prototype.showCodeBar = function () {
      return this.action(
        function (animate) {
          return transition(
            this._codeBar,
            {
              opacity: 1
            },
            0.2 * animate,
            'ease-in-out'
          );
        }.bind(this)
      );
    };

    EventLoopAnimation.prototype.hideCodeBar = function () {
      return this.action(
        function (animate) {
          return transition(
            this._codeBar,
            {
              opacity: 0
            },
            0.2 * animate,
            'ease-in-out'
          );
        }.bind(this)
      );
    };

    EventLoopAnimation.prototype.pushLog = function () {
      return this.action(
        function (animate) {
          var newLog = this._log.children[this._logsShown];
          this._logsShown++;

          return transition(
            newLog,
            {
              opacity: 1
            },
            0.2 * animate,
            'ease-in-out'
          );
        }.bind(this)
      );
    };

    EventLoopAnimation.prototype.moveToLine = function (num) {
      return this.action(
        function (animate) {
          let lineNum = document
            .querySelector('.prettyprint .linenums')
            .children[0].getBoundingClientRect();

          let translateY = (num - 1) * -lineNum.height - 16 + this._codeBar.offsetTop - 1;
          return transition(
            this._codePane,
            {
              transform: 'translateY(' + translateY + 'px)'
            },
            0.3 * animate,
            'ease-in-out'
          );
        }.bind(this)
      );
    };

    EventLoopAnimation.prototype.commentary = function (text) {
      return this.action(
        function (animate) {
          this._commentary.textContent = text;
          return transition(
            this._commentary,
            {
              opacity: 1
            },
            0.2 * animate,
            'ease-in-out'
          );
        }.bind(this)
      );
    };

    EventLoopAnimation.prototype.hideCommentary = function () {
      return this.action(
        function (animate) {
          return transition(
            this._commentary,
            {
              opacity: 0
            },
            0.2 * animate,
            'ease-in-out'
          );
        }.bind(this)
      );
    };

    EventLoopAnimation.prototype.activateMicrotask = function () {
      return this.action(
        function (animate) {
          var div = this._microtaskRail.children[this._microtasksRemoved];
          return transition(
            div,
            {
              'background-color': 'var(--active-color)'
            },
            0.2 * animate,
            'ease-in-out'
          );
        }.bind(this)
      );
    };

    EventLoopAnimation.prototype.shiftMicrotask = function () {
      return this.action(
        function (animate) {
          this._microtasksRemoved++;
          var offset;
          var offsetEl = this._microtaskRail.children[this._microtasksRemoved];

          if (offsetEl) {
            offset = offsetEl.offsetLeft;
          } else {
            offset = this._microtaskRail.offsetWidth;
          }

          return transition(
            this._microtaskRail,
            {
              transform: 'translateX(' + -offset + 'px)'
            },
            0.3 * animate,
            'ease-in-out'
          );
        }.bind(this)
      );
    };

    EventLoopAnimation.prototype.activateTask = function () {
      return this.action(
        function (animate) {
          var div = this._taskRail.children[this._tasksRemoved];
          return transition(
            div,
            {
              'background-color': 'var(--active-color)'
            },
            0.2 * animate,
            'ease-in-out'
          );
        }.bind(this)
      );
    };

    EventLoopAnimation.prototype.shiftTask = function () {
      return this.action(
        function (animate) {
          this._tasksRemoved++;
          var offset;
          var offsetEl = this._taskRail.children[this._tasksRemoved];

          if (offsetEl) {
            offset = offsetEl.offsetLeft;
          } else {
            offset = this._taskRail.offsetWidth;
          }

          return transition(
            this._taskRail,
            {
              transform: 'translateX(' + -offset + 'px)'
            },
            0.3 * animate,
            'ease-in-out'
          );
        }.bind(this)
      );
    };

    window.EventLoopAnimation = EventLoopAnimation;
  })();

  new EventLoopAnimation(document.querySelector('.event-loop-walkthrough-1'))
    .state()
    .moveToLine(1)
    .pushTask(true)
    .pushStack('script')
    .showCodeBar()
    .state()
    .pushLog()
    .state()
    .moveToLine(3)
    .state()
    .commentary('setTimeout callbacks are queued as tasks')
    .state()
    .hideCommentary()
    .pushTask()
    .state()
    .moveToLine(8)
    .state()
    .commentary('Promise callbacks are queued as microtasks')
    .state()
    .hideCommentary()
    .pushMicrotask()
    .state()
    .moveToLine(15)
    .state()
    .pushLog()
    .state()
    .hideCodeBar()
    .popStack()
    .state()
    .commentary('At the end of a task, we process microtasks')
    .state()
    .hideCommentary()
    .activateMicrotask()
    .state()
    .showCodeBar()
    .moveToLine(9)
    .pushStack('Promise callback')
    .state()
    .pushLog()
    .state()
    .hideCodeBar()
    .commentary(
      "This promise callback returns 'undefined', which queues the next promise callback as a microtask"
    )
    .state()
    .hideCommentary()
    .pushMicrotask()
    .state()
    .popStack()
    .commentary('This microtask is done so we move onto the next one in the queue')
    .state()
    .hideCommentary()
    .state()
    .shiftMicrotask()
    .activateMicrotask()
    .state()
    .showCodeBar()
    .moveToLine(12)
    .pushStack('Promise callback')
    .state()
    .pushLog()
    .state()
    .hideCodeBar()
    .popStack()
    .shiftMicrotask()
    .state()
    .commentary("And that's this task done! The browser may update rendering")
    .state()
    .hideCommentary()
    .state()
    .shiftTask()
    .activateTask()
    .state()
    .showCodeBar()
    .moveToLine(4)
    .pushStack('setTimeout callback')
    .state()
    .pushLog()
    .state()
    .hideCodeBar()
    .popStack()
    .state()
    .shiftTask()
    .state()
    .commentary('finish');
&lt;/script&gt;

&lt;h2 id="demo2"&gt;demo2&lt;/h2&gt;&lt;p&gt;有 2 个 div，一个 div 里面嵌着另一个 div&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-html"&gt;&lt;span class="tag"&gt;&amp;lt;div&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="atn"&gt;class&lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="atv"&gt;"outer"&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-html"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="tag"&gt;&amp;lt;div&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="atn"&gt;class&lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="atv"&gt;"inner"&lt;/span&gt;&lt;span class="tag"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-html"&gt;&lt;span class="tag"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;p&gt;给定下面的JS，如果点击里面的 div.inner 会输出什么?&lt;/p&gt;
&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-js"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-js"&gt;&lt;span class="com"&gt;// Let's get hold of those elements&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-js"&gt;&lt;span class="kwd"&gt;var&lt;/span&gt;&lt;span class="pln"&gt; outer &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; document&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;querySelector&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'.outer'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-js"&gt;&lt;span class="kwd"&gt;var&lt;/span&gt;&lt;span class="pln"&gt; inner &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; document&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;querySelector&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'.inner'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-js"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-js"&gt;&lt;span class="com"&gt;// Let's listen for attribute changes on the&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-js"&gt;&lt;span class="com"&gt;// outer element&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-js"&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;MutationObserver&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'mutate'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-js"&gt;&lt;span class="pun"&gt;}).&lt;/span&gt;&lt;span class="pln"&gt;observe&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;outer&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  attributes&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;true&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-js"&gt;&lt;span class="pun"&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-js"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-js"&gt;&lt;span class="com"&gt;// Here's a click listener…&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-js"&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; onClick&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'click'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-js"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  setTimeout&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'timeout'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;},&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;0&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-js"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="typ"&gt;Promise&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;resolve&lt;/span&gt;&lt;span class="pun"&gt;().&lt;/span&gt;&lt;span class="pln"&gt;then&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'promise'&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-js"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  outer&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;setAttribute&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'data-random'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;Math&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;random&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-js"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-js"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-js"&gt;&lt;span class="com"&gt;// …which we'll attach to both elements&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;inner&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addEventListener&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'click'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; onClick&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;outer&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addEventListener&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;'click'&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; onClick&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;
&lt;h3&gt;试一试:&lt;/h3&gt;

&lt;p&gt;点击内部方块触发点击事件:&lt;/p&gt;
&lt;style&gt;
.outer-test {
  background: #D4D4D4;
  padding: 25px;
  width: 150px;
  margin: 0 auto;
}

.inner-test {
  background: #ADADAD;
  padding: 50px;
  width: 0;
}
&lt;/style&gt;

&lt;div class="outer-test"&gt;&lt;div class="inner-test"&gt;&lt;/div&gt;&lt;/div&gt;

&lt;button class="btn clear-log-2"&gt;Clear log&lt;/button&gt;

&lt;p&gt;&lt;textarea class="log-output log-output-2" readonly="readonly"&gt;&lt;/textarea&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;输出的结果是：click, promise, mutate, click, promise, mutate, timeout, timeout&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;“点击” 事件是一个任务。Mutation observer 和promise callbacks 是作为微任务排队的。setTimeout 回调作为一个任务排队。所以，事情是这样的：&lt;/p&gt;
&lt;script&gt;

var targetLogOutput;

function log2(str) {
  console.log(str);
  var el;

  el = document.querySelector('.log-output-2');
  el.value += (el.value ? '\n' : '') + str;
}

document.querySelector('.clear-log-2').addEventListener('click', function() {
  document.querySelector('.log-output-2').value = '';
});


var outer = document.querySelector('.outer-test');
var inner = document.querySelector('.inner-test');


new MutationObserver(function() {
  log2('mutate');
}).observe(outer, {
  attributes: true
});


function onClick() {
  log2('click');

  setTimeout(function() {
    log2('timeout');
  },0);

  Promise.resolve().then(function() {
    log2('promise');
  });

  outer.setAttribute('data-random', Math.random());
}


inner.addEventListener('click', onClick);
outer.addEventListener('click', onClick);
&lt;/script&gt;


&lt;h3 id="分析："&gt;分析：&lt;/h3&gt;&lt;div class="editormd-preview-container markdown-body"&gt;&lt;div class="event-loop-walkthrough event-loop-walkthrough-2"&gt;&lt;div class="js-source"&gt;&lt;div class="line-highlight"&gt;&lt;/div&gt;&lt;div class="code-example" style="transform:translateY(0)"&gt;&lt;div class="language-js"&gt;&lt;pre class="linenums prettyprint prettyprinted"&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code class="lang-js"&gt;&lt;span class="com"&gt;// Let’s get hold of those elements&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-js"&gt;&lt;span class="kwd"&gt;var&lt;/span&gt;&lt;span class="pln"&gt; outer &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; document&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;querySelector&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;‘.outer’&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-js"&gt;&lt;span class="kwd"&gt;var&lt;/span&gt;&lt;span class="pln"&gt; inner &lt;/span&gt;&lt;span class="pun"&gt;=&lt;/span&gt;&lt;span class="pln"&gt; document&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;querySelector&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;‘.inner’&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-js"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-js"&gt;&lt;span class="com"&gt;// Let’s listen for attribute changes on the&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-js"&gt;&lt;span class="com"&gt;// outer element&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-js"&gt;&lt;span class="kwd"&gt;new&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="typ"&gt;MutationObserver&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;‘mutate’&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-js"&gt;&lt;span class="pun"&gt;}).&lt;/span&gt;&lt;span class="pln"&gt;observe&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="pln"&gt;outer&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;&lt;/span&gt;&lt;span class="pln"&gt;attributes&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="kwd"&gt;true&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-js"&gt;&lt;span class="pun"&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-js"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-js"&gt;&lt;span class="com"&gt;// Here’s a click listener…&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-js"&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; onClick&lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;‘click’&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-js"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  setTimeout&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;‘timeout’&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;   &lt;/span&gt;&lt;span class="pun"&gt;},&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="lit"&gt;0&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-js"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L0"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="typ"&gt;Promise&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;resolve&lt;/span&gt;&lt;span class="pun"&gt;().&lt;/span&gt;&lt;span class="pln"&gt;then&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="kwd"&gt;function&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;()&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;    console&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;log&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;‘promise’&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="pun"&gt;});&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code class="lang-js"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;  outer&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;setAttribute&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;‘data-random’&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt;   &lt;/span&gt;&lt;span class="typ"&gt;Math&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;random&lt;/span&gt;&lt;span class="pun"&gt;());&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L5"&gt;&lt;code class="lang-js"&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L6"&gt;&lt;code class="lang-js"&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L7"&gt;&lt;code class="lang-js"&gt;&lt;span class="com"&gt;// …which we’ll attach to both elements&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L8"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;inner&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addEventListener&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;‘click’&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; onClick&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L9"&gt;&lt;code class="lang-js"&gt;&lt;span class="pln"&gt;outer&lt;/span&gt;&lt;span class="pun"&gt;.&lt;/span&gt;&lt;span class="pln"&gt;addEventListener&lt;/span&gt;&lt;span class="pun"&gt;(&lt;/span&gt;&lt;span class="str"&gt;‘click’&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="pln"&gt; onClick&lt;/span&gt;&lt;span class="pun"&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;table&gt;&lt;tbody&gt;&lt;tr class="task-queue"&gt;&lt;th&gt;Tasks&lt;/th&gt;&lt;td&gt;&lt;div class="event-loop-items"&gt;&lt;div class="event-loop-rail"&gt;&lt;div class="event-loop-item"&gt;Dispatch click&lt;/div&gt;&lt;div class="event-loop-item"&gt;setTimeout callback&lt;/div&gt;&lt;div class="event-loop-item"&gt;setTimeout callback&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr class="microtask-queue"&gt;&lt;th&gt;Microtasks&lt;/th&gt;&lt;td&gt;&lt;div class="event-loop-items"&gt;&lt;div class="event-loop-rail"&gt;&lt;div class="event-loop-item"&gt;Promise then&lt;/div&gt;&lt;div class="event-loop-item"&gt;Mutation observers&lt;/div&gt;&lt;div class="event-loop-item"&gt;Promise then&lt;/div&gt;&lt;div class="event-loop-item"&gt;Mutation observers&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr class="js-stack"&gt;&lt;th&gt;JS stack&lt;/th&gt;&lt;td&gt;&lt;div class="event-loop-items"&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr class="event-loop-log"&gt;&lt;th&gt;Log&lt;/th&gt;&lt;td&gt;&lt;div class="event-loop-items"&gt;&lt;div class="event-loop-item"&gt;click&lt;/div&gt;&lt;div class="event-loop-item"&gt;promise&lt;/div&gt;&lt;div class="event-loop-item"&gt;mutate&lt;/div&gt;&lt;div class="event-loop-item"&gt;click&lt;/div&gt;&lt;div class="event-loop-item"&gt;promise&lt;/div&gt;&lt;div class="event-loop-item"&gt;mutate&lt;/div&gt;&lt;div class="event-loop-item"&gt;timeout&lt;/div&gt;&lt;div class="event-loop-item"&gt;timeout&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="event-loop-controls"&gt;&lt;svg viewBox="0 0 5 2"&gt;&lt;path d="M2,0 L2,2 L0,1 z"&gt;&lt;/path&gt;&lt;path d="M3,0 L5,1 L3,2 z"&gt;&lt;/path&gt;&lt;path d="M0,0 H2.5V2H0z" class="prev-btn"&gt;&lt;/path&gt;&lt;path d="M2.5,0 H5V2H2.5z" class="next-btn"&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/div&gt;&lt;div class="event-loop-commentary"&gt;&lt;div class="event-loop-commentary-item"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;

&lt;script&gt;
    new EventLoopAnimation(document.querySelector('.event-loop-walkthrough-2'))
        .state().pushTask(true)
        .state().moveToLine(15).pushStack('onClick').showCodeBar()
        .state().pushLog()
        .state().moveToLine(17)
        .state().pushTask()
        .state().moveToLine(21)
        .state().pushMicrotask()
        .state().moveToLine(25)
        .state().commentary("This mutation queues a microtask to handle observers")
        .state().hideCommentary().pushMicrotask()
        .state().hideCodeBar().popStack()
        .state().commentary("Although we're mid-task, microtasks are processed after callbacks if the stack is empty")
        .state().hideCommentary().activateMicrotask()
        .state().showCodeBar().moveToLine(22).pushStack('Promise callback')
        .state().pushLog()
        .state().hideCodeBar().popStack().shiftMicrotask().activateMicrotask()
        .state().showCodeBar().moveToLine(8).pushStack('Mutation callback')
        .state().pushLog()
        .state().hideCodeBar().popStack().shiftMicrotask()
        .state().commentary("The event bubbles, so our callback is called again for the outer element")
        .state().hideCommentary().moveToLine(15).pushStack('onClick').showCodeBar()
        .state().pushLog()
        .state().moveToLine(17)
        .state().pushTask()
        .state().moveToLine(21)
        .state().pushMicrotask()
        .state().moveToLine(25)
        .state().pushMicrotask()
        .state().hideCodeBar().popStack()
        .state().activateMicrotask()
        .state().showCodeBar().moveToLine(22).pushStack('Promise callback')
        .state().pushLog()
        .state().hideCodeBar().popStack().shiftMicrotask().activateMicrotask()
        .state().showCodeBar().moveToLine(8).pushStack('Mutation callback')
        .state().pushLog()
        .state().hideCodeBar().popStack().shiftMicrotask()
        .state().shiftTask().activateTask()
        .state().showCodeBar().moveToLine(18).pushStack('setTimeout callback')
        .state().pushLog()
        .state().popStack().hideCodeBar().shiftTask().activateTask()
        .state().showCodeBar().pushStack('setTimeout callback')
        .state().pushLog()
        .state().popStack().hideCodeBar().shiftTask()
        .state().commentary('finish');
&lt;/script&gt;

&lt;p&gt;因为事件冒泡，点击内部的 div，也会触发外部 div 的点击事件，外部的 div 再调用回调函数，但内部 div 的 setTimerout 并未被执行， 所以，也验证了上面第 5 点所说的，交互任务的优先级高于定时任务。&lt;/p&gt;
&lt;h1 id="7.总结"&gt;7.总结&lt;/h1&gt;&lt;p&gt;本文介绍了浏览器事件循环的概念、原理和工作流程。了解了同步和异步，任务的优先级，并通过代码片断来验证任务执行顺序。&lt;/p&gt;
&lt;p&gt;事件循环又叫做消息循环，是浏览器渲染主线程的工作方式。单线程是异步产生的原因，事件循环是异步的实现方式。&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/chromium/chromium/blob/main/base/message_loop/message_pump_default.cc" target="_blank" title="在 Chrome 的源码中，它开启一个不会结束的 for 循环"&gt;在 Chrome 的源码中，它开启一个不会结束的 for 循环&lt;/a&gt;，每次循环从消息队列中取出第一个任务执行，而其他线程只需要在合适的时候将任务加入到队列末尾即可。&lt;/p&gt;
&lt;p&gt;过去把消息队列简单分为宏队列和微队列，这种说法目前已无法满足复杂的浏览器环境，取而代之的是一种更加灵活多变的处理方式。&lt;/p&gt;
&lt;p&gt;根据 W3C 官方的解释，每个任务有不同的类型，同类型的任务必须在同一个队列，不同的任务可以属于不同的队列。不同任务队列有不同的优先级，在一次事件循环中，由浏览器自行决定取哪一个队列的任务。但浏览器必须有一个微队列，微队列的任务一定具有最高的优先级，必须优先调度执行。&lt;/p&gt;
&lt;p&gt;对于Web开发人员来说，深入了解浏览器事件循环机制是非常重要的。只有通过合理的异步编程技术和对 JavaScript 引擎的理解，才能写出高效、健壮的 Web 应用程序。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;参考：&lt;/p&gt;
&lt;p&gt;&lt;a href="https://blog.xnim.me/event-loop-and-render-queue" target="_blank" title=" Browser Event loop: micro and macro tasks, call stack, render queue: layout, paint, composite"&gt; Browser Event loop: micro and macro tasks, call stack, render queue: layout, paint, composite&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://felixgerschau.com/javascript-event-loop-call-stack/#call-stack" target="_blank"&gt;JavaScript Event Loop And Call Stack Explained&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/" target="_blank" title="Tasks, microtasks, queues and schedules"&gt;Tasks, microtasks, queues and schedules &lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;</content>
    <summary type="text">介绍了浏览器事件循环的概念、原理和工作流程。了解了同步和异步，任务的优先级，并通过代码片断来验证任务执行顺序。</summary>
  </entry>
  <entry>
    <title>使用 GitHub REST API 将博客同步到 GitHub</title>
    <link rel="alternate" href="https://www.ruanchaomin.com/blog/posts/223" />
    <category term="其他" scheme="https://www.ruanchaomin.com/blog/other" />
    <author>
      <name>阮超民</name>
      <uri>https://www.ruanchaomin.com/</uri>
    </author>
    <id>223</id>
    <updated>2026-05-02T08:31:09Z</updated>
    <published>2022-08-29T16:09:05Z</published>
    <content type="html">&lt;div class="markdown-body editormd-preview-container" previewcontainer="true"&gt;&lt;h1 id="前言"&gt;前言&lt;/h1&gt;&lt;p&gt;在写博客的过程中，往往一篇博客都会经过几次修改，将每次修改的地方产生一个历史版本可以做对比，现在很多的记笔记软件都有历史版本这个功能，如果自己去开发这个功能稍微会有点麻烦，就想到了 GitHub，在博客修改或发布时同步到 GitHub，在 GitHub 上查看历史版本，同时作为远程备份。&lt;/p&gt;
&lt;h1 id="效果"&gt;效果&lt;/h1&gt;&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/77e3e7def0fc4e92b739e7667f766746.gif" alt=""&gt;
&lt;/p&gt;&lt;h1 id="REST 介绍"&gt;REST 介绍&lt;/h1&gt;&lt;p&gt;REST（Representational State Transfer，表现层状态转换）是一个架构风格、设计风格，它没有一个明确的标准，只是提供了一个架构的设计原则。如果一个架构符合 REST 原则，就称它为 RESTful 架构。它首次出现在 2000 年 Roy Thomas Fielding 的博士论文中，在论文中提到：”我这篇文章的写作目的，就是想在符合架构原理的前提下，理解和评估以网络为基础的应用软件的架构设计，得到一个功能强、性能好、适宜通信的架构。”&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/bc828e1a34554fce8f5686a299c9f08d.png" alt=""&gt;
&lt;/p&gt;&lt;h1 id="GitHub REST API"&gt;GitHub REST API&lt;/h1&gt;&lt;p&gt; &lt;a href="https://docs.github.com/en/rest/quickstart" target="_blank" title="GitHub REST API"&gt;GitHub REST API&lt;/a&gt; 是典型的 REST 风格的 web API，它几乎支持一切的 GitHub 操作，如基本的创建 repository、提交、搜索、发布 issue、删库跑路等等。&lt;/p&gt;
&lt;h2 id="例如获取某个用户的公开可用信息"&gt;例如获取某个用户的公开可用信息&lt;/h2&gt;&lt;p&gt;&lt;a href="https://docs.github.com/en/rest/users/users#get-a-user" target="_blank" title="Get a user"&gt;Get a user&lt;/a&gt; 获取某个用户的公开可用信息，如用户的ID、name、email、注册时间等等。&lt;br&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/075ca9c042ff4fdea4075d9cb2720a92.png" alt=""&gt;&lt;br&gt;每个 API 官网文档都详细的介绍了参数、HTTP响应状态码等，并且有 CURL、JavaScript、GitHub CLI 的代码示例，我们使用 Postman 来试一试：
&lt;/p&gt;&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/41b51a3883a144f2b3a64288bddae139.png" alt=""&gt;
&lt;/p&gt;&lt;p&gt;可以看见成功获取到了我的 GitHub 账号的一些信息。&lt;/p&gt;
&lt;h1 id="同步博客"&gt;同步博客&lt;/h1&gt;&lt;p&gt;我的博客服务端是使用 JAVA 开发，调用 GitHub REST API 是通过服务端来调用，当然了也可以在前端使用官方代码示例中的 Octokit.js 来调用。&lt;/p&gt;
&lt;p&gt;主要使用 GitHub REST 中的 &lt;a href="https://docs.github.com/en/rest/repos/contents" target="_blank" title="Repository contents API 
"&gt;Repository contents API 
&lt;/a&gt;，此 API 可以在仓库中 创建、修改和删除 Base64 编码的内容。此 API 需要验证账号权限。&lt;/p&gt;
&lt;h2 id="1.权限认证 Authentication"&gt;1.权限认证 Authentication&lt;/h2&gt;&lt;p&gt;有两种方法可以对 GitHub REST API进行身份验证。在某些地方，需要身份验证的请求将返回404 Not Found，而不是 403 Forbidden。这是为了防止私有存储库意外泄露给未经授权的用户。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Basic authentication&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code&gt;&lt;span class="pln"&gt;$ curl &lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="pln"&gt;u username&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt;token https&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="com"&gt;//api.github.com/user&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;&lt;/li&gt;&lt;li&gt;OAuth2 token (sent in a header)&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code&gt;&lt;span class="pln"&gt;$ curl &lt;/span&gt;&lt;span class="pun"&gt;-&lt;/span&gt;&lt;span class="pln"&gt;H &lt;/span&gt;&lt;span class="str"&gt;"Authorization: Bearer OAUTH-TOKEN"&lt;/span&gt;&lt;span class="pln"&gt; https&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="com"&gt;//api.github.com&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code&gt;&lt;span class="com"&gt;//在大多数情况下，可以使用 Authorization: Bearer 或 Authorization: token 传递令牌。 但是，如果要传递 JSON Web 令牌 (JWT)，则必须使用 Authorization: Bearer。&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;h2 id="2.创建 Token"&gt;2.创建 Token&lt;/h2&gt;&lt;p&gt;创建个人访问令牌 token 来代替账号密码，如何创建可以参考官方介绍：&lt;a href="https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token" target="_blank" title="Create a PAT"&gt;Create a PAT&lt;/a&gt;&lt;br&gt;令牌的作用域权限只需要 repo 就够了，生成后的令牌只会显示一次！
&lt;/p&gt;&lt;h2 id="3.创建文件内容"&gt;3.创建文件内容&lt;/h2&gt;&lt;p&gt;请求方法：PUT&lt;br&gt;请求路径：&lt;a href="https://api.github.com/repos/用户名/仓库名/contents/文件路径" target="_blank"&gt;https://api.github.com/repos/用户名/仓库名/contents/文件路径&lt;/a&gt;&lt;br&gt;JSON参数：
&lt;/p&gt;&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="str"&gt;"message"&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;"commit message"&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="com"&gt;// 提交的信息&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="str"&gt;"content"&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;"aGVsbG8gd29ybGQgIQ=="&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 文件内容，Base64编码&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;&lt;p&gt;Example:&lt;br&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/c525eb3333bc49a69a25494bf0ce8d28.png" alt=""&gt;&lt;br&gt;创建成功：
&lt;/p&gt;&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/84e81e3c15a9430683e9c6d714def9b2.png" alt=""&gt;&lt;br&gt;此 API 需要 Token 才能访问，在 Headers 中加上 Authorization&lt;br&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/6175a7c1163b4cf7a89317acfc697493.png" alt=""&gt;
&lt;/p&gt;&lt;h2 id="4.更新文件内容"&gt;4.更新文件内容&lt;/h2&gt;&lt;p&gt;更新比创建多一个sha参数，就是上面创建成功之后返回的sha&lt;/p&gt;
&lt;p&gt;请求方法：PUT&lt;br&gt;请求路径：&lt;a href="https://api.github.com/repos/用户名/仓库名/contents/文件路径" target="_blank"&gt;https://api.github.com/repos/用户名/仓库名/contents/文件路径&lt;/a&gt;&lt;br&gt;JSON参数：
&lt;/p&gt;&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="str"&gt;"message"&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;"update message"&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="com"&gt;// 提交信息&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="str"&gt;"content"&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;"aGVsbG8gd29ybGQgIQoK5L2g5aW977yB"&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="com"&gt;// 文件内容，Base64编码&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="str"&gt;"sha"&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="str"&gt;"c52e00fbdd1730341db890f4c1bc23b492601870"&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="com"&gt;// 创建成功时 API 返回的 sha&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L4"&gt;&lt;code&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;&lt;p&gt;Example:&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/cdc85d44f3174f9db8cebce15723906f.png" alt=""&gt;&lt;br&gt;更新成功：
&lt;/p&gt;&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/6bab240382df4ca8a87e8136a6cda0d1.png" alt=""&gt;
&lt;/p&gt;&lt;h2 id="5.删除文件"&gt;5.删除文件&lt;/h2&gt;&lt;p&gt;请求方法：DELETE&lt;br&gt;请求路径：&lt;a href="https://api.github.com/repos/用户名/仓库名/contents/文件路径" target="_blank"&gt;https://api.github.com/repos/用户名/仓库名/contents/文件路径&lt;/a&gt;&lt;br&gt;JSON参数：
&lt;/p&gt;&lt;pre class="prettyprint linenums prettyprinted" style=""&gt;&lt;ol class="linenums"&gt;&lt;li class="L0"&gt;&lt;code&gt;&lt;span class="pun"&gt;{&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L1"&gt;&lt;code&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="str"&gt;"message"&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="pln"&gt; &lt;/span&gt;&lt;span class="str"&gt;"delete message"&lt;/span&gt;&lt;span class="pun"&gt;,&lt;/span&gt;&lt;span class="com"&gt;// 提交信息&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L2"&gt;&lt;code&gt;&lt;span class="pln"&gt;  &lt;/span&gt;&lt;span class="str"&gt;"sha"&lt;/span&gt;&lt;span class="pun"&gt;:&lt;/span&gt;&lt;span class="str"&gt;"14d773b65db1d8aacafd7050444822b08fd04ae6"&lt;/span&gt;&lt;span class="com"&gt;// 创建或者更新时 API 返回的 sha&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;li class="L3"&gt;&lt;code&gt;&lt;span class="pun"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/pre&gt;&lt;p&gt;Example:&lt;br&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/d281ca0082e5422bb19dbfba0ef1abd7.png" alt=""&gt;&lt;br&gt;删除成功：&lt;br&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/537851440b3e4b3a993d7bb502cc933a.png" alt=""&gt;
&lt;/p&gt;&lt;h2 id="6.总结"&gt;6.总结&lt;/h2&gt;&lt;p&gt;以上就是对使用 GitHub REST API 对仓库内容进行创建、修改、删除操作的说明，GitHub 的提交记录：&lt;br&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/1eb3ad9e3ef64ccfa668fcdcc61c94bd.png" alt=""&gt;&lt;br&gt;参考：
&lt;/p&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://docs.github.com/en/rest" target="_blank" title="GitHub REST API"&gt;GitHub REST API&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;</content>
    <summary type="text">介绍了 GitHub REST API，使用 Repository contents API  创建仓库文件内容</summary>
  </entry>
  <entry>
    <title>Hello World!</title>
    <link rel="alternate" href="https://www.ruanchaomin.com/blog/posts/161" />
    <category term="闲言碎语" scheme="https://www.ruanchaomin.com/blog/gossip" />
    <author>
      <name>阮超民</name>
      <uri>https://www.ruanchaomin.com/</uri>
    </author>
    <id>161</id>
    <updated>2026-04-26T23:35:02Z</updated>
    <published>2022-04-03T15:27:46Z</published>
    <content type="html">&lt;div class="markdown-body editormd-preview-container" previewcontainer="true"&gt;&lt;h1 id="前言"&gt;前言&lt;/h1&gt;&lt;p&gt;由于疫情原因，今年没有回老家过年，这也是第一次在杭州过年。&lt;br&gt;终于有时间把我的个人网站重构，于是从大年初一开始了我的开发计划。经过两个月的努力，第一版本终于上线了！
&lt;/p&gt;&lt;h1 id="技术栈"&gt;技术栈&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;前端前台 Angular、TypeScript、Rxjs&lt;/li&gt;&lt;li&gt;前端后台 Angular、TypeScript、Rxjs、NG-ZORRO、Editor.md&lt;/li&gt;&lt;li&gt;后端服务 Spring Boot、Spring Security、JWT、MyBatis-Plus&lt;/li&gt;&lt;li&gt;数据库 MySQL&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://image.ruanchaomin.com/blog/2026/01/backend-article.jpg" alt=""&gt;
&lt;/p&gt;&lt;p align="center" style="text-align: center;"&gt;后台管理添加文章界面&lt;/p&gt;

&lt;h1 id="为什么写博客"&gt;为什么写博客&lt;/h1&gt;&lt;h2 id="1. 记录"&gt;1. 记录&lt;/h2&gt;&lt;p&gt;记录，成为更好的自己。人生中有太多美好或深刻的瞬间，无论是学到的新知识还是生活点滴，许久之后，再翻看自己曾经写过的文章，一定会感觉到自己的点滴变化和进步。&lt;/p&gt;
&lt;h2 id="2. 分享"&gt;2. 分享&lt;/h2&gt;&lt;p&gt;写博客的过程其实也是分享自己学习收获的过程，在学习的过程和日常的开发中，难免会遇到一些问题，也要去网络寻找答案，所以知识只有分享才有存在的价值！&lt;/p&gt;
&lt;h2 id="3. 讨论"&gt;3. 讨论&lt;/h2&gt;&lt;p&gt;大家一起讨论问题，或赞同，或反对，听听别人的想法，可以在交流中成长。&lt;/p&gt;
&lt;h1 id="总结"&gt;总结&lt;/h1&gt;&lt;p&gt;对于一个程序员来说，写博客可以记录自己的成长经历，加深对技术点的理解，结交更多志同道合的朋友，在自己进步的同时，帮助他人。&lt;/p&gt;
&lt;/div&gt;</content>
    <summary type="text">第一篇博客</summary>
  </entry>
</feed>
