<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Cain的个人网站</title><description>Mc_Cain 的个人博客，记录前端学习、JavaScript、Vue、React 和开发实践。</description><link>https://cjw32.xyz/blog/</link><language>zh</language><item><title>用GPT学英语--第一课</title><link>https://cjw32.xyz/blog/article/ai-8d70640ed21172ef4de7844d/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/ai-8d70640ed21172ef4de7844d/</guid><description>用 GPT 学英语的第一课记录：从词性（名词、动词、形容词、代词）与句子成分（主语、谓语、宾语）的区别讲起，解释 I like music 与 I am happy 为何一个用实义动词、一个需要系动词，梳理主谓宾与主系表两大基本句型，并附随堂练习、批改与第一课总结。</description><pubDate>Sat, 10 Oct 2026 01:45:42 GMT</pubDate><content:encoded>&lt;h1 id=&quot;用gpt学英语--第一课&quot;&gt;用GPT学英语--第一课&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#用gpt学英语--第一课&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Lesson 1 — Parts of Speech &amp;#x26; Sentence Elements&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;今天先不讲复杂的语法规则，只解决三个问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;什么是词性？&lt;/li&gt;
&lt;li&gt;什么是句子成分？&lt;/li&gt;
&lt;li&gt;为什么有些句子需要 am、is、are，有些却不需要？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;理解这三个问题之后，就能开始真正分析英语句子的结构了。&lt;/p&gt;
&lt;h2 id=&quot;一什么是词性&quot;&gt;一、什么是词性？&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#一什么是词性&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;先看几个中文词语：苹果、吃、漂亮、我。&lt;/p&gt;
&lt;p&gt;它们属于不同的类别：&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;/ul&gt;
&lt;p&gt;英语也是一样的。&lt;strong&gt;所谓词性，就是根据单词的语法性质和用途，把单词分成不同的类别。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;英语中有多个词性，今天先学习最重要的四种。&lt;/p&gt;
&lt;h3 id=&quot;1-名词noun缩写-n&quot;&gt;1. 名词（Noun，缩写 n.）&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-名词noun缩写-n&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;名词就是表示人、事物、地点或抽象概念的词。&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&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;apple&lt;/td&gt;&lt;td&gt;苹果&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;student&lt;/td&gt;&lt;td&gt;学生&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;school&lt;/td&gt;&lt;td&gt;学校&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;English&lt;/td&gt;&lt;td&gt;英语&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;happiness&lt;/td&gt;&lt;td&gt;幸福&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;I like apples.
我喜欢苹果。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这里的 apples 就是名词。&lt;/p&gt;
&lt;h3 id=&quot;2-动词verb缩写-v&quot;&gt;2. 动词（Verb，缩写 v.）&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-动词verb缩写-v&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;动词一般用来表示动作或者状态。&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&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;eat&lt;/td&gt;&lt;td&gt;吃&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;run&lt;/td&gt;&lt;td&gt;跑&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;study&lt;/td&gt;&lt;td&gt;学习&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;like&lt;/td&gt;&lt;td&gt;喜欢&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;know&lt;/td&gt;&lt;td&gt;知道&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;I study English.
我学习英语。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这里的 study 就是动词。需要注意，动词不一定表示身体上的动作，例如 like（喜欢）、know（知道）也属于动词。&lt;/p&gt;
&lt;h3 id=&quot;3-形容词adjective缩写-adj&quot;&gt;3. 形容词（Adjective，缩写 adj.）&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#3-形容词adjective缩写-adj&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;形容词主要用来描述人或者事物的特点、性质和状态。&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&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;happy&lt;/td&gt;&lt;td&gt;开心的&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;beautiful&lt;/td&gt;&lt;td&gt;漂亮的&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;difficult&lt;/td&gt;&lt;td&gt;困难的&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;good&lt;/td&gt;&lt;td&gt;好的&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;important&lt;/td&gt;&lt;td&gt;重要的&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;English is difficult.
英语很难。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;其中 difficult 就是形容词。&lt;/p&gt;
&lt;h3 id=&quot;4-代词pronoun缩写-pron&quot;&gt;4. 代词（Pronoun，缩写 pron.）&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#4-代词pronoun缩写-pron&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;代词可以用来代替名词或名词短语。&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&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;I&lt;/td&gt;&lt;td&gt;我&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;you&lt;/td&gt;&lt;td&gt;你&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;he&lt;/td&gt;&lt;td&gt;他&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;she&lt;/td&gt;&lt;td&gt;她&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;it&lt;/td&gt;&lt;td&gt;它&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;we&lt;/td&gt;&lt;td&gt;我们&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;they&lt;/td&gt;&lt;td&gt;他们&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;He is a student.
他是一名学生。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这里的 He 就是代词，因为它可以用来指代某个男性，而不必每次都说出他的名字。&lt;/p&gt;
&lt;h2 id=&quot;二什么是句子成分&quot;&gt;二、什么是句子成分？&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#二什么是句子成分&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;这是今天最重要的知识。先区分两个概念：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;词性&lt;/strong&gt;：一个单词属于什么类别。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;句子成分&lt;/strong&gt;：一个单词或词组在句子中承担什么作用。&lt;/li&gt;
&lt;/ul&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;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;I like apples.
我喜欢苹果。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;拆解如下：&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;
























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;单词&lt;/th&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;I&lt;/td&gt;&lt;td&gt;代词&lt;/td&gt;&lt;td&gt;主语&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;like&lt;/td&gt;&lt;td&gt;动词&lt;/td&gt;&lt;td&gt;谓语&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;apples&lt;/td&gt;&lt;td&gt;名词&lt;/td&gt;&lt;td&gt;宾语&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;可见，&lt;strong&gt;词性与句子成分不是同一个概念&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;那么什么是主语、谓语、宾语？&lt;/p&gt;
&lt;h3 id=&quot;1-主语subject&quot;&gt;1. 主语（Subject）&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-主语subject&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;主语通常表示句子主要在谈论谁或者什么。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;I like apples.
是谁喜欢苹果？是 I（我）。
所以 I 是主语。

Tom studies English.
汤姆学习英语。
是谁学习英语？是 Tom。
所以 Tom 是主语。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;2-谓语predicate&quot;&gt;2. 谓语（Predicate）&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-谓语predicate&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在目前学习的简单句中，可以先重点理解「谓语动词」。它表示主语的动作或者状态，是句子的重要核心。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;I eat apples.
这里 eat 就是谓语动词。

She likes music.
这里 likes 就是谓语动词。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;不过要注意：严格来说，英语语法中的完整谓语和谓语动词不是完全相同的概念。现阶段先学会识别谓语动词即可。&lt;/p&gt;
&lt;h3 id=&quot;3-宾语object&quot;&gt;3. 宾语（Object）&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#3-宾语object&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;宾语通常表示动作涉及的对象。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;I eat apples.
吃的是什么？苹果。
所以 apples 是宾语。

I love English.
喜欢什么？英语。
所以 English 是宾语。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;现在你已经理解了英语中非常常见的句子结构：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;主语 + 谓语动词 + 宾语&lt;/strong&gt;，也就是 &lt;strong&gt;Subject + Verb + Object（SVO）&lt;/strong&gt;。&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;主语&lt;/th&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;I&lt;/td&gt;&lt;td&gt;like&lt;/td&gt;&lt;td&gt;music&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;She&lt;/td&gt;&lt;td&gt;studies&lt;/td&gt;&lt;td&gt;English&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;He&lt;/td&gt;&lt;td&gt;plays&lt;/td&gt;&lt;td&gt;football&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;We&lt;/td&gt;&lt;td&gt;eat&lt;/td&gt;&lt;td&gt;apples&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;不过，并不是所有英语句子都有宾语，这就涉及今天的第三个问题。&lt;/p&gt;
&lt;h2 id=&quot;三为什么-i-am-happy-需要-am而-i-like-music-不需要&quot;&gt;三、为什么 I am happy 需要 am，而 I like music 不需要？&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#三为什么-i-am-happy-需要-am而-i-like-music-不需要&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;分析这两个句子。&lt;/p&gt;
&lt;h3 id=&quot;句子i-like-music&quot;&gt;句子①：I like music.&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#句子i-like-music&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;先看三个单词：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I：代词&lt;/li&gt;
&lt;li&gt;like：动词&lt;/li&gt;
&lt;li&gt;music：名词&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以这个句子的结构是：&lt;strong&gt;主语 + 谓语动词 + 宾语&lt;/strong&gt;。这里的 like 本身就是动词，因此不需要再添加一个 am。&lt;/p&gt;
&lt;h3 id=&quot;句子i-am-happy&quot;&gt;句子②：I am happy.&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#句子i-am-happy&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;先看其中两个单词：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I：代词&lt;/li&gt;
&lt;li&gt;happy：形容词&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;注意：&lt;strong&gt;happy 是形容词，而不是动词&lt;/strong&gt;。如果直接写成：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;❌ I happy.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这句话在标准英语中是不正确的。因为英语中的普通陈述句通常需要一个能够充当谓语核心的动词，而 happy 只是形容词。&lt;/p&gt;
&lt;p&gt;这时候就需要使用一个特殊的动词：&lt;strong&gt;be 动词&lt;/strong&gt;。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;I am happy.
She is happy.
They are happy.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这里的 am、is、are 都属于 be 动词的不同形式。在这些句子中，它们属于&lt;strong&gt;系动词（Linking Verb）&lt;/strong&gt;，作用是将主语与描述主语的部分联系起来。而 happy 在句子中充当&lt;strong&gt;表语（Predicative）&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;因此 I am happy 的结构是：&lt;strong&gt;主语 + 系动词 + 表语&lt;/strong&gt;，简称&lt;strong&gt;主系表结构&lt;/strong&gt;。这也是英语中非常重要的基本句型。&lt;/p&gt;
&lt;h3 id=&quot;对比一下&quot;&gt;对比一下&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#对比一下&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;table-wrapper&quot;&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;I like English.&lt;/td&gt;&lt;td&gt;主谓宾&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;I am happy.&lt;/td&gt;&lt;td&gt;主系表&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;She studies English.&lt;/td&gt;&lt;td&gt;主谓宾&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;She is beautiful.&lt;/td&gt;&lt;td&gt;主系表&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;He plays football.&lt;/td&gt;&lt;td&gt;主谓宾&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;He is a student.&lt;/td&gt;&lt;td&gt;主系表&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;注意：第一类句子中，like、study、play 本身就是谓语动词；第二类句子中，am、is、are 是系动词，后面通过形容词或名词短语等来说明主语的状态、特征或身份。&lt;/p&gt;
&lt;p&gt;另外，不是所有主系表结构都必须使用 be 动词，例如 I feel happy（我感到高兴）中的 feel 也可以作系动词。这个以后详细讲。&lt;/p&gt;
&lt;h2 id=&quot;四顺便纠正两个理解&quot;&gt;四、顺便纠正两个理解&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#四顺便纠正两个理解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;关于第三人称单数&quot;&gt;关于第三人称单数&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#关于第三人称单数&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;因为 he、she 要加第三人称单数，所以用 plays。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;理解方向是对的，但表达还不够准确。更准确地说：&lt;strong&gt;在一般现在时的肯定句中，当主语为第三人称单数时，谓语动词通常需要使用第三人称单数形式。&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;I like English.   →   He likes English.
I study English.  →   She studies English.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;但要注意，不是任何情况下都加 s，例如：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;He can play football.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这里 play 就不能变成 plays，因为前面已经有情态动词 can 了。这些规则后面会专门学习。&lt;/p&gt;
&lt;h3 id=&quot;关于三个时态&quot;&gt;关于三个时态&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#关于三个时态&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;① I study English. —— 我学英语。&lt;br&gt;
② I am studying English. —— 我正在学习英语。&lt;br&gt;
③ I studied English. —— 我学过英语。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;前两句基本正确，第三句需要稍微纠正。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I studied English.&lt;/strong&gt; 使用的是一般过去时，通常表示过去某个时间学习了英语，可以理解为「我过去学习过英语」。但如果想表达「我有过学习英语的经历」，有时使用 &lt;strong&gt;I have studied English.&lt;/strong&gt; 更合适。两者区别在于是否侧重过去发生的事情，还是过去经历与现在的联系。&lt;/p&gt;
&lt;p&gt;现阶段只需先理解：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;study：一般现在时&lt;/li&gt;
&lt;li&gt;am studying：现在进行时&lt;/li&gt;
&lt;li&gt;studied：一般过去时&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;现在完成时以后再深入学习。&lt;/p&gt;
&lt;h2 id=&quot;-第一课随堂练习&quot;&gt;📝 第一课随堂练习&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#-第一课随堂练习&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;这次只有四道题，难度不高，重点检查是否真正理解了&lt;strong&gt;词性和句子成分的区别&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&quot;第1题分析单词&quot;&gt;第1题：分析单词&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#第1题分析单词&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;观察句子：&lt;strong&gt;She likes apples.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;① She 的词性是什么？句子成分是什么？&lt;br&gt;
② likes 的词性是什么？句子成分是什么？&lt;br&gt;
③ apples 的词性是什么？句子成分是什么？&lt;/p&gt;
&lt;h3 id=&quot;第2题判断句子结构&quot;&gt;第2题：判断句子结构&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#第2题判断句子结构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;下面两个句子分别属于「主谓宾」还是「主系表」结构？&lt;/p&gt;
&lt;p&gt;① He is a teacher.&lt;br&gt;
② I love music.&lt;/p&gt;
&lt;h3 id=&quot;第3题找出错误&quot;&gt;第3题：找出错误&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#第3题找出错误&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;下面的句子有一处语法错误：&lt;strong&gt;She beautiful.&lt;/strong&gt; 请尝试修改，并解释为什么原句是错误的。&lt;/p&gt;
&lt;h3 id=&quot;第4题尝试自己造句&quot;&gt;第4题：尝试自己造句&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#第4题尝试自己造句&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;分别使用下面两种结构，各写出一个简单的英语句子：&lt;/p&gt;
&lt;p&gt;① 主语 + 谓语动词 + 宾语&lt;br&gt;
② 主语 + 系动词 + 表语&lt;/p&gt;
&lt;h2 id=&quot;我的作答与批改&quot;&gt;我的作答与批改&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#我的作答与批改&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;第1题完全正确-&quot;&gt;第1题：完全正确 ✅&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#第1题完全正确-&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;原句：&lt;strong&gt;She likes apples.&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;




























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;单词&lt;/th&gt;&lt;th&gt;词性判断&lt;/th&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;She&lt;/td&gt;&lt;td&gt;代词&lt;/td&gt;&lt;td&gt;主语&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;likes&lt;/td&gt;&lt;td&gt;动词&lt;/td&gt;&lt;td&gt;谓语&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;apples&lt;/td&gt;&lt;td&gt;名词&lt;/td&gt;&lt;td&gt;宾语&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;h3 id=&quot;第2题完全正确-&quot;&gt;第2题：完全正确 ✅&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#第2题完全正确-&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;① He is a teacher. → 主系表 ✅（He：主语；is：系动词；a teacher：表语）&lt;/p&gt;
&lt;p&gt;② I love music. → 主谓宾 ✅（I：主语；love：谓语动词；music：宾语）&lt;/p&gt;
&lt;h3 id=&quot;第3题修改正确但解释需要纠正-&quot;&gt;第3题：修改正确，但解释需要纠正 🟡&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#第3题修改正确但解释需要纠正-&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;原句：❌ She beautiful.&lt;/p&gt;
&lt;p&gt;修改：✅ She is beautiful.&lt;/p&gt;
&lt;p&gt;修改完全正确，但解释「主语后面不能直接跟宾语，需要系动词连接」存在概念错误：&lt;strong&gt;beautiful 不是宾语，而是表语&lt;/strong&gt;。&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&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;She likes music.&lt;/td&gt;&lt;td&gt;She：主语；likes：谓语动词；music：宾语（动作涉及的对象）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;She is beautiful.&lt;/td&gt;&lt;td&gt;She：主语；is：系动词；beautiful：表语（描述 She 的特征）&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;所以需要记住：&lt;strong&gt;宾语通常表示动作涉及的对象，而表语用来说明主语的身份、性质或状态。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;为什么不能直接写 She beautiful？因为 beautiful 是形容词，不能独立充当这个句子的谓语，需要通过 is 这样的系动词构成完整的句子。&lt;/p&gt;
&lt;p&gt;另外补充一个容易混淆的知识：&lt;strong&gt;表语不一定是形容词，也可以是名词或名词短语。&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;She is beautiful.   （表语是形容词）
She is a teacher.   （表语是名词短语）
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;虽然表语的词性不同，但它们都属于主系表结构。&lt;/p&gt;
&lt;h3 id=&quot;第4题有一个小错误&quot;&gt;第4题：有一个小错误&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#第4题有一个小错误&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;① 主谓宾：&lt;strong&gt;I like football.&lt;/strong&gt; ✅&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;
























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;单词&lt;/th&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;I&lt;/td&gt;&lt;td&gt;代词&lt;/td&gt;&lt;td&gt;主语&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;like&lt;/td&gt;&lt;td&gt;动词&lt;/td&gt;&lt;td&gt;谓语&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;football&lt;/td&gt;&lt;td&gt;名词&lt;/td&gt;&lt;td&gt;宾语&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;② 主系表：&lt;strong&gt;She is student.&lt;/strong&gt; ❌&lt;/p&gt;
&lt;p&gt;正确表达：✅ &lt;strong&gt;She is a student.&lt;/strong&gt;（她是一名学生。）&lt;/p&gt;
&lt;p&gt;主系表结构用对了：She（主语）+ is（系动词）+ a student（表语）。但 student 前面需要加一个 &lt;strong&gt;a&lt;/strong&gt;，这涉及英语中非常重要的知识：&lt;strong&gt;冠词（Article）&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;冠词包括 a、an、the。其中 a 和 an 经常放在单数可数名词前面：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;She is a student.   （她是一名学生。）
He is a teacher.    （他是一名老师。）
It is an apple.     （它是一个苹果。）
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;但如果后面是形容词，就不需要加 a：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;✅ She is beautiful.
✅ She is a student.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;因为 beautiful 是形容词，而 student 是名词。这是以后学习冠词时需要重点掌握的内容。&lt;/p&gt;
&lt;h2 id=&quot;-第一课学习总结&quot;&gt;📊 第一课学习总结&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#-第一课学习总结&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;table-wrapper&quot;&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;/td&gt;&lt;td&gt;✅ 初步掌握&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;主语、谓语、宾语&lt;/td&gt;&lt;td&gt;✅ 掌握较好&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;主谓宾结构&lt;/td&gt;&lt;td&gt;✅ 掌握&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;主系表结构&lt;/td&gt;&lt;td&gt;✅ 基本掌握&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;宾语和表语的区别&lt;/td&gt;&lt;td&gt;🟡 需要巩固&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;冠词 a、an、the&lt;/td&gt;&lt;td&gt;🟡 尚未系统学习&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;第一课到这里就结束了。需要记住今天最重要的两个概念：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;词性决定单词属于什么类别，句子成分说明单词在句子中承担什么作用。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在后面的课程中，会不断使用这两个概念。下一课准备学习：&lt;strong&gt;Lesson 2：be 动词与实义动词——为什么英语有时候用 am/is/are，有时候却直接使用 like、study、play？&lt;/strong&gt;&lt;/p&gt;</content:encoded><category>英语学习</category><category>英语</category><category>GPT</category><category>语法</category></item><item><title>LeetCode 146. LRU缓存</title><link>https://cjw32.xyz/blog/article/ai-90bfd873759cf874be6de0f4/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/ai-90bfd873759cf874be6de0f4/</guid><description>LRU 缓存要求在 O(1) 均摊时间内完成读取与写入，并逐出最久未使用的关键字。题解用「哈希表 + 双向链表」实现：哈希表负责 O(1) 定位节点，双向链表维护访问顺序，最近访问的放到头部、容量超限时淘汰尾部；并封装 removeNode、addToHead、moveToHead 三个辅助方法复用移位逻辑。</description><pubDate>Thu, 17 Sep 2026 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;leetcode-146-lru缓存&quot;&gt;LeetCode 146. LRU缓存&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#leetcode-146-lru缓存&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;请你设计并实现一个满足 LRU (最近最少使用) 缓存约束的数据结构。&lt;/p&gt;
&lt;p&gt;实现 &lt;code&gt;LRUCache&lt;/code&gt; 类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;LRUCache(int capacity)&lt;/code&gt; 以&lt;strong&gt;正整数&lt;/strong&gt;作为容量 &lt;code&gt;capacity&lt;/code&gt; 初始化 LRU 缓存&lt;/li&gt;
&lt;li&gt;&lt;code&gt;int get(int key)&lt;/code&gt; 如果关键字 &lt;code&gt;key&lt;/code&gt; 存在于缓存中，则返回关键字的值，否则返回 &lt;code&gt;-1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;void put(int key, int value)&lt;/code&gt; 如果关键字 &lt;code&gt;key&lt;/code&gt; 已经存在，则变更其数据值 &lt;code&gt;value&lt;/code&gt;；如果不存在，则向缓存中插入该组 &lt;code&gt;key-value&lt;/code&gt;。如果插入操作导致关键字数量超过 &lt;code&gt;capacity&lt;/code&gt;，则应该&lt;strong&gt;逐出&lt;/strong&gt;最久未使用的关键字。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;函数 &lt;code&gt;get&lt;/code&gt; 和 &lt;code&gt;put&lt;/code&gt; 必须以 &lt;strong&gt;O(1)&lt;/strong&gt; 的平均时间复杂度运行。&lt;/p&gt;
&lt;h2 id=&quot;示例&quot;&gt;示例&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#示例&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;输入&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[&quot;LRUCache&quot;, &quot;put&quot;, &quot;put&quot;, &quot;get&quot;, &quot;put&quot;, &quot;get&quot;, &quot;put&quot;, &quot;get&quot;, &quot;get&quot;, &quot;get&quot;]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;输出&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[null, null, null, 1, null, -1, null, -1, 3, 4]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;解释&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;LRUCache lRUCache &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LRUCache&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
lRUCache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 缓存是 {1=1}&lt;/span&gt;
lRUCache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 缓存是 {1=1, 2=2}&lt;/span&gt;
lRUCache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// 返回 1&lt;/span&gt;
lRUCache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 该操作会使得关键字 2 作废，缓存是 {1=1, 3=3}&lt;/span&gt;
lRUCache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// 返回 -1 (未找到)&lt;/span&gt;
lRUCache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 该操作会使得关键字 1 作废，缓存是 {4=4, 3=3}&lt;/span&gt;
lRUCache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// 返回 -1 (未找到)&lt;/span&gt;
lRUCache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// 返回 3&lt;/span&gt;
lRUCache&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// 返回 4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;提示&quot;&gt;提示&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#提示&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;1 &amp;#x3C;= capacity &amp;#x3C;= 3000&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0 &amp;#x3C;= key &amp;#x3C;= 10000&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0 &amp;#x3C;= value &amp;#x3C;= 10^5&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;最多调用 &lt;code&gt;2 * 10^5&lt;/code&gt; 次 &lt;code&gt;get&lt;/code&gt; 和 &lt;code&gt;put&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;解题思路&quot;&gt;解题思路&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#解题思路&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;此题需要对容器中的元素进行频繁地取出和插入操作，并且需要拿到链表首尾的元素，所以可以使用&lt;strong&gt;双向链表&lt;/strong&gt;的数据结构进行存储。&lt;/p&gt;
&lt;p&gt;为了能够快速地找到对应的元素，则需要维护一个&lt;strong&gt;哈希表&lt;/strong&gt;来对元素进行存储。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;get 方法实现&lt;/strong&gt;：先查询当前所需要的元素是否在哈希表中，如果不存在则返回 &lt;code&gt;-1&lt;/code&gt;；存在则返回当前元素的值，并且将该节点放到链表首部。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;put 方法实现&lt;/strong&gt;：先查询当前所需要的元素是否在哈希表中。
&lt;ul&gt;
&lt;li&gt;如果存在，则直接将该节点的值修改为新值，并且将该节点放到链表首部；&lt;/li&gt;
&lt;li&gt;如果不存在，则需要判断当前链表是否还有空间存入新元素：如果有空间，则直接将新节点存入链表首部并将长度加一；如果没有空间了，就将链表尾部的节点删除，并在首部存入新元素。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;由于这两个方法的实现都需要将节点从链表中删除、以及将节点添加到链表首部，所以可以直接封装成两个方法用来单独处理这两件事。&lt;/p&gt;
&lt;h2 id=&quot;代码实现&quot;&gt;代码实现&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#代码实现&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;span&gt;27&lt;/span&gt;&lt;span&gt;28&lt;/span&gt;&lt;span&gt;29&lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;span&gt;31&lt;/span&gt;&lt;span&gt;32&lt;/span&gt;&lt;span&gt;33&lt;/span&gt;&lt;span&gt;34&lt;/span&gt;&lt;span&gt;35&lt;/span&gt;&lt;span&gt;36&lt;/span&gt;&lt;span&gt;37&lt;/span&gt;&lt;span&gt;38&lt;/span&gt;&lt;span&gt;39&lt;/span&gt;&lt;span&gt;40&lt;/span&gt;&lt;span&gt;41&lt;/span&gt;&lt;span&gt;42&lt;/span&gt;&lt;span&gt;43&lt;/span&gt;&lt;span&gt;44&lt;/span&gt;&lt;span&gt;45&lt;/span&gt;&lt;span&gt;46&lt;/span&gt;&lt;span&gt;47&lt;/span&gt;&lt;span&gt;48&lt;/span&gt;&lt;span&gt;49&lt;/span&gt;&lt;span&gt;50&lt;/span&gt;&lt;span&gt;51&lt;/span&gt;&lt;span&gt;52&lt;/span&gt;&lt;span&gt;53&lt;/span&gt;&lt;span&gt;54&lt;/span&gt;&lt;span&gt;55&lt;/span&gt;&lt;span&gt;56&lt;/span&gt;&lt;span&gt;57&lt;/span&gt;&lt;span&gt;58&lt;/span&gt;&lt;span&gt;59&lt;/span&gt;&lt;span&gt;60&lt;/span&gt;&lt;span&gt;61&lt;/span&gt;&lt;span&gt;62&lt;/span&gt;&lt;span&gt;63&lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt;65&lt;/span&gt;&lt;span&gt;66&lt;/span&gt;&lt;span&gt;67&lt;/span&gt;&lt;span&gt;68&lt;/span&gt;&lt;span&gt;69&lt;/span&gt;&lt;span&gt;70&lt;/span&gt;&lt;span&gt;71&lt;/span&gt;&lt;span&gt;72&lt;/span&gt;&lt;span&gt;73&lt;/span&gt;&lt;span&gt;74&lt;/span&gt;&lt;span&gt;75&lt;/span&gt;&lt;span&gt;76&lt;/span&gt;&lt;span&gt;77&lt;/span&gt;&lt;span&gt;78&lt;/span&gt;&lt;span&gt;79&lt;/span&gt;&lt;span&gt;80&lt;/span&gt;&lt;span&gt;81&lt;/span&gt;&lt;span&gt;82&lt;/span&gt;&lt;span&gt;83&lt;/span&gt;&lt;span&gt;84&lt;/span&gt;&lt;span&gt;85&lt;/span&gt;&lt;span&gt;86&lt;/span&gt;&lt;span&gt;87&lt;/span&gt;&lt;span&gt;88&lt;/span&gt;&lt;span&gt;89&lt;/span&gt;&lt;span&gt;90&lt;/span&gt;&lt;span&gt;91&lt;/span&gt;&lt;span&gt;92&lt;/span&gt;&lt;span&gt;93&lt;/span&gt;&lt;span&gt;94&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/**
 * LeetCode 146. LRU缓存
 *
 * 请你设计并实现一个满足  LRU (最近最少使用) 缓存 约束的数据结构。
 * 实现 LRUCache 类：
 * LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
 * int get(int key) 如果关键字 key 存在于缓存中，则返回关键字的值，否则返回 -1 。
 * void put(int key, int value) 如果关键字 key 已经存在，则变更其数据值 value ；如果不存在，则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ，则应该 逐出 最久未使用的关键字。
 * 函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。
 */&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 定义节点结构&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;nodeList&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; val&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;key &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; key
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; val
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prev &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * @param {number} capacity
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;LRUCache&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;capacity&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;// 链表的构造函数&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;capacity &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; capacity    &lt;span class=&quot;token comment&quot;&gt;// 链表的最大长度&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;num &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;                &lt;span class=&quot;token comment&quot;&gt;// 当前链表的长度&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;nodeList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 首尾节点&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;last &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;nodeList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hash &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;              &lt;span class=&quot;token comment&quot;&gt;// 哈希表&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;last &lt;span class=&quot;token comment&quot;&gt;// 将首尾节点相连&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;last&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prev &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 从链表上删除节点方法&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;LRUCache&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;removeNode&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prev&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;next
    node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prev &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prev
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 将节点添加到链表首部&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;LRUCache&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;addToHead&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prev &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first
    node&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;next
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prev &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; node
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;first&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; node
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token class-name&quot;&gt;LRUCache&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;moveToHead&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;removeNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addToHead&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;node&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * @param {number} key
 * @return {number}
 */&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;LRUCache&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hash&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;moveToHead&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hash&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hash&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * @param {number} key
 * @param {number} value
 * @return {void}
 */&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;LRUCache&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;put&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hash&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;moveToHead&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hash&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hash&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; value
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; newNode &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;nodeList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;capacity &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;num&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addToHead&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;newNode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hash&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; newNode
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;num&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hash&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;last&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prev&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;removeNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;last&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prev&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addToHead&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;newNode&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hash&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; newNode
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;/**
 * Your LRUCache object will be instantiated and called as such:
 * var obj = new LRUCache(capacity)
 * var param_1 = obj.get(key)
 * obj.put(key,value)
 */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded><category>算法题解</category><category>LeetCode</category><category>算法</category><category>链表</category></item><item><title>手写防抖</title><link>https://cjw32.xyz/blog/article/2026031901/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2026031901/</guid><description>手写实现 debounce，并说明 this、定时器重置和常见场景。</description><pubDate>Wed, 18 Mar 2026 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;手写防抖&quot;&gt;手写防抖&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#手写防抖&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;debounce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;func&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; wait&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; timer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;args&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;clearTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      timer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token function&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;wait&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 测试用例：&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; handleSearch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;debounce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;发送搜索请求:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; query&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;handleSearch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;A&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;handleSearch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;AB&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;handleSearch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;ABC&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 只有最后这个 &quot;ABC&quot; 会在 500ms 后被打印&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded><category>面试</category><category>JavaScript</category><category>手写题</category></item><item><title>手写一个判断空值的函数</title><link>https://cjw32.xyz/blog/article/2026031902/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2026031902/</guid><description>手写 isEmpty 函数，覆盖空字符串、空格串、空数组、空对象、null、undefined 六种空值情形，并附测试用例。</description><pubDate>Wed, 18 Mar 2026 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;手写一个判断空值的函数&quot;&gt;手写一个判断空值的函数&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#手写一个判断空值的函数&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;空数组，空对象，空格字符串，undefined，null都算空值&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;isEmpty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;token comment&quot;&gt;//1、判断空字符串&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;type value &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;string&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;trim&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
 &lt;span class=&quot;token comment&quot;&gt;//2、判断空数组&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
 &lt;span class=&quot;token comment&quot;&gt;//3、判断null和undefined&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; value &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
 &lt;span class=&quot;token comment&quot;&gt;//4、判断空对象&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; value &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;object&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 测试用例：&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isEmpty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isEmpty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;   &quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;// true (纯空格字符串)&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isEmpty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;// true (空对象)&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isEmpty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;// true (空数组)&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isEmpty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;      &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isEmpty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;         &lt;span class=&quot;token comment&quot;&gt;// false (数字0通常算有效值)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded><category>面试</category><category>JavaScript</category><category>手写题</category></item><item><title>手写一个提取URL参数的函数</title><link>https://cjw32.xyz/blog/article/2026031903/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2026031903/</guid><description>手写提取 URL 参数的三种解法：URL/URLSearchParams 现代 API、手动拆分加 decodeURIComponent、以及把所有参数转成对象，配测试用例。</description><pubDate>Wed, 18 Mar 2026 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;手写一个提取url参数的函数&quot;&gt;手写一个提取URL参数的函数&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#手写一个提取url参数的函数&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;这里提供&lt;strong&gt;三种&lt;/strong&gt;解法：现代 API 法、传统手动解析法，以及&lt;strong&gt;将所有参数转为对象的解法&lt;/strong&gt;。&lt;/p&gt;
&lt;h3 id=&quot;解法一现代-api---url-和-urlsearchparams-强烈推荐&quot;&gt;解法一：现代 API - &lt;code&gt;URL&lt;/code&gt; 和 &lt;code&gt;URLSearchParams&lt;/code&gt; (强烈推荐)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#解法一现代-api---url-和-urlsearchparams-强烈推荐&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;这是目前浏览器原生支持的最好用的方法，能够轻松满足“获取参数”和“获取域名”的需求。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getUrlParamModern&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;urlString&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; paramName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;urlString&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;paramName &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;domain&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;hostname 
          &lt;span class=&quot;token comment&quot;&gt;//如果需要获取主域名，则是&lt;/span&gt;
          &lt;span class=&quot;token comment&quot;&gt;//var parts = url.hostname.split(&apos;.&apos;)&lt;/span&gt;
          &lt;span class=&quot;token comment&quot;&gt;//return parts[parts.length - 1]   （因为有可能是www.baidu.com,也有可能是baidu.com）&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;searchParams&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;paramName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;无效的URL格式&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 测试用例：&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; testUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;[https://www.example.com/page?name=%E5%BC%A0%E4%B8%89&amp;#x26;age=25](https://www.example.com/page?name=%E5%BC%A0%E4%B8%89&amp;#x26;age=25)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUrlParamModern&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;testUrl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;domain&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;[www.example.com](https://www.example.com)&quot;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUrlParamModern&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;testUrl&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;name&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;// &quot;张三&quot; (自动解码了)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;解法二传统手动拆解法用到-decodeuricomponent&quot;&gt;解法二：传统手动拆解法（用到 decodeURIComponent）&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#解法二传统手动拆解法用到-decodeuricomponent&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;span&gt;27&lt;/span&gt;&lt;span&gt;28&lt;/span&gt;&lt;span&gt;29&lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;span&gt;31&lt;/span&gt;&lt;span&gt;32&lt;/span&gt;&lt;span&gt;33&lt;/span&gt;&lt;span&gt;34&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getUrlParamManual&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;urlString&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; paramName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 粗略获取域名的方法：使用正则截取&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;paramName &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;domain&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; domainMatch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; urlString&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;^(?:https?:\/\/)?(?:[^@\n]+@)?(?:www\.)?([^:\/\n?]+)&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-flags&quot;&gt;im&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; domainMatch &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; domainMatch&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 1. 找到问号 ? 的位置&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; searchIndex &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; urlString&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;indexOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;?&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;searchIndex &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 没有参数&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 2. 截取问号后面的部分：&quot;name=%E5%BC%A0%E4%B8%89&amp;#x26;age=25&quot;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; searchString &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; urlString&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;substring&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;searchIndex &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  
  &lt;span class=&quot;token comment&quot;&gt;// 去除哈希值 (如果 URL 里有 #hash)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cleanSearch &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; searchString&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;#&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 3. 按 &amp;#x26; 分割成数组：[&quot;name=%E5%BC%A0...&quot;, &quot;age=25&quot;]&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; paramsArray &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; cleanSearch&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;&amp;#x26;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 4. 遍历查找&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt; paramsArray&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pair &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; paramsArray&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;=&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; key &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pair&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; paramName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// 找到了！使用 decodeURIComponent 解码中文和特殊字符&lt;/span&gt;
      &lt;span class=&quot;token comment&quot;&gt;// 如果没有等号后面的值，默认返回空字符串，否则返回解码后的值&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; pair&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;decodeURIComponent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pair&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 没找到该参数&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;解法三将所有参数转换为对象实战常用法&quot;&gt;解法三：将所有参数转换为对象（实战常用法）&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#解法三将所有参数转换为对象实战常用法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;利用 ES6+ 现代语法（代码极简）&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getAllParamsToObjModern&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;urlString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;urlString&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Object.fromEntries 可以把键值对列表转换成一个对象&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// url.searchParams.entries() 产出如: [[&apos;name&apos;, &apos;张三&apos;], [&apos;age&apos;, &apos;25&apos;]]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; Object&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fromEntries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;searchParams&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;entries&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;error&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded><category>面试</category><category>JavaScript</category><category>手写题</category></item><item><title>企业级 Git 提交规范配置指南 (From 0 to 1)</title><link>https://cjw32.xyz/blog/article/2026012801/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2026012801/</guid><description>从零集成 Husky + Commitlint + Commitizen：安装依赖、配置提交校验钩子、接入 cz-git 交互式提交与 lint-staged 代码检查，附 Conventional Commits 类型速查表。</description><pubDate>Tue, 27 Jan 2026 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;企业级-git-提交规范配置指南-from-0-to-1&quot;&gt;企业级 Git 提交规范配置指南 (From 0 to 1)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#企业级-git-提交规范配置指南-from-0-to-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;本文档将指导你如何在项目中集成 &lt;strong&gt;Husky + Commitlint + Commitizen&lt;/strong&gt;，实现自动化的代码与提交信息规范检查。&lt;/p&gt;
&lt;h2 id=&quot;1-核心工具安装-commitlint&quot;&gt;1. 核心工具安装 (Commitlint)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-核心工具安装-commitlint&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;首先安装 Commitlint 及其标准配置。这是“裁判”，负责判断提交信息是否合格。&lt;/p&gt;
&lt;h3 id=&quot;11-安装依赖&quot;&gt;1.1 安装依赖&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#11-安装依赖&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在项目根目录下执行：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;npm install -D @commitlint/cli @commitlint/config-conventional
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;12-创建配置文件&quot;&gt;1.2 创建配置文件&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#12-创建配置文件&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在根目录新建文件 &lt;code&gt;commitlint.config.js&lt;/code&gt;，内容如下：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;module.exports = {
  extends: [&apos;@commitlint/config-conventional&apos;],
  // 你可以在这里自定义规则，例如：
  // rules: {
  //   &apos;type-enum&apos;: [2, &apos;always&apos;, [&apos;feat&apos;, &apos;fix&apos;, &apos;docs&apos;, &apos;style&apos;, &apos;refactor&apos;, &apos;test&apos;, &apos;chore&apos;, &apos;revert&apos;]],
  // }
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;2-自动化钩子配置-husky&quot;&gt;2. 自动化钩子配置 (Husky)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-自动化钩子配置-husky&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Husky 是“触发器”，它利用 Git Hooks 在你敲击回车提交时拦截操作。&lt;/p&gt;
&lt;h3 id=&quot;21-安装并初始化-husky&quot;&gt;2.1 安装并初始化 Husky&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#21-安装并初始化-husky&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：Husky v9 的初始化命令非常简化。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;npm install -D husky
npx husky init
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;执行完 &lt;code&gt;npx husky init&lt;/code&gt; 后，你的 &lt;code&gt;package.json&lt;/code&gt; 会自动增加 &lt;code&gt;&quot;prepare&quot;: &quot;husky&quot;&lt;/code&gt; 脚本，并且根目录下会生成 &lt;code&gt;.husky&lt;/code&gt; 文件夹。&lt;/em&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ 常见报错预警&lt;/strong&gt;： &lt;code&gt;init&lt;/code&gt; 命令会自动创建一个 &lt;code&gt;.husky/pre-commit&lt;/code&gt; 文件，内容默认是 &lt;code&gt;npm test&lt;/code&gt;。 如果你的 &lt;code&gt;package.json&lt;/code&gt; 中没有定义 &lt;code&gt;test&lt;/code&gt; 脚本，提交时就会报错 &lt;code&gt;Missing script: &quot;test&quot;&lt;/code&gt;。 &lt;strong&gt;解决方法&lt;/strong&gt;：打开 &lt;code&gt;.husky/pre-commit&lt;/code&gt; 文件，删除里面的 &lt;code&gt;npm test&lt;/code&gt;，暂时留空即可（后续在第 6 步我们会配置它）。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;22-添加-commit-msg-钩子&quot;&gt;2.2 添加 commit-msg 钩子&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#22-添加-commit-msg-钩子&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;我们需要告诉 Husky：在提交信息生成之前，请用 Commitlint 检查一下。&lt;/p&gt;
&lt;p&gt;在终端执行（Mac/Linux）：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;echo &quot;npx --no -- commitlint --edit \$1&quot; &gt; .husky/commit-msg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Windows 用户 (PowerShell)&lt;/strong&gt; 请执行：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;Set-Content .husky/commit-msg &apos;npx --no -- commitlint --edit $1&apos;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;或者手动在 &lt;code&gt;.husky&lt;/code&gt; 文件夹下新建文件 &lt;code&gt;commit-msg&lt;/code&gt; (无后缀)，内容写入：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;npx --no -- commitlint --edit $1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;3-交互式提交助手-commitizen--cz-git---可选但推荐&quot;&gt;3. 交互式提交助手 (Commitizen &amp;#x26; cz-git) - 可选但推荐&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#3-交互式提交助手-commitizen--cz-git---可选但推荐&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;为了不用每次都手敲 &lt;code&gt;feat: ...&lt;/code&gt;，我们可以安装一个工具，通过选择的方式生成提交信息。这里推荐使用 &lt;code&gt;cz-git&lt;/code&gt;，它比老牌的 &lt;code&gt;cz-conventional-changelog&lt;/code&gt; 更轻量、更漂亮。&lt;/p&gt;
&lt;h3 id=&quot;31-安装依赖&quot;&gt;3.1 安装依赖&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#31-安装依赖&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;npm install -D commitizen cz-git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;32-修改-packagejson&quot;&gt;3.2 修改 package.json&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#32-修改-packagejson&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;打开 &lt;code&gt;package.json&lt;/code&gt;，在顶级层级（与 scripts 同级）添加 &lt;code&gt;config&lt;/code&gt; 字段：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;{
  &quot;scripts&quot;: {
    &quot;commit&quot;: &quot;git-cz&quot;
  },
  &quot;config&quot;: {
    &quot;commitizen&quot;: {
      &quot;path&quot;: &quot;node_modules/cz-git&quot;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;33-测试交互式提交&quot;&gt;3.3 测试交互式提交&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#33-测试交互式提交&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;以后你可以使用 &lt;code&gt;npm run commit&lt;/code&gt; 来代替 &lt;code&gt;git commit&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&quot;4-验证是否成功&quot;&gt;4. 验证是否成功&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#4-验证是否成功&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;测试-1错误的提交&quot;&gt;测试 1：错误的提交&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#测试-1错误的提交&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;尝试在终端输入一个不规范的提交：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;git add .
git commit -m &quot;随便写点什么&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;预期结果&lt;/strong&gt;： 终端报错，提示 &lt;code&gt;subject may not be empty&lt;/code&gt; 或 &lt;code&gt;type must be one of [feat, fix...]&lt;/code&gt;，&lt;strong&gt;提交失败&lt;/strong&gt;。这说明 Husky 拦截成功了。&lt;/p&gt;
&lt;h3 id=&quot;测试-2正确的提交&quot;&gt;测试 2：正确的提交&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#测试-2正确的提交&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;git commit -m &quot;chore: 初始化 git 规范配置&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;预期结果&lt;/strong&gt;： 提交成功。&lt;/p&gt;
&lt;h2 id=&quot;5-附录提交类型速查表-conventional-commits&quot;&gt;5. 附录：提交类型速查表 (Conventional Commits)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#5-附录提交类型速查表-conventional-commits&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;团队成员在提交时应遵循以下前缀：&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;






















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;类型 (Type)&lt;/th&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;strong&gt;feat&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;新增功能 (Feature)&lt;/td&gt;&lt;td&gt;&lt;code&gt;feat: 增加用户登录功能&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;fix&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;修复 Bug&lt;/td&gt;&lt;td&gt;&lt;code&gt;fix: 修复上传文件时的跨域问题&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;docs&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;文档变更&lt;/td&gt;&lt;td&gt;&lt;code&gt;docs: 更新 README.md&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;style&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;代码格式 (不影响逻辑，如空格、分号)&lt;/td&gt;&lt;td&gt;&lt;code&gt;style: 删除多余空行&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;refactor&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;代码重构 (不修 Bug 也不加功能)&lt;/td&gt;&lt;td&gt;&lt;code&gt;refactor: 优化大文件切片逻辑&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;perf&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;性能优化&lt;/td&gt;&lt;td&gt;&lt;code&gt;perf: 优化 ECharts 渲染速度&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;test&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;测试相关&lt;/td&gt;&lt;td&gt;&lt;code&gt;test: 增加单元测试&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;chore&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;构建/工具/依赖变动&lt;/td&gt;&lt;td&gt;&lt;code&gt;chore: 升级 express 版本&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;revert&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;回滚代码&lt;/td&gt;&lt;td&gt;&lt;code&gt;revert: 回滚上一次提交&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&quot;6-进阶代码质量检查-lint-staged&quot;&gt;6. 进阶：代码质量检查 (Lint-staged)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#6-进阶代码质量检查-lint-staged&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;如果你希望在提交时，不仅检查&lt;strong&gt;提交信息&lt;/strong&gt;，还要自动扫描代码（ESLint/Prettier）是否有错误，请继续配置 &lt;code&gt;lint-staged&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id=&quot;61-安装&quot;&gt;6.1 安装&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#61-安装&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;npm install -D lint-staged
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;62-配置-packagejson&quot;&gt;6.2 配置 package.json&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#62-配置-packagejson&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在 &lt;code&gt;package.json&lt;/code&gt; 中添加：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;{
  &quot;lint-staged&quot;: {
    &quot;*.{js,vue,ts}&quot;: [
      &quot;eslint --fix&quot;,
      &quot;prettier --write&quot;
    ]
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;(前提是你项目中已经配置了 eslint 和 prettier)&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;63-修改-husky-的-pre-commit-钩子&quot;&gt;6.3 修改 Husky 的 pre-commit 钩子&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#63-修改-husky-的-pre-commit-钩子&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;找到 &lt;code&gt;.husky/pre-commit&lt;/code&gt; 文件，将其内容修改为：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;npx lint-staged
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;现在，你的流程变成了：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;git commit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Husky 触发 &lt;code&gt;pre-commit&lt;/code&gt; -&gt; 运行 Lint-staged (检查代码格式，有问题直接报错或自动修复)。&lt;/li&gt;
&lt;li&gt;Husky 触发 &lt;code&gt;commit-msg&lt;/code&gt; -&gt; 运行 Commitlint (检查提交文字，格式不对报错)。&lt;/li&gt;
&lt;li&gt;一切通过 -&gt; 真正生成 Commit。&lt;/li&gt;
&lt;/ol&gt;</content:encoded><category>技术文章</category><category>git</category></item><item><title>通用防抖hook封装</title><link>https://cjw32.xyz/blog/article/2026011901/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2026011901/</guid><description>用 TypeScript 封装通用防抖函数，保留原函数参数类型与 this 指向，通过闭包中的 timer 控制延迟执行。</description><pubDate>Sun, 18 Jan 2026 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;通用防抖hook封装&quot;&gt;通用防抖hook封装&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#通用防抖hook封装&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86M13,11.25H8V12.75H9.5V20H11.25V12.75H13V11.25Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;typescript&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-typescript&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;/**
 * 通用防抖函数
 * @param fn 需要防抖执行的函数
 * @param delay 延迟时间（毫秒）
 * @returns 经过防抖处理的新函数
 */&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; debounce&lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;args&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
  fn&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  delay&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;number&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;args&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Parameters&lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; timer&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; ReturnType&lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; setTimeout&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;args&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; Parameters&lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;clearTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;timer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    timer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      timer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; delay&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded><category>面试</category><category>面试</category></item><item><title>Vue 组件间通信方式</title><link>https://cjw32.xyz/blog/article/2026010101/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2026010101/</guid><description>梳理 Vue 组件通信的完整图谱：父子通信的 props/$emit/v-model/refs、跨级的 provide-inject 与 $attrs、全局的 Pinia 与 mitt，附面试回答策略和对比表。</description><pubDate>Wed, 31 Dec 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;vue-组件间通信方式&quot;&gt;Vue 组件间通信方式&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#vue-组件间通信方式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id=&quot;一-父子组件通信-最常用&quot;&gt;一、 父子组件通信 (最常用)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#一-父子组件通信-最常用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;1-props-父传子&quot;&gt;1. Props (父传子)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-props-父传子&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;这是最基础的方式。父组件通过属性绑定传递数据，子组件通过 &lt;code&gt;props&lt;/code&gt; 接收。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：通用的数据传递。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;原则&lt;/strong&gt;：单向数据流，子组件不应直接修改 Props。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;// Child.vue
defineProps([&apos;msg&apos;])

// Parent.vue
&amp;#x3C;Child msg=&quot;Hello Vue 3&quot; /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;2-emit-子传父&quot;&gt;2. $emit (子传父)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-emit-子传父&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;子组件通过触发事件，将数据传递给父组件。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：子组件状态变化通知父组件。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;// Child.vue
const emit = defineEmits([&apos;update&apos;])
function handleClick() {
  emit(&apos;update&apos;, &apos;New Data&apos;)
}

// Parent.vue
&amp;#x3C;Child @update=&quot;handleUpdate&quot; /&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;3-v-model-双向绑定&quot;&gt;3. v-model (双向绑定)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#3-v-model-双向绑定&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;本质是 &lt;code&gt;props&lt;/code&gt; + &lt;code&gt;emit&lt;/code&gt; 的语法糖。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Vue 2&lt;/strong&gt;: 默认为 &lt;code&gt;value&lt;/code&gt; prop 和 &lt;code&gt;input&lt;/code&gt; event。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vue 3&lt;/strong&gt;: 默认为 &lt;code&gt;modelValue&lt;/code&gt; prop 和 &lt;code&gt;update:modelValue&lt;/code&gt; event。支持多个 v-model。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;4-refs--defineexpose&quot;&gt;4. $refs / defineExpose&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#4-refs--defineexpose&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;父组件可以通过 &lt;code&gt;ref&lt;/code&gt; 获取子组件实例，直接调用子组件的方法或访问数据。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;注意&lt;/strong&gt;：Vue 3 中使用 &lt;code&gt;&amp;#x3C;script setup&gt;&lt;/code&gt; 的组件默认是&lt;strong&gt;关闭&lt;/strong&gt;的，必须通过 &lt;code&gt;defineExpose&lt;/code&gt; 暴露属性。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;// Child.vue
const count = ref(0)
defineExpose({ count })

// Parent.vue
const childRef = ref(null)
console.log(childRef.value.count)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;5-parentparent--parentchildren-不推荐频繁使用&quot;&gt;5. &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mi&gt;p&lt;/mi&gt;&lt;mi&gt;a&lt;/mi&gt;&lt;mi&gt;r&lt;/mi&gt;&lt;mi&gt;e&lt;/mi&gt;&lt;mi&gt;n&lt;/mi&gt;&lt;mi&gt;t&lt;/mi&gt;&lt;mi mathvariant=&quot;normal&quot;&gt;/&lt;/mi&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;parent / &lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot; style=&quot;margin-right:0.0278em;&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;mord mathnormal&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;children (不推荐频繁使用)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#5-parentparent--parentchildren-不推荐频繁使用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Vue 2&lt;/strong&gt;: 使用 &lt;code&gt;$children&lt;/code&gt; 访问子组件实例数组。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vue 3&lt;/strong&gt;: &lt;code&gt;$children&lt;/code&gt; 已被&lt;strong&gt;移除&lt;/strong&gt;。建议使用 refs。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$parent&lt;/code&gt; 依然可用，但会导致组件耦合度过高。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;二-跨级祖孙组件通信&quot;&gt;二、 跨级/祖孙组件通信&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#二-跨级祖孙组件通信&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;1-provide--inject-依赖注入&quot;&gt;1. Provide / Inject (依赖注入)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-provide--inject-依赖注入&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;祖先组件作为“依赖提供者”，后代组件（无论多深）都可以注入该依赖。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：编写插件、组件库或深层嵌套结构（不需要通过中间层透传 props）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;特点&lt;/strong&gt;：非响应式（除非传递的是 ref/reactive 对象）。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;// Ancestor.vue
provide(&apos;theme&apos;, &apos;dark&apos;)

// Descendant.vue
const theme = inject(&apos;theme&apos;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;2-attrs&quot;&gt;2. $attrs&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-attrs&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外)。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：高阶组件或二次封装组件，使用 &lt;code&gt;v-bind=&quot;$attrs&quot;&lt;/code&gt; 将属性透传给内部组件。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;三-兄弟组件或任意组件通信&quot;&gt;三、 兄弟组件或任意组件通信&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#三-兄弟组件或任意组件通信&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;1-全局状态管理-vuex--pinia&quot;&gt;1. 全局状态管理 (Vuex / Pinia)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-全局状态管理-vuex--pinia&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;这是大型项目的标准解决方案。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Vuex&lt;/strong&gt;: Vue 2 的主流，包含 State, Getter, Mutation, Action, Module。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pinia&lt;/strong&gt;: Vue 3 官方推荐（也支持 Vue 2），更轻量，去掉了 Mutation，支持 Composition API，对 TypeScript 支持更好。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;2-eventbus-事件总线&quot;&gt;2. EventBus (事件总线)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-eventbus-事件总线&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;创建一个空的 Vue 实例作为中央事件总线，用 &lt;code&gt;$emit&lt;/code&gt; 和 &lt;code&gt;$on&lt;/code&gt; 通信。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Vue 2&lt;/strong&gt;: &lt;code&gt;Vue.prototype.$bus = new Vue()&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vue 3&lt;/strong&gt;: &lt;strong&gt;已移除&lt;/strong&gt; &lt;code&gt;$on&lt;/code&gt;, &lt;code&gt;$off&lt;/code&gt; 等实例方法。官方推荐使用第三方库如 &lt;code&gt;mitt&lt;/code&gt; 或 &lt;code&gt;tiny-emitter&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;3-mitt-vue-3-替代-eventbus&quot;&gt;3. Mitt (Vue 3 替代 EventBus)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#3-mitt-vue-3-替代-eventbus&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;import mitt from &apos;mitt&apos;
const emitter = mitt()
// 监听
emitter.on(&apos;foo&apos;, e =&gt; console.log(e))
// 触发
emitter.emit(&apos;foo&apos;, { a: &apos;b&apos; })
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;四-面试高分总结策略-cheat-sheet&quot;&gt;四、 面试高分总结策略 (Cheat Sheet)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#四-面试高分总结策略-cheat-sheet&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;如果面试官问：“Vue 组件间传值有哪些方法？”，你可以这样回答：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 开场定调&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Vue 的组件通信方式主要取决于组件之间的关系。我一般把它们分为三类：父子通信、跨级通信和全局通信。”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;2. 核心展开 (由浅入深)&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;父子关系&lt;/strong&gt;：最常用的是 &lt;code&gt;props&lt;/code&gt; 和 &lt;code&gt;$emit&lt;/code&gt;，这是符合单向数据流的最佳实践。如果是双向同步，我会用 &lt;code&gt;v-model&lt;/code&gt;。如果是封装组件需要透传属性，我会用 &lt;code&gt;$attrs&lt;/code&gt;。偶尔为了操作子组件内部方法，会配合 &lt;code&gt;ref&lt;/code&gt; 和 &lt;code&gt;defineExpose&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;跨级/祖孙关系&lt;/strong&gt;：对于深层嵌套，为了避免 props 逐层传递（Props Drilling），我会使用 &lt;code&gt;provide&lt;/code&gt; 和 &lt;code&gt;inject&lt;/code&gt;，这在开发通用组件库时非常有用。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;兄弟或任意关系&lt;/strong&gt;：如果是简单的场景，Vue 2 可以用 EventBus，但在 Vue 3 中我推荐使用 &lt;code&gt;mitt&lt;/code&gt;。如果是复杂的应用状态管理，&lt;strong&gt;Pinia&lt;/strong&gt; 是目前的首选（Vuex 是过去式），因为它对 TS 支持更好且 API 更简洁。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;3. 补充亮点 (体现深度)&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Vue 3 的变化&lt;/strong&gt;：特意提到 Vue 3 移除了 &lt;code&gt;$children&lt;/code&gt; 和 &lt;code&gt;$on/$off&lt;/code&gt; API，体现你对新版本的关注。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;状态管理选型&lt;/strong&gt;：提到 Pinia 相比 Vuex 的优势（去掉了 mutation，体积更小）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;浏览器存储&lt;/strong&gt;：如果数据需要持久化，还可以补充 localStorage / sessionStorage 作为辅助通信手段。&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;五-简单对比表&quot;&gt;五、 简单对比表&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#五-简单对比表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;
































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;方式&lt;/th&gt;&lt;th&gt;适用场景&lt;/th&gt;&lt;th&gt;Vue Version&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;strong&gt;Props / Emit&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;父子组件&lt;/td&gt;&lt;td&gt;All&lt;/td&gt;&lt;td&gt;⭐ (低)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;v-model&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;父子双向同步&lt;/td&gt;&lt;td&gt;All (语法略有不同)&lt;/td&gt;&lt;td&gt;⭐&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Refs / Expose&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;父调子方法&lt;/td&gt;&lt;td&gt;All&lt;/td&gt;&lt;td&gt;⭐&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Provide / Inject&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;跨级/插件&lt;/td&gt;&lt;td&gt;All&lt;/td&gt;&lt;td&gt;⭐⭐&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Attributes ($attrs)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;组件封装/透传&lt;/td&gt;&lt;td&gt;All&lt;/td&gt;&lt;td&gt;⭐⭐&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;EventBus ($bus)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;任意组件&lt;/td&gt;&lt;td&gt;Vue 2 Only&lt;/td&gt;&lt;td&gt;⭐⭐&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Mitt / Tiny-emitter&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;任意组件&lt;/td&gt;&lt;td&gt;Vue 3 (替代 EventBus)&lt;/td&gt;&lt;td&gt;⭐⭐&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Vuex&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;全局状态&lt;/td&gt;&lt;td&gt;Vue 2 (Vue 3可用)&lt;/td&gt;&lt;td&gt;⭐⭐⭐ (高)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Pinia&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;全局状态&lt;/td&gt;&lt;td&gt;Vue 3 (推荐)&lt;/td&gt;&lt;td&gt;⭐⭐⭐&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;</content:encoded><category>面试</category><category>面试</category></item><item><title>JS 常用字符串操作大全</title><link>https://cjw32.xyz/blog/article/2025122501/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025122501/</guid><description>汇总 JS 字符串常用方法：查找检测、截取切片（slice 与 substring 的区别）、转换替换、模板字符串与 padStart 补全，附高频场景速查表。</description><pubDate>Wed, 24 Dec 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;js-常用字符串操作大全&quot;&gt;JS 常用字符串操作大全&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#js-常用字符串操作大全&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;在 JavaScript 中，字符串（String）是不可变的。以下方法均&lt;strong&gt;返回新字符串&lt;/strong&gt;，不会修改原字符串。&lt;/p&gt;
&lt;h2 id=&quot;一-查找与检测-searching--checking&quot;&gt;一、 查找与检测 (Searching &amp;#x26; Checking)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#一-查找与检测-searching--checking&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;这组方法用于判断字符串中是否包含某些内容，或者获取其位置。&lt;/p&gt;
&lt;h3 id=&quot;1-includesstr-es6-推荐&quot;&gt;1. &lt;code&gt;includes(str)&lt;/code&gt; (ES6 推荐)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-includesstr-es6-推荐&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;判断是否包含子串，返回布尔值。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;const str = &quot;Hello World&quot;;
console.log(str.includes(&quot;World&quot;)); // true
console.log(str.includes(&quot;Bye&quot;));   // false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;2-indexofstr--lastindexofstr&quot;&gt;2. &lt;code&gt;indexOf(str)&lt;/code&gt; / &lt;code&gt;lastIndexOf(str)&lt;/code&gt;&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-indexofstr--lastindexofstr&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;获取子串第一次/最后一次出现的索引。如果未找到，返回 &lt;code&gt;-1&lt;/code&gt;。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;const str = &quot;frontend&quot;;
console.log(str.indexOf(&quot;end&quot;)); // 5
console.log(str.indexOf(&quot;java&quot;)); // -1 (未找到)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;3-startswithstr--endswithstr&quot;&gt;3. &lt;code&gt;startsWith(str)&lt;/code&gt; / &lt;code&gt;endsWith(str)&lt;/code&gt;&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#3-startswithstr--endswithstr&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;判断字符串是否以某子串开头或结尾。常用于判断文件扩展名或 URL 协议。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;const file = &quot;image.png&quot;;
console.log(file.endsWith(&quot;.png&quot;)); // true
console.log(file.startsWith(&quot;http&quot;)); // false
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;二-截取与切片-slicing&quot;&gt;二、 截取与切片 (Slicing)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#二-截取与切片-slicing&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;面试中常考 &lt;code&gt;slice&lt;/code&gt; 和 &lt;code&gt;substring&lt;/code&gt; 的区别，建议首选 &lt;code&gt;slice&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id=&quot;1-slicestart-end-推荐&quot;&gt;1. &lt;code&gt;slice(start, end)&lt;/code&gt; (推荐)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-slicestart-end-推荐&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;提取字符串的一部分。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;start&lt;/code&gt;: 开始索引。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;end&lt;/code&gt;: 结束索引（不包含该位置）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;特点&lt;/strong&gt;：支持负数索引（代表从后往前数）。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;const str = &quot;JavaScript&quot;;
console.log(str.slice(0, 4));  // &quot;Java&quot;
console.log(str.slice(-6));    // &quot;Script&quot; (从倒数第6个取到最后)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;2-substringstart-end&quot;&gt;2. &lt;code&gt;substring(start, end)&lt;/code&gt;&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-substringstart-end&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;功能与 &lt;code&gt;slice&lt;/code&gt; 类似，但&lt;strong&gt;不支持负数&lt;/strong&gt;（负数会被当作 0）。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;const str = &quot;JavaScript&quot;;
console.log(str.substring(0, 4)); // &quot;Java&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;三-转换与替换-transform--replace&quot;&gt;三、 转换与替换 (Transform &amp;#x26; Replace)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#三-转换与替换-transform--replace&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;1-splitseparator-转数组---核心&quot;&gt;1. &lt;code&gt;split(separator)&lt;/code&gt; (转数组 - 核心)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-splitseparator-转数组---核心&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;将字符串拆分为数组。这是字符串处理中最强大的方法之一。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;const str = &quot;apple,banana,orange&quot;;
const arr = str.split(&quot;,&quot;); 
console.log(arr); // [&quot;apple&quot;, &quot;banana&quot;, &quot;orange&quot;]

// 常见技巧：反转字符串
const reverse = &quot;abc&quot;.split(&quot;&quot;).reverse().join(&quot;&quot;); // &quot;cba&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;2-replacesearchvalue-newvalue--replaceall&quot;&gt;2. &lt;code&gt;replace(searchValue, newValue)&lt;/code&gt; / &lt;code&gt;replaceAll()&lt;/code&gt;&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-replacesearchvalue-newvalue--replaceall&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;replace&lt;/code&gt;: 默认只替换&lt;strong&gt;第一个&lt;/strong&gt;匹配项（除非使用带全局标志 &lt;code&gt;g&lt;/code&gt; 的正则）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;replaceAll&lt;/code&gt; (ES2021): 替换&lt;strong&gt;所有&lt;/strong&gt;匹配项。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;const str = &quot;hello world, hello js&quot;;

// 只替换第一个
console.log(str.replace(&quot;hello&quot;, &quot;hi&quot;)); // &quot;hi world, hello js&quot;

// 替换所有 (ES2021)
console.log(str.replaceAll(&quot;hello&quot;, &quot;hi&quot;)); // &quot;hi world, hi js&quot;

// 使用正则替换所有
console.log(str.replace(/hello/g, &quot;hi&quot;)); // &quot;hi world, hi js&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;3-tolowercase--touppercase&quot;&gt;3. &lt;code&gt;toLowerCase()&lt;/code&gt; / &lt;code&gt;toUpperCase()&lt;/code&gt;&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#3-tolowercase--touppercase&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;大小写转换。常用于搜索功能中忽略大小写的比对。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;const input = &quot;React&quot;;
console.log(input.toLowerCase() === &quot;react&quot;); // true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;4-trim--trimstart--trimend&quot;&gt;4. &lt;code&gt;trim()&lt;/code&gt; / &lt;code&gt;trimStart()&lt;/code&gt; / &lt;code&gt;trimEnd()&lt;/code&gt;&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#4-trim--trimstart--trimend&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;去除空白字符（空格、换行、Tab）。常用于处理表单输入。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;const user = &quot;  admin  &quot;;
console.log(user.trim()); // &quot;admin&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;四-现代实用功能-es6&quot;&gt;四、 现代实用功能 (ES6+)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#四-现代实用功能-es6&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;1-模版字符串-template-literals&quot;&gt;1. 模版字符串 (Template Literals)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-模版字符串-template-literals&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;使用反引号 ```，支持变量插入和多行文本。&lt;strong&gt;强烈推荐代替 &lt;code&gt;+&lt;/code&gt; 号拼接。&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;const name = &quot;Mike&quot;;
const age = 25;

// 旧写法
const oldStr = &quot;My name is &quot; + name + &quot; and I am &quot; + age;

// 新写法 (推荐)
const newStr = `My name is ${name} and I am ${age}`;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;2-padstarttargetlength-padstring--padend&quot;&gt;2. &lt;code&gt;padStart(targetLength, padString)&lt;/code&gt; / &lt;code&gt;padEnd()&lt;/code&gt;&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-padstarttargetlength-padstring--padend&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;用于补全字符串长度。常用于&lt;strong&gt;时间格式化&lt;/strong&gt;或&lt;strong&gt;脱敏显示&lt;/strong&gt;。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;// 时间补零
const hour = &quot;5&quot;;
console.log(hour.padStart(2, &quot;0&quot;)); // &quot;05&quot;

// 手机号脱敏
const phone = &quot;13812345678&quot;;
const last4 = phone.slice(-4);
console.log(last4.padStart(11, &quot;*&quot;)); // &quot;*******5678&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;五-总结高频场景速查表&quot;&gt;五、 总结：高频场景速查表&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#五-总结高频场景速查表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;












































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;场景&lt;/th&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;strong&gt;搜索关键字&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;includes()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;返回 true/false&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;获取位置&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;indexOf()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;没找到返回 -1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;字符串截取&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;slice()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;支持负数，最灵活&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;转为数组&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;split()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;配合数组方法处理复杂逻辑&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;拼接字符串&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;${var}&lt;/code&gt;&lt;/td&gt;&lt;td&gt;模版字符串&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;表单去空格&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;trim()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;处理用户输入&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;替换内容&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;replaceAll()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;或使用正则 &lt;code&gt;/g&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;</content:encoded><category>面试</category><category>面试</category></item><item><title>浏览器存储方式</title><link>https://cjw32.xyz/blog/article/2025122101/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025122101/</guid><description>主流存储方式的详细对比与解析</description><pubDate>Sat, 20 Dec 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;浏览器存储方式&quot;&gt;浏览器存储方式&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#浏览器存储方式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;现代浏览器提供了多种存储机制，用于在客户端保存数据。根据数据的生命周期、大小限制和使用场景，开发者需要选择最适合的方案。以下是主流存储方式的详细对比与解析。&lt;/p&gt;
&lt;h2 id=&quot;1-cookie&quot;&gt;1. Cookie&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-cookie&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Cookie 是最早期的客户端存储机制，主要设计初衷是为了在无状态的 HTTP 协议中维持状态（如用户登录态）。&lt;/p&gt;
&lt;h3 id=&quot;特点&quot;&gt;特点&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#特点&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;大小限制&lt;/strong&gt;：非常小，通常限制在 &lt;strong&gt;4KB&lt;/strong&gt; 左右。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自动发送&lt;/strong&gt;：在同域名的 HTTP 请求中，Cookie 会自动附加在 Request Header 中发送给服务器（这可能造成性能浪费）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;配置项&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Expires&lt;/code&gt;/&lt;code&gt;Max-Age&lt;/code&gt;：设置过期时间。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;HttpOnly&lt;/code&gt;：若设置为 true，JavaScript 无法读取（防止 XSS 攻击窃取 Cookie）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Secure&lt;/code&gt;：只允许在 HTTPS 下传输。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SameSite&lt;/code&gt;：控制跨站请求时是否发送 Cookie（防止 CSRF 攻击）。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;适用场景&quot;&gt;适用场景&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#适用场景&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;存储用户 Token / Session ID（配合 &lt;code&gt;HttpOnly&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;需要服务端读取的小型配置信息。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;代码示例&quot;&gt;代码示例&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#代码示例&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;/**
 * 设置 Cookie 的完整示例
 * 注意：HttpOnly 属性只能由服务器设置，无法在客户端 JS 中设置
 */

// 1. 基础用法：设置路径 (Path)
document.cookie = &quot;username=JohnDoe; path=/&quot;;

// 2. 设置过期时间 (Max-Age 或 Expires)
// Max-Age: 单位为秒 (例如 3600秒 = 1小时)
document.cookie = &quot;token=abc12345; path=/; max-age=3600&quot;;

// Expires: 具体的 UTC 时间字符串
const date = new Date();
date.setTime(date.getTime() + (7 * 24 * 60 * 60 * 1000)); // 7天后
document.cookie = `theme=dark; path=/; expires=${date.toUTCString()}`;

// 3. 安全配置 (Secure &amp;#x26; SameSite)
// Secure: 仅允许在 HTTPS 连接中传输
// SameSite: Strict (完全禁止跨站) | Lax (导航到目标网址时发送) | None (允许跨站，必须配合 Secure)
document.cookie = &quot;tracking_id=xyz987; path=/; Secure; SameSite=Strict&quot;;

// 4. 读取 Cookie (需要自行解析)
console.log(document.cookie); // 输出: &quot;username=JohnDoe; token=abc12345; ...&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;2-web-storage-localstorage--sessionstorage&quot;&gt;2. Web Storage (LocalStorage &amp;#x26; SessionStorage)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-web-storage-localstorage--sessionstorage&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;HTML5 引入了 Web Storage API，旨在提供更大容量且更易用的本地存储，且&lt;strong&gt;不会&lt;/strong&gt;自动随 HTTP 请求发送给服务器。&lt;/p&gt;
&lt;h3 id=&quot;a-localstorage-本地存储&quot;&gt;A. LocalStorage (本地存储)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#a-localstorage-本地存储&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;生命周期&lt;/strong&gt;：&lt;strong&gt;永久有效&lt;/strong&gt;。除非用户手动清除或代码调用清除，否则数据一直存在。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;作用域&lt;/strong&gt;：同源（协议、域名、端口相同）共享。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;大小限制&lt;/strong&gt;：通常为 &lt;strong&gt;5MB&lt;/strong&gt; 左右（不同浏览器略有差异）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;b-sessionstorage-会话存储&quot;&gt;B. SessionStorage (会话存储)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#b-sessionstorage-会话存储&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;生命周期&lt;/strong&gt;：&lt;strong&gt;仅在当前会话（Session）有效&lt;/strong&gt;。当浏览器标签页或窗口关闭时，数据会被清除。
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;注意&lt;/em&gt;：在同一个窗口打开新链接（&lt;code&gt;_self&lt;/code&gt;）会保留，但右键“在新标签页打开”或通过 &lt;code&gt;window.open&lt;/code&gt; 打开的新标签页（取决于浏览器实现和上下文）通常不共享 SessionStorage。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;作用域&lt;/strong&gt;：限制在当前标签页，即使是同源的两个标签页，SessionStorage 也是隔离的。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;大小限制&lt;/strong&gt;：通常为 &lt;strong&gt;5MB&lt;/strong&gt; 左右。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;适用场景-1&quot;&gt;适用场景&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#适用场景-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LocalStorage&lt;/strong&gt;: 网站偏好设置（如深色模式）、购物车数据（未登录状态）、长期缓存的数据。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SessionStorage&lt;/strong&gt;: 表单分步填写的临时数据、一次性敏感信息（关闭页面即焚）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;代码示例-两者-api-相同&quot;&gt;代码示例 (两者 API 相同)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#代码示例-两者-api-相同&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;// API 非常简单，没有复杂的配置项

// 1. 存储数据 (Key-Value)
localStorage.setItem(&apos;theme&apos;, &apos;dark&apos;);
localStorage.setItem(&apos;userSettings&apos;, JSON.stringify({ notifications: true, volume: 80 })); // 存对象需序列化

// 2. 读取数据
const theme = localStorage.getItem(&apos;theme&apos;);
const settings = JSON.parse(localStorage.getItem(&apos;userSettings&apos;) || &apos;{}&apos;);

// 3. 删除特定项
localStorage.removeItem(&apos;theme&apos;);

// 4. 清空所有数据
localStorage.clear();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;3-indexeddb&quot;&gt;3. IndexedDB&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#3-indexeddb&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;IndexedDB 是一个运行在浏览器中的&lt;strong&gt;非关系型数据库 (NoSQL)&lt;/strong&gt;。它比 Web Storage 强大得多，适合存储大量结构化数据。&lt;/p&gt;
&lt;h3 id=&quot;特点-1&quot;&gt;特点&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#特点-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;容量大&lt;/strong&gt;：通常不少于 &lt;strong&gt;250MB&lt;/strong&gt;，甚至可以达到磁盘可用空间的百分比（如 50%）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;异步操作&lt;/strong&gt;：所有操作（读取、写入）都是异步的，不会阻塞主线程（LocalStorage 是同步的，大数据量读取会卡顿）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;支持事务&lt;/strong&gt;：支持事务（Transaction），保证数据一致性。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;支持索引&lt;/strong&gt;：可以给字段建立索引，进行高效查询。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;支持二进制存储&lt;/strong&gt;：可以存储 &lt;code&gt;ArrayBuffer&lt;/code&gt;、&lt;code&gt;Blob&lt;/code&gt; 等文件对象。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;适用场景-2&quot;&gt;适用场景&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#适用场景-2&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;离线应用（PWA）的大量数据存储。&lt;/li&gt;
&lt;li&gt;富文本编辑器保存草稿、图片或文件缓存。&lt;/li&gt;
&lt;li&gt;复杂的本地数据管理系统。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;代码示例-配置数据库结构&quot;&gt;代码示例 (配置数据库结构)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#代码示例-配置数据库结构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;span&gt;27&lt;/span&gt;&lt;span&gt;28&lt;/span&gt;&lt;span&gt;29&lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;span&gt;31&lt;/span&gt;&lt;span&gt;32&lt;/span&gt;&lt;span&gt;33&lt;/span&gt;&lt;span&gt;34&lt;/span&gt;&lt;span&gt;35&lt;/span&gt;&lt;span&gt;36&lt;/span&gt;&lt;span&gt;37&lt;/span&gt;&lt;span&gt;38&lt;/span&gt;&lt;span&gt;39&lt;/span&gt;&lt;span&gt;40&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;// 打开数据库: open(数据库名, 版本号)
const request = indexedDB.open(&quot;MyDatabase&quot;, 1);

// 配置阶段：仅在数据库版本升级（第一次打开或版本号增加）时触发
request.onupgradeneeded = function(event) {
  const db = event.target.result;
  
  // 1. 创建对象仓库 (类似于 SQL 中的 Table)
  // 配置项: keyPath (主键字段), autoIncrement (是否自增)
  if (!db.objectStoreNames.contains(&quot;users&quot;)) {
    const objectStore = db.createObjectStore(&quot;users&quot;, { keyPath: &quot;id&quot;, autoIncrement: true });
    
    // 2. 创建索引 (用于查询)
    // createIndex(索引名, 键路径, 配置项)
    // unique: false (允许重复值), unique: true (必须唯一，如邮箱)
    objectStore.createIndex(&quot;name&quot;, &quot;name&quot;, { unique: false });
    objectStore.createIndex(&quot;email&quot;, &quot;email&quot;, { unique: true });
  }
};

request.onsuccess = function(event) {
  const db = event.target.result;
  
  // 3. 开启事务进行读写
  // db.transaction(scope, mode)
  // 参数1 [&quot;users&quot;]: 作用域，声明本次事务需要操作哪些表（Object Store）。
  //                  因为 IndexedDB 建立事务时会锁定这些表，为了性能必须明确指定。
  // 参数2 &quot;readwrite&quot;: 事务模式，&quot;readonly&quot; (默认，只读) 或 &quot;readwrite&quot; (读写)。
  const transaction = db.transaction([&quot;users&quot;], &quot;readwrite&quot;);
  
  // 4. 获取具体的对象仓库（表）进行操作
  // 必须通过事务对象(transaction)来获取表，而不是直接通过 db 获取
  const objectStore = transaction.objectStore(&quot;users&quot;);
  
  // 添加数据
  const addRequest = objectStore.add({ name: &quot;Alice&quot;, email: &quot;alice@example.com&quot;, age: 25 });
  
  addRequest.onsuccess = () =&gt; console.log(&quot;数据添加成功&quot;);
  addRequest.onerror = () =&gt; console.error(&quot;数据添加失败&quot;);
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;4-cache-api&quot;&gt;4. Cache API&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#4-cache-api&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Cache API 最初是为 Service Worker 设计的，用于网络资源的缓存，但也可以在普通页面脚本中使用。&lt;/p&gt;
&lt;h3 id=&quot;特点-2&quot;&gt;特点&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#特点-2&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;基于 Request/Response&lt;/strong&gt;：专门用于存储网络请求对（Request 对象和 Response 对象）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可编程缓存&lt;/strong&gt;：开发者可以精确控制缓存哪些资源（CSS, JS, 图片等）以及何时更新。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;异步&lt;/strong&gt;：基于 Promise。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;适用场景-3&quot;&gt;适用场景&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#适用场景-3&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;PWA (Progressive Web App)&lt;/strong&gt;：实现离线访问。&lt;/li&gt;
&lt;li&gt;预加载关键资源。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;5-综合对比表&quot;&gt;5. 综合对比表&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#5-综合对比表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;





















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;特性&lt;/th&gt;&lt;th&gt;Cookie&lt;/th&gt;&lt;th&gt;LocalStorage&lt;/th&gt;&lt;th&gt;SessionStorage&lt;/th&gt;&lt;th&gt;IndexedDB&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;数据生命周期&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;可设置过期时间，默认关闭浏览器失效&lt;/td&gt;&lt;td&gt;永久有效，直到手动删除&lt;/td&gt;&lt;td&gt;仅在当前标签页会话有效&lt;/td&gt;&lt;td&gt;永久有效，直到手动删除&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;存储大小&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;~4KB&lt;/td&gt;&lt;td&gt;~5MB&lt;/td&gt;&lt;td&gt;~5MB&lt;/td&gt;&lt;td&gt;很大 (&gt;250MB)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;与服务器通信&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;每次 HTTP 请求都会自动携带&lt;/td&gt;&lt;td&gt;不参与服务器通信&lt;/td&gt;&lt;td&gt;不参与服务器通信&lt;/td&gt;&lt;td&gt;不参与服务器通信&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;易用性&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;较差 (原生 API 难用)&lt;/td&gt;&lt;td&gt;简单 (Key-Value)&lt;/td&gt;&lt;td&gt;简单 (Key-Value)&lt;/td&gt;&lt;td&gt;复杂 (类似数据库操作)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;访问性能&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;同步 (且影响网络带宽)&lt;/td&gt;&lt;td&gt;同步 (大数据量可能阻塞 UI)&lt;/td&gt;&lt;td&gt;同步&lt;/td&gt;&lt;td&gt;异步 (高性能)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;主要用途&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;身份验证、Session ID&lt;/td&gt;&lt;td&gt;简单配置、持久化数据&lt;/td&gt;&lt;td&gt;临时表单、单次会话状态&lt;/td&gt;&lt;td&gt;复杂结构化数据、离线应用&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&quot;总结建议&quot;&gt;总结建议&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#总结建议&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;需要与服务端交互的 Auth Token&lt;/strong&gt;：优先考虑 &lt;strong&gt;Cookie&lt;/strong&gt; (配合 HttpOnly)。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;简单的键值对数据 (设置、标志位)&lt;/strong&gt;：使用 &lt;strong&gt;LocalStorage&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;临时保存的数据 (刷新页面还在，关闭页面清除)&lt;/strong&gt;：使用 &lt;strong&gt;SessionStorage&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;大量结构化数据、文件、离线数据&lt;/strong&gt;：务必使用 &lt;strong&gt;IndexedDB&lt;/strong&gt;，避免 LocalStorage 阻塞主线程。&lt;/li&gt;
&lt;/ol&gt;</content:encoded><category>面试</category><category>面试</category></item><item><title>Vue 2 vs Vue 3 核心差异深度解析</title><link>https://cjw32.xyz/blog/article/2025122102/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025122102/</guid><description>两者在核心原理、开发体验和新特性上的主要区别</description><pubDate>Sat, 20 Dec 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;vue-2-vs-vue-3-核心差异深度解析&quot;&gt;Vue 2 vs Vue 3 核心差异深度解析&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#vue-2-vs-vue-3-核心差异深度解析&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Vue 3 相比 Vue 2 带来了巨大的性能提升和架构改进。以下是两者在核心原理、开发体验和新特性上的主要区别。&lt;/p&gt;
&lt;h2 id=&quot;1-响应式系统原理-核心区别&quot;&gt;1. 响应式系统原理 (核心区别)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-响应式系统原理-核心区别&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;这是 Vue 3 最底层的变革，直接决定了性能上限和开发体验。&lt;/p&gt;
&lt;h3 id=&quot;vue-2-objectdefineproperty-的局限&quot;&gt;Vue 2: Object.defineProperty 的局限&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#vue-2-objectdefineproperty-的局限&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Vue 2 使用 ES5 的 &lt;code&gt;Object.defineProperty&lt;/code&gt; API 来劫持对象的 getter 和 setter。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;初始化开销大&lt;/strong&gt;：在组件初始化时，Vue 2 必须&lt;strong&gt;递归遍历&lt;/strong&gt; data 对象的所有属性（包括嵌套属性），将它们转换为 getter/setter。如果不访问这些属性，它们依然会被转换，这在数据量大时会造成明显的性能损耗。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;无法监听属性新增/删除&lt;/strong&gt;：由于 JavaScript 的限制，&lt;code&gt;Object.defineProperty&lt;/code&gt; 只能劫持&lt;strong&gt;已存在&lt;/strong&gt;的属性。
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;this.obj.newProp = 123&lt;/code&gt; &lt;strong&gt;不会&lt;/strong&gt;触发视图更新。&lt;/li&gt;
&lt;li&gt;必须使用 &lt;code&gt;Vue.set(this.obj, &apos;newProp&apos;, 123)&lt;/code&gt; 或 &lt;code&gt;this.$set&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数组监听缺陷&lt;/strong&gt;：Vue 2 不能通过 &lt;code&gt;Object.defineProperty&lt;/code&gt; 完美拦截数组索引的修改（如 &lt;code&gt;arr[0] = 1&lt;/code&gt;）和长度修改（&lt;code&gt;arr.length = 0&lt;/code&gt;）。
&lt;ul&gt;
&lt;li&gt;Vue 2 不得不重写（Monkey Patch）了数组的 7 个变异方法（&lt;code&gt;push&lt;/code&gt;, &lt;code&gt;pop&lt;/code&gt;, &lt;code&gt;shift&lt;/code&gt;...）来实现响应式。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;vue-3-proxy-的强大能力&quot;&gt;Vue 3: Proxy 的强大能力&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#vue-3-proxy-的强大能力&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Vue 3 使用 ES6 的 &lt;code&gt;Proxy&lt;/code&gt; API，它不是劫持属性，而是&lt;strong&gt;代理整个对象&lt;/strong&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;懒代理 (Lazy Observation)&lt;/strong&gt;：Proxy 默认只代理第一层。只有当你真正访问嵌套对象时，Vue 3 才会通过 Reflect 动态地将嵌套对象包装为 Proxy。这使得初始化速度极大提升，内存占用显著降低。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;动态属性支持&lt;/strong&gt;：Proxy 可以拦截对象上任意属性的变化，包括新增属性和删除属性。
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;state.newProp = 123&lt;/code&gt; &lt;strong&gt;直接生效&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数组完美支持&lt;/strong&gt;：Proxy 可以原生拦截数组索引修改和 length 变化，无需再重写数组方法。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;更多拦截操作&lt;/strong&gt;：Proxy 可以拦截多达 13 种操作，包括 &lt;code&gt;has&lt;/code&gt; (in 操作符), &lt;code&gt;deleteProperty&lt;/code&gt; (delete 操作符) 等，这让 Vue 3 的响应式能力更全面。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;深度对比表&quot;&gt;深度对比表&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#深度对比表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;












































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;特性&lt;/th&gt;&lt;th&gt;Vue 2 (Object.defineProperty)&lt;/th&gt;&lt;th&gt;Vue 3 (Proxy)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;拦截粒度&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;属性级别 (必须遍历所有 key)&lt;/td&gt;&lt;td&gt;对象级别 (直接拦截整个对象)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;初始化性能&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;递归遍历，开销大&lt;/td&gt;&lt;td&gt;&lt;strong&gt;懒代理&lt;/strong&gt;，按需转换，快&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;新增/删除属性&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;不支持 (需用 &lt;code&gt;$set&lt;/code&gt; / &lt;code&gt;$delete&lt;/code&gt;)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;原生支持&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;数组索引修改&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;不支持 (需用 &lt;code&gt;$set&lt;/code&gt; 或 &lt;code&gt;splice&lt;/code&gt;)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;原生支持&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Map / Set 支持&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;不支持&lt;/td&gt;&lt;td&gt;&lt;strong&gt;支持&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Class 语法&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;支持较弱&lt;/td&gt;&lt;td&gt;支持&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;兼容性&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;IE9+&lt;/td&gt;&lt;td&gt;不支持 IE11 (因 Proxy 无法被 Polyfill)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;h3 id=&quot;伪代码原理解析&quot;&gt;伪代码原理解析&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#伪代码原理解析&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;为了让你理解得更透彻，这里是两者实现的简化逻辑对比：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Vue 2 实现逻辑 (简化):&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;function defineReactive(obj, key, val) {
  // 必须针对每一个 key 进行定义
  Object.defineProperty(obj, key, {
    get() {
      // 收集依赖
      return val;
    },
    set(newVal) {
      if (newVal !== val) {
        val = newVal;
        // 触发更新
        updateView();
      }
    }
  });
}
// 初始化时必须立即递归遍历所有属性
for (const key in data) {
  defineReactive(data, key, data[key]);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Vue 3 实现逻辑 (简化):&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;const handler = {
  get(target, key, receiver) {
    // 收集依赖 (track)
    const result = Reflect.get(target, key, receiver);
    // 懒代理：只有当属性值是对象且被访问时，才递归创建 Proxy
    return isObject(result) ? reactive(result) : result;
  },
  set(target, key, value, receiver) {
    const oldValue = target[key];
    const result = Reflect.set(target, key, value, receiver);
    // 触发更新 (trigger)
    if (oldValue !== value) {
      updateView();
    }
    return result;
  },
  deleteProperty(target, key) {
    // 还能拦截 delete 操作
    const result = Reflect.deleteProperty(target, key);
    updateView();
    return result;
  }
};
// 不需要预先遍历 key，直接代理整个对象
const proxy = new Proxy(data, handler);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;2-api-风格options-api-vs-composition-api&quot;&gt;2. API 风格：Options API vs Composition API&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-api-风格options-api-vs-composition-api&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;这是开发者感受最直观的变化。&lt;/p&gt;
&lt;h3 id=&quot;vue-2-options-api-选项式-api&quot;&gt;Vue 2: Options API (选项式 API)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#vue-2-options-api-选项式-api&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;代码按照 &lt;code&gt;data&lt;/code&gt;, &lt;code&gt;methods&lt;/code&gt;, &lt;code&gt;computed&lt;/code&gt;, &lt;code&gt;watch&lt;/code&gt; 等选项块进行组织。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;优点&lt;/strong&gt;：结构清晰，适合初学者，强制规范。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;缺点&lt;/strong&gt;：当组件逻辑复杂时，同一功能的代码（比如“搜索功能”）会分散在 data、methods 等不同地方，导致代码难以阅读和维护（&quot;反复横跳&quot;）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;vue-3-composition-api-组合式-api&quot;&gt;Vue 3: Composition API (组合式 API)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#vue-3-composition-api-组合式-api&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;使用 &lt;code&gt;setup()&lt;/code&gt; 函数（或 &lt;code&gt;&amp;#x3C;script setup&gt;&lt;/code&gt;），将逻辑关注点组织在一起。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;优点&lt;/strong&gt;：逻辑复用极强（Hooks），类似 React Hooks；同一功能的代码集中在一起，易于维护；更好的类型推导。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;兼容性&lt;/strong&gt;：Vue 3 依然完全支持 Options API。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;代码对比&quot;&gt;代码对比&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#代码对比&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Vue 2 (Options API):&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;export default {
  data() {
    return { count: 0 };
  },
  methods: {
    increment() {
      this.count++;
    }
  },
  mounted() {
    console.log(&apos;mounted&apos;);
  }
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Vue 3 (Composition API - script setup):&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;script setup&gt;
import { ref, onMounted } from &apos;vue&apos;;

// 状态定义
const count = ref(0);

// 方法定义
const increment = () =&gt; {
  count.value++;
};

// 生命周期
onMounted(() =&gt; {
  console.log(&apos;mounted&apos;);
});
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;3-生命周期钩子-lifecycle-hooks&quot;&gt;3. 生命周期钩子 (Lifecycle Hooks)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#3-生命周期钩子-lifecycle-hooks&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Vue 3 对生命周期钩子进行了重命名，使其更语义化，并提供了对应 Composition API 的函数。&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;
































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Vue 2 (Options API)&lt;/th&gt;&lt;th&gt;Vue 3 (Options API)&lt;/th&gt;&lt;th&gt;Vue 3 (Composition API)&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;beforeCreate&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;beforeCreate&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;setup()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;setup 执行时机更早&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;created&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;created&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;setup()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;setup 取代了这两个钩子&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;beforeMount&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;beforeMount&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;onBeforeMount&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;mounted&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;mounted&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;onMounted&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;beforeUpdate&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;beforeUpdate&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;onBeforeUpdate&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;updated&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;updated&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;onUpdated&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;code&gt;beforeDestroy&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;&lt;code&gt;beforeUnmount&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;onBeforeUnmount&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;名称变更&lt;/strong&gt;：销毁变成了卸载&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;&lt;code&gt;destroyed&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;&lt;code&gt;unmounted&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;onUnmounted&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;名称变更&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;errorCaptured&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;errorCaptured&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;onErrorCaptured&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&quot;4-多根节点-fragments&quot;&gt;4. 多根节点 (Fragments)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#4-多根节点-fragments&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Vue 2&lt;/strong&gt;: 组件模板必须有一个唯一的根元素。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vue 3&lt;/strong&gt;: &lt;strong&gt;支持多根节点&lt;/strong&gt;（Fragments）。Vue 3 会自动在虚拟 DOM 中创建一个 Fragment 节点来包裹它们，减少了不必要的 DOM 层级嵌套。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;5-typescript-支持&quot;&gt;5. TypeScript 支持&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#5-typescript-支持&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Vue 2&lt;/strong&gt;: 对 TypeScript 支持较弱。因为 &lt;code&gt;this&lt;/code&gt; 上下文的动态性，很难进行完美的类型推导，通常需要使用 &lt;code&gt;vue-class-component&lt;/code&gt; 装饰器写法，体验较为割裂。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vue 3&lt;/strong&gt;: 源码完全使用 TypeScript 重写。Composition API 天然对类型推导友好，不再依赖复杂的 &lt;code&gt;this&lt;/code&gt;，开发体验极佳。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;6-新增内置组件与特性&quot;&gt;6. 新增内置组件与特性&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#6-新增内置组件与特性&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;teleport-传送门&quot;&gt;Teleport (传送门)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#teleport-传送门&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;允许将组件的 DOM 结构渲染到该组件 DOM 树之外的地方（例如直接挂载到 &lt;code&gt;body&lt;/code&gt; 下），这对于制作&lt;strong&gt;模态框 (Modal)&lt;/strong&gt;、&lt;strong&gt;通知 (Toast)&lt;/strong&gt; 非常有用，避免了 &lt;code&gt;z-index&lt;/code&gt; 层级冲突问题。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;Teleport to=&quot;body&quot;&gt;
  &amp;#x3C;div class=&quot;modal&quot;&gt;我是挂载在 body 下的模态框&amp;#x3C;/div&gt;
&amp;#x3C;/Teleport&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;suspense-实验性&quot;&gt;Suspense (实验性)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#suspense-实验性&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;允许在组件树中协调异步依赖的处理。可以在深层组件加载完成前，在父组件渲染一个“加载中”状态。&lt;/p&gt;
&lt;h3 id=&quot;tree-shaking-按需打包&quot;&gt;Tree Shaking (按需打包)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#tree-shaking-按需打包&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Vue 3 的全局 API（如 &lt;code&gt;nextTick&lt;/code&gt;, &lt;code&gt;set&lt;/code&gt; 等）改为 ES 模块导出。如果你不使用某个功能，打包工具可以将其摇掉（Remove），从而减小最终包的体积。&lt;/p&gt;
&lt;h2 id=&quot;7-全局-api-变更&quot;&gt;7. 全局 API 变更&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#7-全局-api-变更&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Vue 2 使用 &lt;code&gt;new Vue()&lt;/code&gt; 并修改 &lt;code&gt;Vue&lt;/code&gt; 全局对象，这导致在同一页面运行多个 Vue 实例时容易相互污染。Vue 3 改为使用 &lt;code&gt;createApp&lt;/code&gt; 创建应用实例。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;// Vue 3 写法
import { createApp } from &apos;vue&apos;;
import App from &apos;./App.vue&apos;;

const app = createApp(App);
app.use(MyPlugin); // 仅影响当前实例
app.mount(&apos;#app&apos;);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;总结&quot;&gt;总结&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#总结&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Vue 3 在&lt;strong&gt;性能&lt;/strong&gt;（Proxy、Virtual DOM 优化）、&lt;strong&gt;可维护性&lt;/strong&gt;（Composition API、TypeScript）和&lt;strong&gt;架构灵活性&lt;/strong&gt;（Fragments、Teleport）上都全面优于 Vue 2。&lt;/p&gt;
&lt;p&gt;如果是新项目，&lt;strong&gt;强烈建议直接使用 Vue 3 + Script Setup + TypeScript&lt;/strong&gt;。&lt;/p&gt;</content:encoded><category>面试</category><category>面试</category></item><item><title>Server-Sent Events (SSE) 技术详解</title><link>https://cjw32.xyz/blog/article/2025122103/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025122103/</guid><description>SSE是一种基于 HTTP 的服务器推送技术</description><pubDate>Sat, 20 Dec 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;server-sent-events-sse-技术详解&quot;&gt;Server-Sent Events (SSE) 技术详解&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#server-sent-events-sse-技术详解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;SSE (Server-Sent Events) 是一种基于 HTTP 的服务器推送技术。它允许服务器通过一个长期的 HTTP 连接，源源不断地向客户端发送文本数据流。&lt;/p&gt;
&lt;h2 id=&quot;1-核心概念&quot;&gt;1. 核心概念&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-核心概念&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;通俗地说，SSE 就像是收音机广播。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;客户端&lt;/strong&gt;：打开收音机（建立连接）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;服务器&lt;/strong&gt;：不断发送广播信号（推送数据）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;单向性&lt;/strong&gt;：你只能听广播，不能通过收音机向电台说话（只能服务器发给客户端）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;工作流程&quot;&gt;工作流程&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#工作流程&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;客户端发起一个普通的 HTTP 请求。&lt;/li&gt;
&lt;li&gt;服务器响应头中设置 &lt;code&gt;Content-Type: text/event-stream&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;连接保持打开状态（Keep-Alive）。&lt;/li&gt;
&lt;li&gt;服务器随时可以通过这个连接发送数据。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;2-sse-vs-websocket&quot;&gt;2. SSE vs WebSocket&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-sse-vs-websocket&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;这是面试和架构选型中最常见的问题。&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;







































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;特性&lt;/th&gt;&lt;th&gt;SSE (Server-Sent Events)&lt;/th&gt;&lt;th&gt;WebSocket&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;通信方向&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;单向&lt;/strong&gt; (Server -&gt; Client)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;双向&lt;/strong&gt; (全双工)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;协议&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;基于 HTTP 协议&lt;/td&gt;&lt;td&gt;独立的 WebSocket 协议 (TCP)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;数据格式&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;仅支持 &lt;strong&gt;文本&lt;/strong&gt; (UTF-8)&lt;/td&gt;&lt;td&gt;支持 &lt;strong&gt;文本&lt;/strong&gt; 和 &lt;strong&gt;二进制&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;自动重连&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;原生支持&lt;/strong&gt; (浏览器自动处理)&lt;/td&gt;&lt;td&gt;不支持 (需手写心跳重连逻辑)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;使用难度&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;简单 (像普通 HTTP 请求)&lt;/td&gt;&lt;td&gt;较复杂 (需专门的握手和协议处理)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;典型应用&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;股票行情、新闻推送、ChatGPT 回复&lt;/td&gt;&lt;td&gt;在线聊天室、多人游戏、协作编辑&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&quot;3-实战代码示例&quot;&gt;3. 实战代码示例&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#3-实战代码示例&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;a-后端实现-nodejsexpress&quot;&gt;A. 后端实现 (Node.js/Express)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#a-后端实现-nodejsexpress&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;SSE 对数据格式有严格要求，每条消息必须以 &lt;code&gt;data:&lt;/code&gt; 开头，以 &lt;code&gt;\n\n&lt;/code&gt; 结尾。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;span&gt;27&lt;/span&gt;&lt;span&gt;28&lt;/span&gt;&lt;span&gt;29&lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;span&gt;31&lt;/span&gt;&lt;span&gt;32&lt;/span&gt;&lt;span&gt;33&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;const express = require(&apos;express&apos;);
const app = express();

app.get(&apos;/stream&apos;, (req, res) =&gt; {
  // 1. 设置关键 Header
  res.writeHead(200, {
    &apos;Content-Type&apos;: &apos;text/event-stream&apos;, // 声明流式数据
    &apos;Cache-Control&apos;: &apos;no-cache&apos;,         // 禁止缓存
    &apos;Connection&apos;: &apos;keep-alive&apos;,          // 保持长连接
    &apos;Access-Control-Allow-Origin&apos;: &apos;*&apos;   // 允许跨域
  });

  // 2. 发送初始消息
  res.write(&apos;data: 连接成功！\n\n&apos;);

  // 3. 模拟每隔 1 秒推送一次数据
  const intervalId = setInterval(() =&gt; {
    const message = {
      time: new Date().toLocaleTimeString(),
      value: Math.random()
    };
    // 注意格式：data: &amp;#x3C;JSON字符串&gt;\n\n
    res.write(`data: ${JSON.stringify(message)}\n\n`);
  }, 1000);

  // 4. 当客户端断开连接时，清理定时器
  req.on(&apos;close&apos;, () =&gt; {
    clearInterval(intervalId);
    console.log(&apos;客户端已断开&apos;);
  });
});

app.listen(3000, () =&gt; console.log(&apos;SSE Server running on port 3000&apos;));
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;b-前端实现-原生-eventsource-api&quot;&gt;B. 前端实现 (原生 EventSource API)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#b-前端实现-原生-eventsource-api&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;浏览器提供了原生的 &lt;code&gt;EventSource&lt;/code&gt; 对象来处理 SSE。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;// 1. 建立连接
const eventSource = new EventSource(&apos;http://localhost:3000/stream&apos;);

// 2. 监听消息
eventSource.onmessage = function(event) {
  const data = JSON.parse(event.data);
  console.log(&apos;收到服务器数据:&apos;, data);
  
  // 更新 UI
  document.getElementById(&apos;result&apos;).innerText = data.time;
};

// 3. 监听错误 (包括连接中断)
eventSource.onerror = function(err) {
  console.error(&apos;连接出错:&apos;, err);
  // 注意：EventSource 默认会自动尝试重连，无需手动干预
};

// 4. 手动关闭连接
// eventSource.close();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;4-sse-的高级特性&quot;&gt;4. SSE 的高级特性&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#4-sse-的高级特性&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;除了基础的 &lt;code&gt;data&lt;/code&gt; 字段，SSE 协议还支持其他字段来实现高级功能。特别要注意&lt;strong&gt;自动重连&lt;/strong&gt;与&lt;strong&gt;数据补全&lt;/strong&gt;的区别。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;id: 101           &amp;#x3C;-- 消息 ID (关键：用于断线重连恢复)
event: update     &amp;#x3C;-- 自定义事件类型
retry: 5000       &amp;#x3C;-- 告诉浏览器如果断连，5秒后重试
data: hello world &amp;#x3C;-- 数据内容
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;自动重连与断点续传机制详解&quot;&gt;自动重连与断点续传机制详解&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#自动重连与断点续传机制详解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;自动重连 (无需代码)&lt;/strong&gt;： 当连接中断（网络波动或服务器重启）时，浏览器会自动在约 3 秒后尝试重新连接。这是浏览器的默认行为，开发者无需编写任何前端代码。可以通过服务器发送 &lt;code&gt;retry: 5000&lt;/code&gt; 字段来修改这个重试间隔。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据补全 (需要服务端配合)&lt;/strong&gt;： &lt;strong&gt;仅仅自动重连并不保证能收到“剩余的数据”。&lt;/strong&gt; 为了不丢失断开期间的数据，必须配合 ID 机制：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;服务端&lt;/strong&gt;：发送每条消息时必须带上 &lt;code&gt;id: 序号&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;浏览器&lt;/strong&gt;：重连时，会自动在新的 HTTP 请求头中带上 &lt;code&gt;Last-Event-ID: 序号&lt;/code&gt;（告诉服务器我上次收到了哪）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;服务端逻辑&lt;/strong&gt;：&lt;strong&gt;必须读取&lt;/strong&gt;这个 Header，并根据 ID 从数据库或缓存中把断开期间错过的消息补发给客户端。如果服务端不处理这个 Header，重连后就只能接收最新的数据，中间的数据会丢失。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;5-优缺点总结&quot;&gt;5. 优缺点总结&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#5-优缺点总结&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;优点&quot;&gt;优点&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#优点&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;轻量级&lt;/strong&gt;：不需要像 WebSocket 那样升级协议，不仅对服务器压力小，而且防火墙/代理服务器对 HTTP 更友好。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自动重连&lt;/strong&gt;：浏览器原生内置了重连机制，开发成本极低。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;简单&lt;/strong&gt;：对于只需要服务器推送的场景（如大盘走势），SSE 是最简单的解决方案。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;缺点&quot;&gt;缺点&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#缺点&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;单向性&lt;/strong&gt;：如果客户端也需要频繁向服务器发送数据（如实时游戏），SSE 不合适。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;连接限制&lt;/strong&gt;：HTTP/1.1 限制浏览器对同一域名的并发连接数（通常是 6 个）。如果打开多个 Tab 页，连接池可能会被占满。（HTTP/2 解决了这个问题）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;仅支持文本&lt;/strong&gt;：无法直接传输二进制文件（WebSockets 支持）。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;6-经典案例chatgpt&quot;&gt;6. 经典案例：ChatGPT&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#6-经典案例chatgpt&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;目前最火的 SSE 应用就是 &lt;strong&gt;ChatGPT&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;当你和 AI 对话时，AI 的回复是一个字一个字蹦出来的。这&lt;strong&gt;不是&lt;/strong&gt; WebSocket，而是 &lt;strong&gt;SSE&lt;/strong&gt;。 服务器通过 SSE 流，生成一个 token 就推送到前端渲染一个，从而实现了“打字机”效果，让用户感觉响应速度很快，不需要等待整段话生成完毕。&lt;/p&gt;</content:encoded><category>面试</category><category>面试</category></item><item><title>深浅拷贝，以及JS如何判断数据类型</title><link>https://cjw32.xyz/blog/article/2025112401/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025112401/</guid><description>先讲 JS 数据类型判断的四种方案（typeof、instanceof、constructor、Object.prototype.toString.call）及各自坑点并手写 getType，再对比深浅拷贝原理，给出 Object.assign 浅拷贝与递归 + WeakMap 解决循环引用的深拷贝实现。</description><pubDate>Sun, 23 Nov 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;深浅拷贝以及js如何判断数据类型&quot;&gt;深浅拷贝，以及JS如何判断数据类型&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#深浅拷贝以及js如何判断数据类型&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h4 id=&quot;1-最基础的方法typeof&quot;&gt;1. 最基础的方法：&lt;code&gt;typeof&lt;/code&gt;&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-最基础的方法typeof&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：简单，适合判断&lt;strong&gt;基础数据类型&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;适用&lt;/strong&gt;：Number, String, Boolean, Symbol, Undefined, Function。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;局限性（面试必考点）&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;null&lt;/code&gt; 的陷阱&lt;/strong&gt;：&lt;code&gt;typeof null&lt;/code&gt; 会返回 &lt;code&gt;&apos;object&apos;&lt;/code&gt;（这是 JS 的历史遗留 Bug）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;引用类型无法区分&lt;/strong&gt;：除了 Function 外，其他的引用类型（Array, Date, RegExp, Error）都会统统返回 &lt;code&gt;&apos;object&apos;&lt;/code&gt;，无法具体区分。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &apos;number&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;1&apos;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &apos;string&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &apos;undefined&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &apos;boolean&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Symbol&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &apos;symbol&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &apos;object&apos; (注意！)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &apos;object&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &apos;object&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;2-基于原型链的方法instanceof&quot;&gt;2. 基于原型链的方法：&lt;code&gt;instanceof&lt;/code&gt;&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-基于原型链的方法instanceof&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：适合判断&lt;strong&gt;引用数据类型&lt;/strong&gt;（Object），检测构造函数的 &lt;code&gt;prototype&lt;/code&gt; 属性是否出现在某个实例对象的原型链上。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;适用&lt;/strong&gt;：Array, Date, RegExp(正则) 等对象类型。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;局限性&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;不能判断基础类型&lt;/strong&gt;：比如 &lt;code&gt;1 instanceof Number&lt;/code&gt; 为 &lt;code&gt;false&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;原型链可被修改&lt;/strong&gt;：如果手动修改了原型指向，结果可能不准确。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多窗口/iframe 问题&lt;/strong&gt;：在不同 iframe 中，全局对象不同，&lt;code&gt;[] instanceof Array&lt;/code&gt; 可能会失效。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Array&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;3-构造函数属性constructor&quot;&gt;3. 构造函数属性：&lt;code&gt;constructor&lt;/code&gt;&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#3-构造函数属性constructor&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：查看对象的构造函数。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;适用&lt;/strong&gt;：大部分类型。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;局限性&lt;/strong&gt;：非常不安全。因为 &lt;code&gt;constructor&lt;/code&gt; 属性是可以被随意修改的，而且 &lt;code&gt;null&lt;/code&gt;和 &lt;code&gt;undefined&lt;/code&gt; 没有 &lt;code&gt;constructor&lt;/code&gt;。一般不推荐作为首选方案。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;JavaScript&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;constructor &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; Array &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;4-终极全能方案objectprototypetostringcall&quot;&gt;4. 终极全能方案：&lt;code&gt;Object.prototype.toString.call()&lt;/code&gt;&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#4-终极全能方案objectprototypetostringcall&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;特点&lt;/strong&gt;：这是&lt;strong&gt;最准确、最通用&lt;/strong&gt;的方法，也是面试中的“标准答案”。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;原理&lt;/strong&gt;：所有对象都继承自 Object，调用 Object 原型上的 &lt;code&gt;toString&lt;/code&gt; 方法，会返回格式为 &lt;code&gt;[object type]&lt;/code&gt; 的字符串。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;适用&lt;/strong&gt;：所有类型（包括 &lt;code&gt;null&lt;/code&gt; 和 &lt;code&gt;undefined&lt;/code&gt;）。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;[object Number]&quot;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;1&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;[object String]&quot;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;[object Boolean]&quot;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;[object Null]&quot;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;undefined&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;[object Undefined]&quot;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;[object Array]&quot;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;[object Function]&quot;&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;[object Object]&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;h3 id=&quot;手写通用类型判断函数&quot;&gt;手写通用类型判断函数&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#手写通用类型判断函数&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getType&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 1. 处理 null 和 undefined (虽然 toString 也能处理，但这样更直观)&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;null&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; value &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;undefined&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;undefined&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 2. 使用 typeof 处理基础类型 (性能稍好)&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 注意：Function 也是 &apos;function&apos;，这里也可以直接返回&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; value &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;object&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; value&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// 3. 使用 Object.prototype.toString.call 处理复杂类型&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// slice(8, -1) 是为了去掉 &quot;[object &quot; 和 &quot;]&quot;，只保留类型名称&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;prototype&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toLowerCase&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;深浅拷贝&quot;&gt;深浅拷贝&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#深浅拷贝&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;第一，从原理上讲：&lt;/strong&gt; &lt;strong&gt;浅拷贝 (Shallow Copy)&lt;/strong&gt; 就像是‘复制了钥匙’。对于引用类型，它只复制了指向堆内存中对象的地址（指针）。所以如果修改了新对象里的属性，原对象也会受到影响，因为它们指向的是同一个房间。 &lt;strong&gt;深拷贝 (Deep Copy)&lt;/strong&gt; 则是‘建造了一个一模一样的新房子’。它会在堆内存中开辟新的空间，完整复制原对象的所有属性。新旧对象互不干扰。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第二，在日常开发中：&lt;/strong&gt; 如果只是简单的对象，我会用 &lt;code&gt;Object.assign()&lt;/code&gt; 或者 ES6 的展开运算符 &lt;code&gt;...&lt;/code&gt; 来做浅拷贝。 如果要深拷贝，最简单粗暴的方法是 &lt;code&gt;JSON.parse(JSON.stringify())&lt;/code&gt;，但这只适用于纯数据对象。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第三，关于特殊情况：&lt;/strong&gt; &lt;code&gt;JSON&lt;/code&gt; 方法有局限性，比如它无法处理函数、正则、&lt;code&gt;Date&lt;/code&gt; 对象，遇到循环引用还会报错。 所以在复杂的场景或者面试手写题中，我会采用&lt;strong&gt;递归&lt;/strong&gt;的方式来实现深拷贝，并且需要通过 &lt;code&gt;WeakMap&lt;/code&gt; 来解决循环引用的问题。”&lt;/p&gt;
&lt;h3 id=&quot;手写实现深拷贝&quot;&gt;手写实现深拷贝&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#手写实现深拷贝&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;span&gt;27&lt;/span&gt;&lt;span&gt;28&lt;/span&gt;&lt;span&gt;29&lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;span&gt;31&lt;/span&gt;&lt;span&gt;32&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;deepClone&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; hash &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;WeakMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 如果是null或者不是对象，则直接返回&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; obj &lt;span class=&quot;token operator&quot;&gt;!==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;object&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; obj&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 如果是正则表达式，则直接返回&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;RegExp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;RegExp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 如果是日期对象，则直接返回&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj &lt;span class=&quot;token keyword&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 如果是函数，则直接返回&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;typeof&lt;/span&gt; obj &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;function&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; obj&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//如果已经存在于hash中，直接返回克隆后的对象&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;map&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; hash&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 创建一个新的对象或数组&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cloneObj &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 将新对象存入hash中&lt;/span&gt;
    hash&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cloneObj&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 递归克隆&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; key &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; obj&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;hasOwnProperty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            cloneObj&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;deepClone&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;obj&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;key&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; hash&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded><category>面试</category><category>面试</category></item><item><title>防抖节流</title><link>https://cjw32.xyz/blog/article/2025112402/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025112402/</guid><description>用一句话区分防抖与节流：防抖是「最后一次说了算」，n 秒内重复触发会重新计时；节流是「按时间节奏执行」，单位时间内只生效一次。</description><pubDate>Sun, 23 Nov 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;防抖节流&quot;&gt;防抖节流&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#防抖节流&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h3 id=&quot;一句话总结&quot;&gt;一句话总结&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#一句话总结&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“防抖（Debounce）是‘最后一次说了算’，而节流（Throttle）是‘按时间节奏执行’。”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;防抖&lt;/strong&gt;：在事件被触发 n 秒后再执行回调，如果在这 n 秒内又被触发，则重新计时。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;节流&lt;/strong&gt;：规定在一个单位时间内，只能触发一次函数。如果这个单位时间内触发多次函数，只有一次生效。&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>面试</category><category>面试</category></item><item><title>this</title><link>https://cjw32.xyz/blog/article/2025112403/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025112403/</guid><description>系统梳理 this 的五条绑定规则：默认、隐式、显式（call/apply/bind）、new 绑定与箭头函数的词法作用域，附优先级顺序和三者对比表。</description><pubDate>Sun, 23 Nov 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;this&quot;&gt;this&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#this&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h3 id=&quot;1-默认绑定-default-binding&quot;&gt;1. 默认绑定 (Default Binding)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-默认绑定-default-binding&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;这是最基础的规则。当函数独立调用，没有带任何修饰符（没有 &lt;code&gt;new&lt;/code&gt;，没有 &lt;code&gt;obj.&lt;/code&gt;，没有 &lt;code&gt;call&lt;/code&gt;）时，应用此规则。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;规则&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;非严格模式&lt;/strong&gt;：&lt;code&gt;this&lt;/code&gt; 指向全局对象（浏览器中是 &lt;code&gt;window&lt;/code&gt;，Node.js 中是 &lt;code&gt;global&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;严格模式 (&lt;code&gt;&apos;use strict&apos;&lt;/code&gt;)&lt;/strong&gt;：&lt;code&gt;this&lt;/code&gt; 指向 &lt;code&gt;undefined&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sayHi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;sayHi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// window (非严格模式) / undefined (严格模式)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;面试陷阱&lt;/strong&gt;：这也是你之前做错的那道题的原因。&lt;code&gt;const say = person.sayName; say();&lt;/code&gt; 这里 &lt;code&gt;say&lt;/code&gt; 是独立调用的，所以 &lt;code&gt;this&lt;/code&gt; 丢了，变成了全局或 undefined。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;2-隐式绑定-implicit-binding&quot;&gt;2. 隐式绑定 (Implicit Binding)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-隐式绑定-implicit-binding&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;当函数作为&lt;strong&gt;对象的方法&lt;/strong&gt;被调用时，&lt;code&gt;this&lt;/code&gt; 指向那个对象。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;规则&lt;/strong&gt;：&lt;code&gt;this&lt;/code&gt; 指向调用链中&lt;strong&gt;最后一层&lt;/strong&gt;的对象。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;JavaScript&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; user &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Alice&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;greet&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;greet&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Alice -&gt; user 调用了 greet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;隐式丢失（常见坑）：&lt;/p&gt;
&lt;p&gt;如果把对象的方法赋值给一个变量，或者作为参数传入回调函数，隐式绑定会丢失，退化为默认绑定。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;JavaScript&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; fn &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;greet&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;fn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// undefined (因为变成了独立调用)&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;greet&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// undefined (回调函数通常也是独立调用的)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;h3 id=&quot;3-显式绑定-explicit-binding-call-apply-bind&quot;&gt;3. 显式绑定 (Explicit Binding): call, apply, bind&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#3-显式绑定-explicit-binding-call-apply-bind&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;这三个方法都在 &lt;code&gt;Function.prototype&lt;/code&gt; 上，允许你&lt;strong&gt;强制指定&lt;/strong&gt;函数的 &lt;code&gt;this&lt;/code&gt; 指向。&lt;/p&gt;
&lt;h4 id=&quot;a-call-和-apply&quot;&gt;A. &lt;code&gt;call&lt;/code&gt; 和 &lt;code&gt;apply&lt;/code&gt;&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#a-call-和-apply&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;这两个方法非常相似，都会&lt;strong&gt;立即执行&lt;/strong&gt;函数。区别仅在于传递参数的方式。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;call(thisArg, arg1, arg2, ...)&lt;/code&gt;&lt;/strong&gt;：参数是一个接一个传的。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;apply(thisArg, [argsArray])&lt;/code&gt;&lt;/strong&gt;：参数是放在一个数组里传的。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;JavaScript&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;introduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;lang&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; hobby&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; likes &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;lang&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; and &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;hobby&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; p1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Bob&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 使用 call：参数逗号隔开&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;introduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;JS&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Gaming&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;Bob likes JS and Gaming&quot;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 使用 apply：参数放数组里&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;introduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;apply&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;JS&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Gaming&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;Bob likes JS and Gaming&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;记忆口诀&lt;/strong&gt;：&lt;code&gt;a&lt;/code&gt;pply 对应 &lt;code&gt;a&lt;/code&gt;rray（数组），&lt;code&gt;c&lt;/code&gt;all 对应 &lt;code&gt;c&lt;/code&gt;omma（逗号）。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id=&quot;b-bind&quot;&gt;B. &lt;code&gt;bind&lt;/code&gt;&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#b-bind&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;bind&lt;/code&gt; &lt;strong&gt;不会立即执行&lt;/strong&gt;函数，而是&lt;strong&gt;返回一个新的函数&lt;/strong&gt;。这个新函数的 &lt;code&gt;this&lt;/code&gt; 被永久地“锁死”（硬绑定）到了传入的第一个参数上。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;场景&lt;/strong&gt;：常用于 React 类组件的事件处理，或者解决 &lt;code&gt;setTimeout&lt;/code&gt; 中的 &lt;code&gt;this&lt;/code&gt; 丢失问题。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;JavaScript&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; p2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Charlie&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sayName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; boundFn &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sayName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 只是绑定，没执行&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;boundFn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;Charlie&quot;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 即使之后再 call 别人，也改变不了 bind 的结果&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;boundFn&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;call&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Dave&apos;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 依然是 &quot;Charlie&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;h3 id=&quot;4-new-绑定-new-binding&quot;&gt;4. &lt;code&gt;new&lt;/code&gt; 绑定 (New Binding)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#4-new-绑定-new-binding&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;当使用 &lt;code&gt;new&lt;/code&gt; 关键字调用构造函数时，会发生以下步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;创建一个全新的空对象。&lt;/li&gt;
&lt;li&gt;将这个对象的 &lt;code&gt;[[Prototype]]&lt;/code&gt; 链接到构造函数的 &lt;code&gt;prototype&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;将函数内部的 &lt;code&gt;this&lt;/code&gt; 指向这个新对象&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;如果函数没有返回其他对象，则自动返回这个新对象。&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;JavaScript&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// this 指向新创建的实例&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; tom &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Tom&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;tom&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;Tom&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;h3 id=&quot;5-特殊规则箭头函数-arrow-function&quot;&gt;5. 特殊规则：箭头函数 (Arrow Function)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#5-特殊规则箭头函数-arrow-function&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;箭头函数&lt;strong&gt;没有自己的 &lt;code&gt;this&lt;/code&gt;&lt;/strong&gt;。它不遵循以上 4 条规则。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;规则&lt;/strong&gt;：箭头函数的 &lt;code&gt;this&lt;/code&gt; 完全取决于&lt;strong&gt;定义时&lt;/strong&gt;（也就是写代码时）所处的&lt;strong&gt;外层（词法）作用域&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;特点&lt;/strong&gt;：
&lt;ul&gt;
&lt;li&gt;一旦确定，无法被 &lt;code&gt;call&lt;/code&gt;、&lt;code&gt;apply&lt;/code&gt;、&lt;code&gt;bind&lt;/code&gt; 修改。&lt;/li&gt;
&lt;li&gt;常用于解决回调函数中 &lt;code&gt;this&lt;/code&gt; 指向错误的问题。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;JavaScript&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; obj &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;Arrow&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 定义时，外层作用域是全局（对象字面量不构成作用域）&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;say&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 普通函数创造了一个作用域&lt;/span&gt;
  &lt;span class=&quot;token function-variable function&quot;&gt;waitAndSay&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 这里的箭头函数定义在 waitAndSay 内部&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 所以它继承 waitAndSay 的 this (即 obj)&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

obj&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;say&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// undefined (指向全局)&lt;/span&gt;
obj&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;waitAndSay&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;Arrow&quot; (正确继承了 obj)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;h3 id=&quot;总结与优先级-priority&quot;&gt;总结与优先级 (Priority)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#总结与优先级-priority&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;如果同一个调用位置存在多种规则，谁说了算？优先级如下（从高到低）：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;new&lt;/code&gt; 绑定&lt;/strong&gt; (最高)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;显式绑定&lt;/strong&gt; (&lt;code&gt;call&lt;/code&gt;, &lt;code&gt;apply&lt;/code&gt;, &lt;code&gt;bind&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;隐式绑定&lt;/strong&gt; (&lt;code&gt;obj.func()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;默认绑定&lt;/strong&gt; (&lt;code&gt;func()&lt;/code&gt;) (最低)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;箭头函数&lt;/strong&gt;是一个特例，它忽略所有绑定规则（除了 &lt;code&gt;new&lt;/code&gt;，但箭头函数不能被 &lt;code&gt;new&lt;/code&gt;），只认词法作用域。&lt;/p&gt;
&lt;h3 id=&quot;一张表复习-call-apply-bind&quot;&gt;一张表复习 &lt;code&gt;call&lt;/code&gt;, &lt;code&gt;apply&lt;/code&gt;, &lt;code&gt;bind&lt;/code&gt;&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#一张表复习-call-apply-bind&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;




























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;特性&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;call&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;apply&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;bind&lt;/strong&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;立即执行?&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;td&gt;&lt;strong&gt;否&lt;/strong&gt; (返回新函数)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;参数形式&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;arg1, arg2, ...&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;[arg1, arg2, ...]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;arg1, arg2, ...&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;用途&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;借用方法、改变上下文&lt;/td&gt;&lt;td&gt;处理数组参数 (如 &lt;code&gt;Math.max&lt;/code&gt;)&lt;/td&gt;&lt;td&gt;预设参数、回调函数绑定&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;</content:encoded><category>面试</category><category>面试</category></item><item><title>原型链</title><link>https://cjw32.xyz/blog/article/2025112001/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025112001/</guid><description>简述原型链作为 JS 继承的核心机制：函数有 prototype、对象有 __proto__，实例沿原型链逐级向上查找属性直到 null，并说明实例、构造函数与原型三者的指向关系。</description><pubDate>Wed, 19 Nov 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;原型链&quot;&gt;原型链&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#原型链&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;原型链是 JavaScript 实现继承（Inheritance）的核心机制。有两个核心的概念：prototype（原型对象）,_ &lt;em&gt;proto&lt;/em&gt;_&lt;/p&gt;
&lt;p&gt;_ _proto__作为链条链接着prototype，每个函数都有prototype，prototype是给子类提供共享属性的。由于prototype是一个对象。每个对象默认有着一个proto的属性，指向这个对象的构造函数的prototype（即实例.proto === 构造函数.prototype），以此形成链条，当这个实例的prototype中没有所需的属性时候就通过proto向父级的prototype寻找知道找到null（即Object.prototype.proto）&lt;/p&gt;</content:encoded><category>面试</category><category>面试</category></item><item><title>闭包</title><link>https://cjw32.xyz/blog/article/2025112002/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025112002/</guid><description>从定义、词法作用域原理讲到闭包的三大应用（私有变量、柯里化、防抖节流），并解析循环中 var/let 的经典面试题，最后给出缺点、内存管理建议与高分回答模板。</description><pubDate>Wed, 19 Nov 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;闭包&quot;&gt;闭包&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#闭包&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h2 id=&quot;一-什么是闭包&quot;&gt;一、 什么是闭包？&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#一-什么是闭包&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;1-通俗定义一句话回答&quot;&gt;1. 通俗定义（一句话回答）&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-通俗定义一句话回答&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;闭包就是一个函数以及它所引用的周边环境（词法环境）的组合。&lt;/strong&gt; 简单来说，就是&lt;strong&gt;内部函数可以访问外部函数的变量&lt;/strong&gt;，即使外部函数已经执行完毕。&lt;/p&gt;
&lt;h3 id=&quot;2-官方学术定义-mdn&quot;&gt;2. 官方/学术定义 (MDN)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-官方学术定义-mdn&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;二-核心原理&quot;&gt;二、 核心原理&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#二-核心原理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;闭包的形成基于 JavaScript 的 &lt;strong&gt;词法作用域 (Lexical Scoping)&lt;/strong&gt; 规则：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;函数的作用域在定义时决定，而不是调用时。&lt;/li&gt;
&lt;li&gt;内部函数持有对外部函数作用域的引用（Scope Chain）。&lt;/li&gt;
&lt;li&gt;当外部函数执行完毕后，因为内部函数还持有引用，所以外部函数的变量对象无法被垃圾回收机制（GC）回收，从而形成了闭包。&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;function createCounter() {
  let count = 0; // 私有变量
  return function() {
    count++;
    console.log(count);
  }
}

const counter = createCounter();
counter(); // 1
counter(); // 2
// count 变量依然存在内存中，但外部无法直接访问
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;三-闭包的常见应用场景&quot;&gt;三、 闭包的常见应用场景&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#三-闭包的常见应用场景&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;面试时列举 2-3 个实际场景非常加分：&lt;/p&gt;
&lt;h3 id=&quot;1-数据私有化--模拟私有变量-最常用&quot;&gt;1. 数据私有化 / 模拟私有变量 (最常用)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-数据私有化--模拟私有变量-最常用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在 ES6 类出现之前，闭包是实现模块化和私有变量的主要方式。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;function User(name) {
  let _name = name; // 私有变量
  
  return {
    getName: function() {
      return _name;
    },
    setName: function(newName) {
      _name = newName;
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;2-柯里化-currying&quot;&gt;2. 柯里化 (Currying)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-柯里化-currying&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;将多参数函数转换成一系列单参数函数。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;function makeAdder(x) {
  return function(y) {
    return x + y;
  };
}
const add5 = makeAdder(5);
console.log(add5(2)); // 7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;3-防抖与节流-debounce--throttle&quot;&gt;3. 防抖与节流 (Debounce &amp;#x26; Throttle)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#3-防抖与节流-debounce--throttle&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;工具函数中大量使用闭包来保存定时器状态 &lt;code&gt;timer&lt;/code&gt;。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;function debounce(fn, delay) {
  let timer = null; // 闭包变量，保存定时器状态
  return function(...args) {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() =&gt; fn.apply(this, args), delay);
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;四-经典面试题循环中的闭包&quot;&gt;四、 经典面试题：循环中的闭包&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#四-经典面试题循环中的闭包&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;这是考察闭包最经典的题目，考察 &lt;code&gt;var&lt;/code&gt; 和 &lt;code&gt;let&lt;/code&gt; 的区别。&lt;/p&gt;
&lt;h3 id=&quot;题目&quot;&gt;题目&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#题目&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;for (var i = 1; i &amp;#x3C;= 3; i++) {
  setTimeout(function() {
    console.log(i);
  }, 1000);
}
// 输出结果是什么？
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;答案&quot;&gt;答案&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#答案&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;结果&lt;/strong&gt;：输出三次 &lt;code&gt;4&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;原因&lt;/strong&gt;：&lt;code&gt;var&lt;/code&gt; 声明的变量是函数作用域（这里变成了全局），循环结束后 &lt;code&gt;i&lt;/code&gt; 变成了 4。&lt;code&gt;setTimeout&lt;/code&gt; 是异步执行的，当它执行时，去读取 &lt;code&gt;i&lt;/code&gt; 的值，此时 &lt;code&gt;i&lt;/code&gt; 已经是 4 了。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;怎么修改为输出-1-2-3&quot;&gt;怎么修改为输出 1, 2, 3？&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#怎么修改为输出-1-2-3&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;方法 1：使用 let (推荐)&lt;/strong&gt; &lt;code&gt;let&lt;/code&gt; 有块级作用域，每次循环都会创建一个新的绑定。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;for (let i = 1; i &amp;#x3C;= 3; i++) {
  setTimeout(function() { console.log(i); }, 1000);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;方法 2：使用立即执行函数 (IIFE) 构造闭包&lt;/strong&gt; 通过传参，将当前的 &lt;code&gt;i&lt;/code&gt; 保存为局部变量 &lt;code&gt;j&lt;/code&gt;。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;for (var i = 1; i &amp;#x3C;= 3; i++) {
  (function(j) {
    setTimeout(function() { console.log(j); }, 1000);
  })(i);
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;五-闭包的缺点与内存泄漏&quot;&gt;五、 闭包的缺点与内存泄漏&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#五-闭包的缺点与内存泄漏&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;缺点&lt;/strong&gt;：闭包会让变量始终保存在内存中，不会被垃圾回收。如果不当使用，会导致内存消耗过大。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;内存泄漏误区&lt;/strong&gt;：闭包本身&lt;strong&gt;不是&lt;/strong&gt;内存泄漏（它是 JS 的特性）。但如果闭包持有的大量对象不再需要使用，却一直不释放，就会导致内存泄漏。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;解决方法&lt;/strong&gt;：将不再使用的闭包引用置为 &lt;code&gt;null&lt;/code&gt;。&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;let counter = createCounter();
counter();
counter = null; // 解除引用，允许 GC 回收
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;六-面试高分回答策略-cheat-sheet&quot;&gt;六、 面试高分回答策略 (Cheat Sheet)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#六-面试高分回答策略-cheat-sheet&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;如果面试官问：“讲讲闭包”，你可以这样回答：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;下定义&lt;/strong&gt;：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“闭包是指有权访问另一个函数作用域中变量的函数。简单来说，就是内部函数引用了外部函数的变量，导致这些变量无法被垃圾回收。”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;讲原理&lt;/strong&gt;：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“它的核心原理是基于 JavaScript 的词法作用域链。内部函数在定义时就记住了它所处的环境。”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;举例子&lt;/strong&gt;：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“在实际开发中，闭包主要有两个用途： 一是&lt;strong&gt;保护变量&lt;/strong&gt;，比如实现数据私有化、模块化； 二是&lt;strong&gt;保存变量&lt;/strong&gt;，比如在防抖节流函数中保存 timer，或者在柯里化函数中保存预设参数。”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;提注意&lt;/strong&gt;：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“不过使用闭包要注意内存管理。因为它会阻止垃圾回收，滥用可能导致内存占用过高。在不再使用时，我会手动将引用置为 null。”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;</content:encoded><category>面试</category><category>面试</category></item><item><title>事件循环，宏任务，微任务</title><link>https://cjw32.xyz/blog/article/2025112003/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025112003/</guid><description>用两道输出顺序题讲清事件循环：同步代码与宏任务、微任务的区别，微任务优先于宏任务，附完整执行流程和常见宏微任务清单。</description><pubDate>Wed, 19 Nov 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;事件循环宏任务微任务&quot;&gt;事件循环，宏任务，微任务&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#事件循环宏任务微任务&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;问题&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;1&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;2&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;3&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;4&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;5&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;打印顺序是1,3,5,4,2。在这段代码中1,3,5都是同步任务，所以从上到下立即执行。setTimeout中的是宏任务，.then中的是微任务。优先级是：微任务＞宏任务。常见的微任务有&lt;code&gt;Promise.then&lt;/code&gt; / &lt;code&gt;.catch&lt;/code&gt; / &lt;code&gt;.finally&lt;/code&gt;，process.nextTick（node环境），常见的宏任务有script(整体代码，这是第一个宏任务)，&lt;code&gt;setTimeout&lt;/code&gt; / &lt;code&gt;setInterval&lt;/code&gt; (定时器)，DOM 事件回调 (如点击事件)，&lt;code&gt;ajax&lt;/code&gt; 请求回调。&lt;/p&gt;
&lt;p&gt;所以事件循环的顺序是：&lt;strong&gt;同步代码&lt;/strong&gt;先执行（这属于当前的宏任务）-&gt;同步代码执行完，&lt;strong&gt;立刻&lt;/strong&gt;清空&lt;strong&gt;微任务队列&lt;/strong&gt;（所有加塞的 &lt;code&gt;Promise.then&lt;/code&gt;）-&gt;渲染页面（如果有需要）-&gt;取出&lt;strong&gt;下一个宏任务&lt;/strong&gt;（比如 &lt;code&gt;setTimeout&lt;/code&gt;）-&gt;重复第二步&lt;/p&gt;
&lt;p&gt;小测验：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;1&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 同步&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;2&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 宏任务&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;async1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;3&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 同步？还是异步？&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;async2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;4&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 这里的代码相当于在 .then 里&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;async2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;5&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;async1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;6&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;7&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;8&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;答案是：1, 3, 5, 6, 8, 4, 7, 2， 注意await async2();是同步代码&lt;/p&gt;</content:encoded><category>面试</category><category>面试</category></item><item><title>组件间传值</title><link>https://cjw32.xyz/blog/article/2025111701/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025111701/</guid><description>用完整代码示例演示 Vue 组件通信的三种方式：props 父传子、defineEmits 子传父（含事件名与参数接收），以及 defineExpose 配合 ref 暴露子组件方法属性。</description><pubDate>Sun, 16 Nov 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;组件间传值&quot;&gt;组件间传值&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#组件间传值&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h4 id=&quot;父传子&quot;&gt;父传子&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#父传子&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;父组件：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;template&gt;
  &amp;#x3C;div style=&quot;background-color: lightcoral;&quot;&gt;
    我是父组件
    &amp;#x3C;!-- 将要传给子组件的值重新命个名加上：即可 --&gt;
    &amp;#x3C;Children :name = &quot;fatherName&quot;&gt;&amp;#x3C;/Children&gt;
  &amp;#x3C;/div&gt;

&amp;#x3C;/template&gt;

&amp;#x3C;script setup&gt;
import Children from &apos;./components/children.vue&apos;
const fatherName = &apos;Cain&apos;
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;子组件：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;template&gt;
  我是子组件
  父亲的名字是：{{ props.name }}
&amp;#x3C;/template&gt;

&amp;#x3C;script setup&gt;
// 接收父组件传过来的值
const props = defineProps({
  name: {
    type: String,
    default: &apos;默认值&apos;
  }
})
&amp;#x3C;/script&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;子传父&quot;&gt;子传父&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#子传父&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;子组件：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;template&gt;
  我是子组件
  &amp;#x3C;button @click=&quot;send&quot;&gt;发送&amp;#x3C;/button&gt;
&amp;#x3C;/template&gt;

&amp;#x3C;script setup&gt;
// 定义子组件传值
const emit = defineEmits([&apos;update:childrenName&apos;])
const send = () =&gt; {
    // 传值给父组件
  emit(&apos;update:childrenName&apos;, &apos;这里是子组件传过来的值1&apos;, &apos;这里是子组件传过来的值2&apos;)
}
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;父组件：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;template&gt;
  &amp;#x3C;div &gt;
    我是父组件
    &amp;#x3C;!-- 通过事件的方式接收子组件传过来的值 事件名要与子组件中定义的相同--&gt;
     &amp;#x3C;!-- 需要使用一个函数来接收，因为子组件的值是放到参数中的--&gt;
    &amp;#x3C;Children @update:children-name=&quot;getChildrenName&quot;&gt;&amp;#x3C;/Children&gt;
  &amp;#x3C;/div&gt;
&amp;#x3C;/template&gt;

&amp;#x3C;script setup&gt;
import { ref } from &apos;vue&apos;
import Children from &apos;./components/children.vue&apos;
const childrenName = ref(&apos;&apos;)
// 定义接收子组件传值的方法
const getChildrenName = (name1, name2) =&gt; {
  console.log(name1, name2)
}
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;子组件参数暴露&quot;&gt;子组件参数暴露&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#子组件参数暴露&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;子组件：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;template&gt;
  我是子组件
&amp;#x3C;/template&gt;

&amp;#x3C;script setup&gt;
// 使用 defineExpose 向父组件暴露方法或属性
defineExpose({
  send() {
    console.log(&apos;子组件发送消息&apos;)
  },
  name: &apos;子组件名称&apos;
})
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;父组件：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;template&gt;
  &amp;#x3C;div &gt;
    我是父组件
    &amp;#x3C;!-- 使用ref绑定一下子组件的实例 --&gt;
    &amp;#x3C;Children ref=&quot;children&quot;&gt;&amp;#x3C;/Children&gt;
  &amp;#x3C;/div&gt;
&amp;#x3C;/template&gt;

&amp;#x3C;script setup&gt;
import { ref } from &apos;vue&apos;
import Children from &apos;./components/children.vue&apos;
const children = ref(&apos;&apos;)
import { onMounted } from &apos;vue&apos;
onMounted(() =&gt; {
  // 通过ref访问子组件暴露的方法
  children.value?.send()
  console.log(children.value?.name) // 访问子组件暴露的属性
})
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;这样拿到的子组件参数不能直接修改&lt;/p&gt;</content:encoded><category>技术文章</category><category>vue</category></item><item><title>WebSocket</title><link>https://cjw32.xyz/blog/article/2025110401/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025110401/</guid><description>基于 ws 库搭建 WebSocket 服务：从安装与类型声明开始，实现前后端消息互发（服务端 connection/message 监听、客户端 onopen/onmessage），并演示向所有客户端群发消息。</description><pubDate>Mon, 03 Nov 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;websocket&quot;&gt;WebSocket&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#websocket&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;安装&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M5 9H7.31L7.63 6H9.63L9.31 9H11.31L11.63 6H13.63L13.31 9H15V11H13.1L12.9 13H15V15H12.69L12.37 18H10.37L10.69 15H8.69L8.37 18H6.37L6.69 15H5V13H6.9L7.1 11H5V9M9.1 11L8.9 13H10.9L11.1 11M19 6H17V14H19M19 16H17V18H19Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;bash&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i ws//安装WebSocket
&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; i @types/ws -D//安装声明文件
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;前后端互发消息（后端）&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; WebSocketServer &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ws&apos;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 创建一个WebSocket服务器 端口8080&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; wss &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;WebSocketServer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;服务器启动成功！&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 监听客户端连接事件&lt;/span&gt;
wss&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;connection&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;客户端连接成功&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    socket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;message&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;收到客户端消息：&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; message&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        socket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;前后端互发消息（前端）&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ref &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;vue&apos;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; msg &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;hello&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; list &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//发送信息&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;ws&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 引入WebSocket&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ws &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;WebSocket&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;ws://localhost:8080&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 连接成功&lt;/span&gt;
ws&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onopen&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;连接成功&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 接收到消息&lt;/span&gt;
ws&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onmessage&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;msg&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;群发消息（后端，前端不需要修改）&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; WebSocketServer &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;ws&apos;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 创建一个WebSocket服务器 端口8080&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; wss &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;WebSocketServer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token literal-property property&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;服务器启动成功！&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 监听客户端连接事件&lt;/span&gt;
wss&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;connection&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;socket&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;客户端连接成功&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    socket&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;message&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;收到客户端消息：&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; message&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;//群发&lt;/span&gt;
        wss&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;clients&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            client&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;message&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded><category>技术文章</category><category>网络</category></item><item><title>跨域</title><link>https://cjw32.xyz/blog/article/2025110301/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025110301/</guid><description>从同源策略讲起，用判断表说明协议/域名/端口任一不同即跨域，再逐一给出 CORS、Vite 代理、Nginx 反向代理、JSONP 与 WebSocket 五种方案及代码示例，最后附按场景选择的最佳实践。</description><pubDate>Sun, 02 Nov 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;跨域&quot;&gt;跨域&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#跨域&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;解决跨域问题有四种方案：jsonp（需要前后端协作，不安全），打包工具（纯前端，只能在开发阶段解决跨域），设置相应头（纯后端），nginx&lt;/p&gt;
&lt;h2 id=&quot;1-什么是跨域&quot;&gt;1. 什么是跨域？&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-什么是跨域&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;跨域本质上是浏览器为了安全而引入的一种 &lt;strong&gt;同源策略 (Same-Origin Policy)&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;当一个请求 URL 的 &lt;strong&gt;协议 (Protocol)&lt;/strong&gt;、&lt;strong&gt;域名 (Domain)&lt;/strong&gt;、&lt;strong&gt;端口 (Port)&lt;/strong&gt; 三者中，只要有一个与当前页面的 URL 不同，就会产生跨域。&lt;/p&gt;
&lt;h3 id=&quot;11-同源策略判断表&quot;&gt;1.1 同源策略判断表&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#11-同源策略判断表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;假设当前页面地址为: &lt;code&gt;http://www.example.com/index.html&lt;/code&gt;&lt;/p&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;


































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;请求地址&lt;/th&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;http://www.example.com/api/data&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;成功&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;同源&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;https://www.example.com/api/data&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;跨域&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;协议不同 (http vs https)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;http://api.example.com/data&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;跨域&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;域名不同 (www vs api)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;http://www.example.com:8080/data&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;跨域&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;端口不同 (80 vs 8080)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;http://www.google.com/api&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;跨域&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;域名完全不同&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;h3 id=&quot;12-为什么要有同源策略&quot;&gt;1.2 为什么要有同源策略？&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#12-为什么要有同源策略&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;主要是为了&lt;strong&gt;安全&lt;/strong&gt;。如果没有同源策略，恶意网站可能会窃取你在其他网站（如银行）的敏感数据（Cookies、LocalStorage），或者利用你的登录状态伪造请求（CSRF 攻击）。&lt;/p&gt;
&lt;h2 id=&quot;2-常见的解决方案&quot;&gt;2. 常见的解决方案&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-常见的解决方案&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;解决跨域的核心思路通常有两种：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;后端配合&lt;/strong&gt;：允许特定的源访问（CORS）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;绕过浏览器&lt;/strong&gt;：通过服务器代理转发请求（因为服务器之间没有同源策略）。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;以下是 5 种最常用的解决方案：&lt;/p&gt;
&lt;h3 id=&quot;方案一cors-cross-origin-resource-sharing-最推荐&quot;&gt;方案一：CORS (Cross-Origin Resource Sharing) 【最推荐】&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#方案一cors-cross-origin-resource-sharing-最推荐&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;这是目前最标准、最通用的解决方案。它需要&lt;strong&gt;后端&lt;/strong&gt;在响应头中添加特定的字段，告诉浏览器：“我允许这个源访问我”。&lt;/p&gt;
&lt;h4 id=&quot;核心响应头&quot;&gt;核心响应头：&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#核心响应头&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt;: 允许访问的源（例如 &lt;code&gt;http://localhost:3000&lt;/code&gt; 或 &lt;code&gt;*&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Access-Control-Allow-Methods&lt;/code&gt;: 允许的请求方法（GET, POST, PUT, DELETE 等）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Access-Control-Allow-Headers&lt;/code&gt;: 允许的自定义 Header。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;代码示例-nodejsexpress&quot;&gt;代码示例 (Node.js/Express):&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#代码示例-nodejsexpress&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;const express = require(&apos;express&apos;);
const app = express();

// 方法 1: 手动设置 Header
app.use((req, res, next) =&gt; {
    // 允许所有来源访问，生产环境建议指定具体域名
    res.header(&apos;Access-Control-Allow-Origin&apos;, &apos;*&apos;); 
    res.header(&apos;Access-Control-Allow-Headers&apos;, &apos;Content-Type, Authorization&apos;);
    res.header(&apos;Access-Control-Allow-Methods&apos;, &apos;PUT, POST, GET, DELETE, OPTIONS&apos;);
    next();
});

// 方法 2: 使用 cors 中间件 (推荐)
const cors = require(&apos;cors&apos;);
app.use(cors()); 

app.get(&apos;/api/data&apos;, (req, res) =&gt; {
    res.json({ msg: &apos;这是跨域数据&apos; });
});

app.listen(3000);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;方案二开发环境代理-proxy-前端开发常用&quot;&gt;方案二：开发环境代理 (Proxy) 【前端开发常用】&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#方案二开发环境代理-proxy-前端开发常用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在前端开发阶段（使用 Vue, React, Webpack, Vite 等），由于本地服务器（如 localhost:3000）和后端接口（如 &lt;a href=&quot;https://www.google.com/search?q=api.server.com%EF%BC%89%E4%B8%8D%E5%90%8C%E6%BA%90%EF%BC%8C%E5%B8%B8%E4%BD%BF%E7%94%A8%E6%9C%AC%E5%9C%B0%E4%BB%A3%E7%90%86%E8%A7%A3%E5%86%B3%E3%80%82&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;https://www.google.com/search?q=api.server.com）不同源，常使用本地代理解决。&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原理&lt;/strong&gt;： 浏览器 -&gt; 本地开发服务器 (同源) -&gt; 转发请求到后端服务器。 &lt;em&gt;服务器与服务器之间通信不受同源策略限制。&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&quot;代码示例-vite-viteconfigjs&quot;&gt;代码示例 (Vite &lt;code&gt;vite.config.js&lt;/code&gt;):&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#代码示例-vite-viteconfigjs&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;export default defineConfig({
  server: {
    proxy: {
      // 当请求路径以 /api 开头时
      &apos;/api&apos;: {
        target: &apos;[http://backend-api.com](http://backend-api.com)&apos;, // 目标后端地址
        changeOrigin: true, // 修改请求头的 Host 为目标地址
        rewrite: (path) =&gt; path.replace(/^\/api/, &apos;&apos;) // 去掉 /api 前缀
      }
    }
  }
})
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;注意：这只在开发环境有效，生产环境通常需要 Nginx 配合。&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;方案三nginx-反向代理-生产环境常用&quot;&gt;方案三：Nginx 反向代理 【生产环境常用】&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#方案三nginx-反向代理-生产环境常用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在项目上线时，通常使用 Nginx 作为反向代理服务器。前端请求 Nginx，Nginx 再转发给后端，从而实现“同源”的效果。&lt;/p&gt;
&lt;h4 id=&quot;nginx-配置示例-nginxconf&quot;&gt;Nginx 配置示例 (&lt;code&gt;nginx.conf&lt;/code&gt;):&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#nginx-配置示例-nginxconf&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;server {
    listen 80;
    server_name [www.example.com](https://www.example.com);

    # 前端静态资源
    location / {
        root /usr/share/nginx/html;
        index index.html;
    }

    # 接口代理
    location /api/ {
        proxy_pass http://backend-server:8080/; # 转发到真实后端
        
        # 也可以在这里配置 CORS 头
        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods &apos;GET, POST, OPTIONS&apos;;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;方案四jsonp-json-with-padding-老旧方案&quot;&gt;方案四：JSONP (JSON with Padding) 【老旧方案】&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#方案四jsonp-json-with-padding-老旧方案&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;JSONP 是利用 &lt;code&gt;&amp;#x3C;script&gt;&lt;/code&gt; 标签不受同源策略限制的特性来实现跨域的。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;缺点&lt;/strong&gt;：&lt;strong&gt;只支持 GET 请求&lt;/strong&gt;，不安全（容易受 XSS 攻击），现在已经很少使用，主要用于兼容极老的系统。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;前端实现原理&quot;&gt;前端实现原理：&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#前端实现原理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;script&gt;
    function handleResponse(data) {
        console.log(&apos;获取到的数据:&apos;, data);
    }
&amp;#x3C;/script&gt;
&amp;#x3C;!-- 请求后端，并告诉后端回调函数名是 handleResponse --&gt;
&amp;#x3C;script src=&quot;https://cjw32.xyz/blog/article/2025110301/[http://api.example.com/data?callback=handleResponse](http://api.example.com/data?callback=handleResponse)&quot;&gt;&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;方案五websocket&quot;&gt;方案五：Websocket&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#方案五websocket&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Websocket 协议本身不受同源策略限制。如果你使用 Socket.io 等库进行通信，天然支持跨域。&lt;/p&gt;
&lt;h2 id=&quot;3-总结与建议&quot;&gt;3. 总结与建议&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#3-总结与建议&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;场景&lt;/th&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;strong&gt;日常开发调试&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Proxy (代理)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;配置简单，无侵入，仅对开发环境有效&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;生产环境 API&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;CORS&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;标准做法，后端控制权限，支持所有 HTTP 方法&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;项目部署&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;Nginx 反向代理&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;性能高，架构清晰，隐藏真实后端地址&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;老旧系统兼容&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;JSONP&lt;/td&gt;&lt;td&gt;仅限 GET 请求，不推荐新项目使用&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;最佳实践流程：&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;开发时&lt;/strong&gt;：前端配置 &lt;code&gt;proxy&lt;/code&gt; 解决本地开发跨域。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;上线时&lt;/strong&gt;：后端配置 &lt;code&gt;CORS&lt;/code&gt; 允许特定的线上域名访问，或者运维配置 &lt;code&gt;Nginx&lt;/code&gt; 反向代理将前端和后端聚合在同一个域下。&lt;/li&gt;
&lt;/ol&gt;</content:encoded><category>技术文章</category><category>面试</category></item><item><title>promise</title><link>https://cjw32.xyz/blog/article/2025102801/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025102801/</guid><description>系统整理 Promise：三种状态与不可逆的状态流转、then/catch/finally 实例方法，以及 all、allSettled、race、any 四个并发静态方法的机制对比表和完整实践示例。</description><pubDate>Mon, 27 Oct 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;promise&quot;&gt;promise&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#promise&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Promise 是 JavaScript 异步编程的核心解决方案，它代表了一个异步操作的最终完成（或失败）及其结果值。&lt;/p&gt;
&lt;h2 id=&quot;1-promise-的核心概念与状态&quot;&gt;1. Promise 的核心概念与状态&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-promise-的核心概念与状态&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;11-三种状态-states&quot;&gt;1.1 三种状态 (States)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#11-三种状态-states&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;一个 Promise 必然处于以下三种状态之一，且状态的改变是&lt;strong&gt;不可逆&lt;/strong&gt;的。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Pending (待定)&lt;/strong&gt;: 初始状态。既没有被兑现（fulfilled），也没有被拒绝（rejected）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fulfilled (已兑现/已成功)&lt;/strong&gt;: 意味着操作成功完成。此时会有一个 result (值)。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rejected (已拒绝/已失败)&lt;/strong&gt;: 意味着操作失败。此时会有一个 error (通常是一个 Error 对象)。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;12-状态转化-state-transitions&quot;&gt;1.2 状态转化 (State Transitions)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#12-状态转化-state-transitions&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Promise 的状态流转只有两个方向，一旦发生，状态就&lt;strong&gt;固定 (Settled)&lt;/strong&gt; 了，不会再变：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pending -&gt; Fulfilled&lt;/strong&gt;: 调用 &lt;code&gt;resolve(value)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pending -&gt; Rejected&lt;/strong&gt;: 调用 &lt;code&gt;reject(reason)&lt;/code&gt; 或执行器函数内抛出异常。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;13-基本语法&quot;&gt;1.3 基本语法&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#13-基本语法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; myPromise &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 这是一个 &quot;Executor&quot; (执行器) 函数，会立即执行&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; success &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;success&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 将状态从 Pending 改为 Fulfilled&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;操作成功！&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 将状态从 Pending 改为 Rejected&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;操作失败...&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;2-实例方法-instance-methods&quot;&gt;2. 实例方法 (Instance Methods)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-实例方法-instance-methods&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;创建 Promise 后，我们通过以下方法处理结果：&lt;/p&gt;
&lt;h3 id=&quot;21-thenonfulfilled-onrejected&quot;&gt;2.1 &lt;code&gt;.then(onFulfilled, onRejected)&lt;/code&gt;&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#21-thenonfulfilled-onrejected&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;接收两个函数作为参数。&lt;/li&gt;
&lt;li&gt;第一个参数在 Promise 成功时执行。&lt;/li&gt;
&lt;li&gt;第二个参数在 Promise 失败时执行（可选，一般常用 &lt;code&gt;.catch&lt;/code&gt; 代替）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;链式调用&lt;/strong&gt;: &lt;code&gt;.then&lt;/code&gt; 返回一个新的 Promise。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;22-catchonrejected&quot;&gt;2.2 &lt;code&gt;.catch(onRejected)&lt;/code&gt;&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#22-catchonrejected&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;专门用于捕获错误（Rejected 状态）。&lt;/li&gt;
&lt;li&gt;等同于 &lt;code&gt;.then(null, onRejected)&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;具有“冒泡”性质，可以捕获前面链中任何一个步骤抛出的错误。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;23-finallyonfinally&quot;&gt;2.3 &lt;code&gt;.finally(onFinally)&lt;/code&gt;&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#23-finallyonfinally&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;无论 Promise 是成功还是失败，都会执行。&lt;/li&gt;
&lt;li&gt;通常用于清理工作（如关闭加载动画、关闭数据库连接）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;3-静态方法-static-methods---并发与调度&quot;&gt;3. 静态方法 (Static Methods) - 并发与调度&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#3-静态方法-static-methods---并发与调度&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;这是你提到的类似于 &lt;code&gt;Promise.all&lt;/code&gt; 的方法集合。它们用于处理多个 Promise 的组合情况。&lt;/p&gt;
&lt;h3 id=&quot;31-promiseallp1-p2--全有或全无&quot;&gt;3.1 &lt;code&gt;Promise.all([p1, p2, ...])&lt;/code&gt; (全有或全无)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#31-promiseallp1-p2--全有或全无&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;机制&lt;/strong&gt;: 接收一个 Promise 数组（或可迭代对象）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;成功&lt;/strong&gt;: 只有当&lt;strong&gt;所有&lt;/strong&gt; Promise 都成功时，才返回成功，结果是结果数组。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;失败&lt;/strong&gt;: 只要有&lt;strong&gt;任意一个&lt;/strong&gt; Promise 失败，立即返回失败（短路效应），错误信息是那个失败的 Promise 的错误信息。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; p1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; p2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; p3 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;foo&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;p1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; p2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; p3&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;values&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [3, 42, &quot;foo&quot;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;32-promiseallsettledp1-p2--无论死活都要结果&quot;&gt;3.2 &lt;code&gt;Promise.allSettled([p1, p2, ...])&lt;/code&gt; (无论死活，都要结果)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#32-promiseallsettledp1-p2--无论死活都要结果&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;机制&lt;/strong&gt;: 等待&lt;strong&gt;所有&lt;/strong&gt; Promise 完成，无论它们是成功还是失败。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;结果&lt;/strong&gt;: 返回一个对象数组，每个对象包含 &lt;code&gt;status&lt;/code&gt; (&apos;fulfilled&apos; 或 &apos;rejected&apos;) 和对应的 &lt;code&gt;value&lt;/code&gt; 或 &lt;code&gt;reason&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;适用场景&lt;/strong&gt;: 并发请求，不关心其中某些是否失败，想拿到所有结果时。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; p1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Success&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; p2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;Fail&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;allSettled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;p1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; p2&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// results: &lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// [&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//   { status: &apos;fulfilled&apos;, value: &apos;Success&apos; },&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//   { status: &apos;rejected&apos;, reason: &apos;Fail&apos; }&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// ]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;33-promiseracep1-p2--赛跑谁快谁赢&quot;&gt;3.3 &lt;code&gt;Promise.race([p1, p2, ...])&lt;/code&gt; (赛跑，谁快谁赢)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#33-promiseracep1-p2--赛跑谁快谁赢&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;机制&lt;/strong&gt;: 哪个 Promise &lt;strong&gt;最先&lt;/strong&gt;解决（无论是成功还是失败），&lt;code&gt;Promise.race&lt;/code&gt; 就返回那个结果。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;适用场景&lt;/strong&gt;: 设置请求超时（网络请求 vs 设定时间的 Reject）。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pSlow &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;慢&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pFast &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;快&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;race&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;pSlow&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pFast&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;快&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;34-promiseanyp1-p2--求生欲只要一个成功&quot;&gt;3.4 &lt;code&gt;Promise.any([p1, p2, ...])&lt;/code&gt; (求生欲，只要一个成功)&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#34-promiseanyp1-p2--求生欲只要一个成功&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;机制&lt;/strong&gt;: 等待直到有&lt;strong&gt;任意一个&lt;/strong&gt; Promise 成功。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;成功&lt;/strong&gt;: 返回第一个成功的 Promise 的值。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;失败&lt;/strong&gt;: 只有当&lt;strong&gt;所有&lt;/strong&gt; Promise 都失败时，才返回失败（AggregateError）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;区别&lt;/strong&gt;: 与 &lt;code&gt;race&lt;/code&gt; 不同，&lt;code&gt;any&lt;/code&gt; 会忽略失败的 Promise，直到遇到成功的。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pErr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;错误&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pSlow &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;慢但成功&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; pFast &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;快但成功&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;pErr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pSlow&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pFast&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;value&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// &quot;快但成功&quot; (忽略了 pErr)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;35-辅助方法&quot;&gt;3.5 辅助方法&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#35-辅助方法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Promise.resolve(value)&lt;/code&gt;&lt;/strong&gt;: 快速创建一个状态为 Fulfilled 的 Promise。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;Promise.reject(reason)&lt;/code&gt;&lt;/strong&gt;: 快速创建一个状态为 Rejected 的 Promise。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;4-总结对比表&quot;&gt;4. 总结对比表&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#4-总结对比表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;


































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;方法&lt;/th&gt;&lt;th&gt;描述&lt;/th&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;strong&gt;Promise.all&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;并行执行，且必须全部成功&lt;/td&gt;&lt;td&gt;所有都成功&lt;/td&gt;&lt;td&gt;&lt;strong&gt;任意一个&lt;/strong&gt;失败 (立即返回)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Promise.allSettled&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;并行执行，获取所有结果&lt;/td&gt;&lt;td&gt;总是成功 (等待所有完成)&lt;/td&gt;&lt;td&gt;不会失败 (除非迭代器本身出错)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Promise.race&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;赛跑，以最快的为准&lt;/td&gt;&lt;td&gt;第一个 Settled 的是成功&lt;/td&gt;&lt;td&gt;第一个 Settled 的是失败&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Promise.any&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;只要有一个成功即可&lt;/td&gt;&lt;td&gt;&lt;strong&gt;任意一个&lt;/strong&gt;成功&lt;/td&gt;&lt;td&gt;所有都失败&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;h2 id=&quot;5-最佳实践代码示例&quot;&gt;5. 最佳实践代码示例&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#5-最佳实践代码示例&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;span&gt;27&lt;/span&gt;&lt;span&gt;28&lt;/span&gt;&lt;span&gt;29&lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;span&gt;31&lt;/span&gt;&lt;span&gt;32&lt;/span&gt;&lt;span&gt;33&lt;/span&gt;&lt;span&gt;34&lt;/span&gt;&lt;span&gt;35&lt;/span&gt;&lt;span&gt;36&lt;/span&gt;&lt;span&gt;37&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 模拟两个异步任务&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;fetchUser&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;用户数据&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;fetchPosts&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;resolve&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;文章数据&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;fetchError&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Promise&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;_&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;reject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;连接超时&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;--- 开始 Promise.all 演示 ---&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 只有两个都成功才会打印&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;user&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; posts&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fetchUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchPosts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Promise.all 结果: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;user&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;posts&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Promise.all 出错:&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;\n--- 开始 Promise.allSettled 演示 ---&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 即使包含 fetchError，也会返回所有结果&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; results &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;allSettled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fetchUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    results&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;status &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;fulfilled&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;任务 &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;index&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; 成功: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;value&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;任务 &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;index&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt; 失败: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;reason&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;\n--- 开始 Promise.any 演示 ---&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 忽略 fetchError，返回最快成功的 fetchUser&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; firstSuccess &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; Promise&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fetchError&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchUser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fetchPosts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Promise.any 赢家: &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;firstSuccess&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;全军覆没&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded><category>技术文章</category><category>vue</category></item><item><title>插槽</title><link>https://cjw32.xyz/blog/article/2025102701/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025102701/</guid><description>用子组件与父组件的对照代码说明 Vue 插槽的两种用法：匿名插槽（默认插槽）通过 slot 占位、父组件用 #default 填充，具名插槽用 name 区分 header/footer，并给出 v-slot:xxx 的完整写法与 #xxx 简写。</description><pubDate>Sun, 26 Oct 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;插槽&quot;&gt;插槽&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#插槽&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;插槽就是子组件中的提供给父组件使用的一个占位符，用&lt;slot&gt;&lt;/slot&gt; 表示，父组件可以在这个占位符中填充任何模板代码，如 HTML、组件等，填充的内容会替换子组件的&lt;slot&gt;&lt;/slot&gt;标签。&lt;/p&gt;
&lt;h4 id=&quot;匿名插槽&quot;&gt;匿名插槽&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#匿名插槽&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;!-- 我是子组件slot_test.vue --&gt;
&amp;#x3C;template&gt;
  &amp;#x3C;div style=&quot;background-color: aqua; width: 1000px; height: 100px&quot;&gt;&amp;#x3C;/div&gt;
  &amp;#x3C;div style=&quot;background-color: red; width: 1000px; height: 100px&quot;&gt;
    &amp;#x3C;slot&gt;&amp;#x3C;/slot&gt;
  &amp;#x3C;/div&gt;
  &amp;#x3C;div
    style=&quot;background-color: greenyellow; width: 1000px; height: 100px&quot;
  &gt;&amp;#x3C;/div&gt;
&amp;#x3C;/template&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;!-- 父组件 --&gt;
&amp;#x3C;template&gt;
  &amp;#x3C;slot_test&gt;
    &amp;#x3C;template #default&gt;
      &amp;#x3C;h3&gt;我是默认插槽&amp;#x3C;/h3&gt;
    &amp;#x3C;/template&gt;
  &amp;#x3C;/slot_test&gt;
&amp;#x3C;/template&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;具名插槽&quot;&gt;具名插槽&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#具名插槽&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;!-- 我是子组件slot_test.vue --&gt;
&amp;#x3C;template&gt;
  &amp;#x3C;div style=&quot;background-color: aqua; width: 1000px; height: 100px&quot;&gt;
    &amp;#x3C;slot name=&quot;header&quot;&gt;&amp;#x3C;/slot&gt;
  &amp;#x3C;/div&gt;
  &amp;#x3C;div style=&quot;background-color: red; width: 1000px; height: 100px&quot;&gt;
    &amp;#x3C;slot&gt;&amp;#x3C;/slot&gt;
  &amp;#x3C;/div&gt;
  &amp;#x3C;div style=&quot;background-color: greenyellow; width: 1000px; height: 100px&quot;&gt;
    &amp;#x3C;slot name=&quot;footer&quot;&gt;&amp;#x3C;/slot&gt;
  &amp;#x3C;/div&gt;
&amp;#x3C;/template&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;!-- 父组件 --&gt;
&amp;#x3C;template&gt;
  &amp;#x3C;slot_test&gt;
    &amp;#x3C;template #default&gt;
      &amp;#x3C;h3&gt;我是默认插槽&amp;#x3C;/h3&gt;
    &amp;#x3C;/template&gt;
    &amp;#x3C;!-- 完整写法 --&gt;
    &amp;#x3C;template v-slot:header&gt;
      &amp;#x3C;h3&gt;我是header插槽&amp;#x3C;/h3&gt;
    &amp;#x3C;/template&gt;
    &amp;#x3C;!-- 简写写法 --&gt;
    &amp;#x3C;template #footer&gt;
      &amp;#x3C;h3&gt;我是footer插槽&amp;#x3C;/h3&gt;
    &amp;#x3C;/template&gt;
  &amp;#x3C;/slot_test&gt;
&amp;#x3C;/template&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;span class=&quot;img-frame&quot;&gt;&lt;a class=&quot;img-lightbox&quot; href=&quot;https://cjw32.xyz/blog/media/e34a2693718cb4d07738.png&quot;&gt;&lt;img src=&quot;https://cjw32.xyz/blog/media/e34a2693718cb4d07738.png&quot; alt=&quot;35ecac4d360a8843add693ca42e29448.png&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot;&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</content:encoded><category>技术文章</category><category>vue</category></item><item><title>LazyMan函数实现</title><link>https://cjw32.xyz/blog/article/2025102501/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025102501/</guid><description>经典面试题 LazyMan 的完整解答：先给出四组调用与预期输出，再用队列 + next() 链式驱动实现 eat、sleep、sleepFirst（sleepFirst 通过 unshift 插到队首），最后逐步拆解 setTimeout(next, 0) 触发队列执行的流程。</description><pubDate>Fri, 24 Oct 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;lazyman函数实现&quot;&gt;LazyMan函数实现&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#lazyman函数实现&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;题目：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;span&gt;27&lt;/span&gt;&lt;span&gt;28&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//1&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;LazyMan&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Cain&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//输出“你好！我是Cain！”&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;//2&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;LazyMan&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Cain&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;eat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dinner&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//输出“你好！我是Cain！”&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//等待10秒&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//输出“我醒了，我睡了10秒”&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//输出“我现在吃晚饭”&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;//3&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;LazyMan&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Cain&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;eat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dinner&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;eat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;breakfast&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//输出“你好！我是Cain！”&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//等待10秒&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//输出“我醒了，我睡了10秒”&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//输出“我现在吃晚饭”&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//我现在吃早饭&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;//4&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;LazyMan&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Cain&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;eat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dinner&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;eat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;breakfast&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sleepFirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//等待5秒&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//输出“我醒了，我睡了5秒”&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//输出“你好！我是Cain！”&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//等待10秒&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//输出“我醒了，我睡了10秒”&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//输出“我现在吃晚饭”&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//我现在吃早饭&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;代码实现：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;span&gt;27&lt;/span&gt;&lt;span&gt;28&lt;/span&gt;&lt;span&gt;29&lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;span&gt;31&lt;/span&gt;&lt;span&gt;32&lt;/span&gt;&lt;span&gt;33&lt;/span&gt;&lt;span&gt;34&lt;/span&gt;&lt;span&gt;35&lt;/span&gt;&lt;span&gt;36&lt;/span&gt;&lt;span&gt;37&lt;/span&gt;&lt;span&gt;38&lt;/span&gt;&lt;span&gt;39&lt;/span&gt;&lt;span&gt;40&lt;/span&gt;&lt;span&gt;41&lt;/span&gt;&lt;span&gt;42&lt;/span&gt;&lt;span&gt;43&lt;/span&gt;&lt;span&gt;44&lt;/span&gt;&lt;span&gt;45&lt;/span&gt;&lt;span&gt;46&lt;/span&gt;&lt;span&gt;47&lt;/span&gt;&lt;span&gt;48&lt;/span&gt;&lt;span&gt;49&lt;/span&gt;&lt;span&gt;50&lt;/span&gt;&lt;span&gt;51&lt;/span&gt;&lt;span&gt;52&lt;/span&gt;&lt;span&gt;53&lt;/span&gt;&lt;span&gt;54&lt;/span&gt;&lt;span&gt;55&lt;/span&gt;&lt;span&gt;56&lt;/span&gt;&lt;span&gt;57&lt;/span&gt;&lt;span&gt;58&lt;/span&gt;&lt;span&gt;59&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; onMounted &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;vue&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;LazyMan&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; queue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;你好！我是&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;name&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;queue&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      queue&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  queue&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; api &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;等待了&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;time&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;秒&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; time &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      queue&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; api&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;eat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;food&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;food &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;dinner&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;我吃了晚饭&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;我吃了早饭&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      queue&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; api&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;sleepFirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token function-variable function&quot;&gt;task&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
          console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;等待了&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;time&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;秒&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; time &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      queue&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unshift&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; api&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; api&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;onMounted&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;LazyMan&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Cain&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;eat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dinner&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;eat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;breakfast&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sleepFirst&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;执行过程：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token number&quot;&gt;1.&lt;/span&gt; 创建 queue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;2.&lt;/span&gt; 创建 task 函数  
&lt;span class=&quot;token number&quot;&gt;3.&lt;/span&gt; queue&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; → queue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token number&quot;&gt;4.&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; ← 只是注册，不立即执行！
&lt;span class=&quot;token number&quot;&gt;5.&lt;/span&gt; 创建并返回 api 对象
&lt;span class=&quot;token number&quot;&gt;6.&lt;/span&gt; 调用 &lt;span class=&quot;token function&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
   &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; queue&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sleepTask&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; → queue &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;task&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sleepTask&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;token number&quot;&gt;7.&lt;/span&gt; 事件循环：现在才执行 setTimeout 回调回调！
   &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 第一次执行：取出并执行 &lt;span class=&quot;token function&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
     ↓
     输出&lt;span class=&quot;token string&quot;&gt;&quot;你好！我是张三&quot;&lt;/span&gt;
     调用 &lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
     
   &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 第二次执行：取出并执行 &lt;span class=&quot;token function&quot;&gt;sleepTask&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
     ↓
     设置&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;秒定时器
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded><category>面试</category><category>面试</category></item><item><title>生命周期</title><link>https://cjw32.xyz/blog/article/2025102502/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025102502/</guid><description>把 Vue 生命周期归纳为创建、更新、卸载三个阶段，用组合式 API 代码对应 onBeforeMount/onMounted、onBeforeUpdate/onUpdated、onBeforeUnmount/onUnmounted 六个钩子，并标注各自能否访问 DOM，最后补充 beforeCreate、created 与调试用的 onRenderTracked、onRenderTriggered。</description><pubDate>Fri, 24 Oct 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;生命周期&quot;&gt;生命周期&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#生命周期&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;vue有三个阶段，创建，更新，卸载，分别对应6个生命周期钩子函数&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;span&gt;27&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; onBeforeMount&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; onBeforeUnmount&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; onBeforeUpdate&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; onMounted&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; onUnmounted&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; onUpdated &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;vue&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;//创建&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;onBeforeMount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//无法访问dom&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;创建之前=======&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;onMounted&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//可以访问dom&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;创建之后=======&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//更新&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;onBeforeUpdate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//可以访问dom,访问到的是更新前的dom&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;更新之前=======&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;onUpdated&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;//可以访问dom,访问到的是更新后的dom&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;更新之后=======&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//卸载,卸载组件的操作可以通过使用v-if来进行卸载&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;onBeforeUnmount&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;卸载之前=======&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;onUnmounted&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;卸载之后=======&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;除此之外还有4个生命钩子函数分别是，beforeCreate,created(使用setup就没有前两个生命周期),onRenderTracked,onRenderTriggered(这两个生命周期钩子函数是用来调试的，他会在组件中内容被修改时返回一个effect事件)&lt;/p&gt;</content:encoded><category>技术文章</category><category>vue</category></item><item><title>watch监听器</title><link>https://cjw32.xyz/blog/article/2025102101/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025102101/</guid><description>介绍 Vue watch 监听器的用法：用 ref 配合 v-model 监听单个变量，用数组同时监听多个变量（回调收到新旧值数组），并说明 deep 深度监听、immediate 立即执行与 flush 的 pre/sync/post 三种时机。</description><pubDate>Mon, 20 Oct 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;watch监听器&quot;&gt;watch监听器&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#watch监听器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;用于监听响应式变量，当传入的响应式变量发生变化就执行传入的逻辑，用法如下：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;template&gt;
  &amp;#x3C;input type=&quot;text&quot; v-model=&quot;name1&quot; /&gt;
  &amp;#x3C;input type=&quot;text&quot; v-model=&quot;name2&quot; /&gt;
&amp;#x3C;/template&gt;

&amp;#x3C;script setup&gt;
import { ref, watch } from &quot;vue&quot;;

const name1 = ref(&quot;张三&quot;);
const name2 = ref(&quot;李四&quot;);

//当有多个变量需要监听时，可以使用数组，这样返回的值也是一个数组
watch([name1, name2], (newValues, oldValues) =&gt; {
  console.log(newValues, oldValues);
});
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;watch的其他参数&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; ref&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; watch &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;vue&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; name1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token literal-property property&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Cain&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token function&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;newValues&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; oldValues&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;newValues&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; oldValues&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;deep&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//开启深度监听&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;immediate&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//立即执行&lt;/span&gt;
  &lt;span class=&quot;token literal-property property&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;pre&quot;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//pre 组件更新前执行 sync 同步执行 post 组件更新后执行&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded><category>技术文章</category><category>vue</category></item><item><title>Computed计算属性</title><link>https://cjw32.xyz/blog/article/2025101901/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025101901/</guid><description>对比 Vue computed 计算属性的两种写法：选项式通过 get/set 同时支持读取与反向修改（示例用下划线拆分姓名），函数式只实现 get 逻辑、因此结果不可修改。</description><pubDate>Sat, 18 Oct 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;computed计算属性&quot;&gt;Computed计算属性&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#computed计算属性&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Computed有两种写法选项式和函数式&lt;/p&gt;
&lt;p&gt;选项式&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;template&gt;
&amp;#x3C;input type=&quot;text&quot; v-model=&quot;firstName&quot;&gt;
&amp;#x3C;input type=&quot;text&quot; v-model=&quot;lastName&quot;&gt;
{{ name }}
&amp;#x3C;button @click=&quot;change&quot;&gt;修改&amp;#x3C;/button&gt;
&amp;#x3C;/template&gt;

&amp;#x3C;script setup lang=&quot;ts&quot;&gt;
import { computed, ref } from &apos;vue&apos;;
const firstName = ref(&apos;张&apos;);
const lastName = ref(&apos;三&apos;);
const change = () =&gt; {
  name.value = &apos;Mc_Cain&apos;
}
//选项式
const name = computed({
  get() {//computed展示的逻辑
    return firstName.value + &quot;_&quot; + lastName.value
  },
  
  set(value: string) {//computed修改时执行的函数
    [firstName.value, lastName.value] = value.split(&apos;_&apos;)
  }
})
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;span class=&quot;img-frame&quot;&gt;&lt;a class=&quot;img-lightbox&quot; href=&quot;https://cjw32.xyz/blog/media/e7b85be4c654596b23bb.gif&quot;&gt;&lt;img src=&quot;https://cjw32.xyz/blog/media/e7b85be4c654596b23bb.gif&quot; alt=&quot;0e290cff4117940c39a052ce26edbdbe.gif&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot;&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;函数式&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;template&gt;
&amp;#x3C;input type=&quot;text&quot; v-model=&quot;firstName&quot;&gt;
&amp;#x3C;input type=&quot;text&quot; v-model=&quot;lastName&quot;&gt;
{{ name }}
&amp;#x3C;/template&gt;

&amp;#x3C;script setup lang=&quot;ts&quot;&gt;
import { computed, ref } from &apos;vue&apos;;
const firstName = ref(&apos;张&apos;);
const lastName = ref(&apos;三&apos;);

//函数式
const name = computed(() =&gt; {
  return firstName.value + lastName.value
})
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;函数式只能实现get函数的逻辑，不能实现set的逻辑，因此使用函数式定义的Computed不能修改&lt;/p&gt;</content:encoded><category>技术文章</category><category>vue</category></item><item><title>to全家桶</title><link>https://cjw32.xyz/blog/article/2025101601/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025101601/</guid><description>梳理 Vue 的 to 系列 API：toRef 把 reactive 的单个属性转成 ref（非响应式数据转不了），toRefs 批量转换并顺手手写了一遍底层实现，toRaw 则把响应式代理对象还原成普通对象，各附代码示例。</description><pubDate>Wed, 15 Oct 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;to全家桶&quot;&gt;to全家桶&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#to全家桶&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h5 id=&quot;toref能将reactive的属性转化为ref对象但是不能将非响应式的数据转化为ref对象可以用于将reactive的属性解构成ref对象&quot;&gt;toRef：能将reactive的属性转化为ref对象，但是不能将非响应式的数据转化为ref对象。可以用于将reactive的属性解构成ref对象。&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#toref能将reactive的属性转化为ref对象但是不能将非响应式的数据转化为ref对象可以用于将reactive的属性解构成ref对象&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;用法如下：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;script setup lang=&quot;ts&quot;&gt;
import { reactive, toRef } from &apos;vue&apos;;
const Cain = reactive({name: &quot;Cain&quot;})
const name = toRef(Cain, &quot;name&quot;)
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h5 id=&quot;torefs能将reactive的每一个属性转化为ref对象用法如下&quot;&gt;toRefs:能将reactive的每一个属性转化为ref对象，用法如下：&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#torefs能将reactive的每一个属性转化为ref对象用法如下&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h5&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;script setup lang=&quot;ts&quot;&gt;
import { reactive, toRef, toRefs } from &apos;vue&apos;;
const Cain = reactive({
  name: &apos;Cain&apos;,
  age: 18,
  gander: &quot;男&quot;
})
const { name, age, gander} = toRefs(Cain)
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;toRefs的底层实现非常简单，就是将reactive的每个属性都使用toRef转成ref，再创建一个全是ref对象属性reactive返回出去&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;script setup lang=&quot;ts&quot;&gt;
import { reactive, toRef } from &apos;vue&apos;;
const Cain = reactive({
  name: &apos;Cain&apos;,
  age: 18,
  gander: &quot;男&quot;
})
//手写toRef
const toRefs = &amp;#x3C;T extends object&gt;(object: T) =&gt; {
    const map:any = {}
    for (let key in object) {
      map[key] = toRef(object,key)
    }
    return map
}
const { name, age, gander} = toRefs(Cain)
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h5 id=&quot;toraw将响应式对象转化为普通对象即消除响应式&quot;&gt;toRaw:将响应式对象转化为普通对象，即消除响应式。&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#toraw将响应式对象转化为普通对象即消除响应式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;用法如下：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;script setup lang=&quot;ts&quot;&gt;
import { onMounted, reactive, toRaw, toRef } from &apos;vue&apos;;
const Cain = reactive({
  name: &apos;Cain&apos;,
  age: 18,
  gander: &quot;男&quot;
})
console.log(Cain,toRaw(Cain))
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;可以看到将原来的proxy对象变成了普通对象&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;img-frame&quot;&gt;&lt;a class=&quot;img-lightbox&quot; href=&quot;c:%5CUsers%5C86159%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20251016121355790.png&quot;&gt;&lt;img src=&quot;c:%5CUsers%5C86159%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20251016121355790.png&quot; alt=&quot;image-20251016121355790&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot;&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</content:encoded><category>技术文章</category><category>vue</category></item><item><title>响应式源码实现</title><link>https://cjw32.xyz/blog/article/2025101602/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025101602/</guid><description>用 TypeScript 手写 reactive 的核心实现：基于 Proxy 拦截 get/set 两个操作，在 get 中通过 Reflect.get 读取属性、set 中通过 Reflect.set 写入，并说明用 Reflect 是为了避免 this 上下文错乱。</description><pubDate>Wed, 15 Oct 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;响应式源码实现&quot;&gt;响应式源码实现&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#响应式源码实现&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h4 id=&quot;reactive&quot;&gt;reactive&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#reactive&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;script setup lang=&quot;ts&quot;&gt;
const reactive = &amp;#x3C;T extends object&gt;(target: T) =&gt; {
    return new Proxy(target, {
        get(target, key, receiver){//tarftet:目标对象 key:属性名 receiver:代理对象本身
            //返回目标对象的属性值,使用反射 API 执行原始的属性写入操作，行为与直接赋值类似，使用Reflect可以避免上下文错乱的问题
            return Reflect.get(target, key, receiver)
        },
        set(target, key, value, receiver){
            //设置目标对象的属性值
            return Reflect.set(target, key, value, receiver)
        }
    })
}
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded><category>技术文章</category><category>vue</category></item><item><title>Reactive全家桶</title><link>https://cjw32.xyz/blog/article/2025101301/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025101301/</guid><description>讲清 reactive 与 ref 的区别（只收引用类型、不用 .value）及不能整体赋值的代理限制，并介绍 readonly 生成只读版本、shallowReactive 只做第一层浅响应、深层修改不触发视图更新的特点。</description><pubDate>Sun, 12 Oct 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;reactive全家桶&quot;&gt;Reactive全家桶&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#reactive全家桶&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;reactive的作用也是创建一个响应式对象，reactive与ref的区别是reactive只接收引用类型（Object，Array，Map等），且使用时不用加.value。而ref接受任何类型，且使用时需要加.value。reactive的使用场景一般为为form表单进行数据双向绑定。&lt;/p&gt;
&lt;p&gt;由于reactive是一个proxy对象，所以不能直接用对象或者数组对reactive进行赋值，这样会让reactive失去响应性。&lt;/p&gt;
&lt;h4 id=&quot;readonly&quot;&gt;readonly&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#readonly&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;readonly能够将reactive变成只读的&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;script setup lang=&quot;ts&quot;&gt;
import { reactive, readonly } from &apos;vue&apos;;
const Cain = reactive({name: &quot;Cain&quot;})
const read = readonly(Cain)
//这样read就是Cain的只读版本了，是不能直接修改read里面的属性的，但是能够通过修改Cain的属性来间接修改read属性
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;shallowreactive&quot;&gt;shallowReactive&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#shallowreactive&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;与shallowRef相同，能将reactive变成浅层次的响应,根本原因还是因为没有触发视图的更新&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;template&gt;
  &amp;#x3C;button @click=&quot;change&quot;&gt;修改&amp;#x3C;/button&gt;
  &amp;#x3C;h1&gt;{{ shallowCain.first.name }}&amp;#x3C;/h1&gt;
&amp;#x3C;/template&gt;

&amp;#x3C;script setup lang=&quot;ts&quot;&gt;
import { reactive, readonly, shallowReactive } from &quot;vue&quot;;
const shallowCain = shallowReactive({
  first: {
    name: &quot;Cain&quot;,
  },
});
const Cain = reactive({ name: &quot;Cain&quot; });
const read = readonly(Cain);
const change = () =&gt; {
  //这样修改是不可以的，因为shallowReactive只到第一层即first
  shallowCain.first.name = &quot;我被修改了&quot;;
};
&amp;#x3C;/script&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;同样，shallowReactive也具有与shallowRef相同的特性，即与reactive写到一起的时候，也会引起shallowReactive的更新&lt;/p&gt;</content:encoded><category>技术文章</category><category>vue</category></item><item><title>Ref全家桶</title><link>https://cjw32.xyz/blog/article/2025101201/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025101201/</guid><description>如题</description><pubDate>Sat, 11 Oct 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;ref全家桶&quot;&gt;Ref全家桶&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#ref全家桶&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;由于ref返回的是一个ES6的class类，要修改ref的值要通过.value来进行修改。&lt;/p&gt;
&lt;h4 id=&quot;isref&quot;&gt;isRef&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#isref&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;用于判断是不是ref，用法为&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;script setup&gt;
import { isRef, ref } from &apos;vue&apos;;
const Cain = ref({name: &quot;Cain&quot;})
isRef(Cain)//返回一个布尔值
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;shallowref&quot;&gt;shallowRef&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#shallowref&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;ref实现深层次的响应，shallowRef实现浅层的响应&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;template&gt;
  &amp;#x3C;button @click=&quot;change&quot; style=&quot;width: 200px;height: 200px;&quot;&gt;修改&amp;#x3C;/button&gt;
  &amp;#x3C;div&gt;
    &amp;#x3C;h1&gt;ref:{{ Cain }}&amp;#x3C;/h1&gt;
    &amp;#x3C;h1&gt;shallowRef:{{ Cain2 }}&amp;#x3C;/h1&gt;
  &amp;#x3C;/div&gt;
&amp;#x3C;/template&gt;

&amp;#x3C;script setup&gt;
import { ref, shallowRef } from &quot;vue&quot;;
const Cain = ref({ name: &quot;Cain&quot; });
const Cain2 = shallowRef({ name: &quot;Cain2&quot; });
const change = () =&gt; {
  Cain2.value.name = &quot;Cain3&quot;;
  console.log(Cain2);
};
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;点击按钮前，视图效果如下：&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;img-frame&quot;&gt;&lt;a class=&quot;img-lightbox&quot; href=&quot;https://cjw32.xyz/blog/media/21fb6f50f6617f429b83.png&quot;&gt;&lt;img src=&quot;https://cjw32.xyz/blog/media/21fb6f50f6617f429b83.png&quot; alt=&quot;3d2e194d0e5a71e617e04ab795bfd14c.png&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot;&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;点击按钮后，视图效果没有变化，控制台输出：&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;img-frame&quot;&gt;&lt;a class=&quot;img-lightbox&quot; href=&quot;https://cjw32.xyz/blog/media/8dc0a4131a2c33e872a2.png&quot;&gt;&lt;img src=&quot;https://cjw32.xyz/blog/media/8dc0a4131a2c33e872a2.png&quot; alt=&quot;e298011cd3157fcaed7b912d1f29b36b.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;说明值变化了，但是视窗没有变化，这是因为shallowRef的响应是浅层的，shallowRef的响应只到.value处，如果要实现修改shallowRef的效果需要直接修改.value&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;script setup&gt;
import { ref, shallowRef } from &quot;vue&quot;;
const Cain = ref({ name: &quot;Cain&quot; });
const Cain2 = shallowRef({ name: &quot;Cain2&quot; });
const change = () =&gt; {
  Cain2.value = { name: &quot;Cain3&quot; };//修改成这样就可以实现响应了
  console.log(Cain2);
};
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;视窗显示：&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;img-frame&quot;&gt;&lt;a class=&quot;img-lightbox&quot; href=&quot;https://cjw32.xyz/blog/media/ca0c1dd9b74caaa0000b.png&quot;&gt;&lt;img src=&quot;https://cjw32.xyz/blog/media/ca0c1dd9b74caaa0000b.png&quot; alt=&quot;b4e08b8c53c44605ac35cc6583389b77.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;可以看到视图成功响应了，但是有一个地方需要注意就是如果ref跟shallowRef写到一起就会引起shallowRef跟ref一起变化&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;script setup&gt;
import { ref, shallowRef } from &quot;vue&quot;;
const Cain = ref({ name: &quot;Cain&quot; });
const Cain2 = shallowRef({ name: &quot;Cain2&quot; });
    
//如果这样写的话shallowRef就会被ref影响到改变
const change = () =&gt; {
  Cain.value.name = &quot;我是ref&quot;
  Cain2.value.name = &quot;我被影响了&quot;;
  console.log(Cain2);
};
    
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;span class=&quot;img-frame&quot;&gt;&lt;a class=&quot;img-lightbox&quot; href=&quot;https://cjw32.xyz/blog/media/35a8776d4173340472b7.png&quot;&gt;&lt;img src=&quot;https://cjw32.xyz/blog/media/35a8776d4173340472b7.png&quot; alt=&quot;6ec7e73d0ece78b804cb7ab5c260f1de.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;这是因为ref更新底层会调用triggerRef&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;script setup&gt;
import { ref, shallowRef, triggerRef } from &quot;vue&quot;;
const Cain = ref({ name: &quot;Cain&quot; });
const Cain2 = shallowRef({ name: &quot;Cain2&quot; });

//如果这样写的话shallowRef也会更新
const change = () =&gt; {
  Cain2.value.name = &quot;我被影响了&quot;;
  triggerRef(Cain2)
  console.log(Cain2);
};
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;效果如下：&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;img-frame&quot;&gt;&lt;a class=&quot;img-lightbox&quot; href=&quot;https://cjw32.xyz/blog/media/194d1e14a4b25285b1b4.png&quot;&gt;&lt;img src=&quot;https://cjw32.xyz/blog/media/194d1e14a4b25285b1b4.png&quot; alt=&quot;e11bb70b80af96a766ebb4bc1ae42c9b.png&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 id=&quot;customref&quot;&gt;customRef&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#customref&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;用于自己实现ref功能，但是可以在ref更新过程中加入一些自己的逻辑，例如防抖，下面是自己实现一个最简易的ref代码&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;script setup lang=&quot;ts&quot;&gt;
import { customRef, ref, shallowRef, triggerRef } from &quot;vue&quot;;
const Cain = ref({ name: &quot;Cain&quot; });
const Cain2 = shallowRef({ name: &quot;Cain2&quot; });
//实现一个最基础的ref
function MyRef&amp;#x3C;T&gt;(value: T) {
  return customRef((track, trigger) =&gt; {
    return {
      get(){
        track()//收集依赖
        return value
      },
      set(newVal){
        value = newVal
        trigger()//更新依赖
      }
    }
  })
}
const myRef = MyRef&amp;#x3C;string&gt;(&quot;myCain&quot;)
const change = () =&gt; {
  myRef.value = &quot;我被修改了&quot;
}
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;以下是最简单的防抖功能实现&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;span&gt;27&lt;/span&gt;&lt;span&gt;28&lt;/span&gt;&lt;span&gt;29&lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;script setup lang=&quot;ts&quot;&gt;
import { customRef, ref, shallowRef, triggerRef } from &quot;vue&quot;;
const Cain = ref({ name: &quot;Cain&quot; });
const Cain2 = shallowRef({ name: &quot;Cain2&quot; });
//实现一个最基础的防抖
function MyRef&amp;#x3C;T&gt;(value: T) {
  let timer: any;
  return customRef((track, trigger) =&gt; {
    return {
      get() {
        track(); //收集依赖
        return value;
      },
      set(newVal) {
        clearTimeout(timer);
        timer =  setTimeout(() =&gt; {
          console.log(&quot;调用了接口&quot;)
          timer = null
          value = newVal;
          trigger(); //更新依赖
        },500);
      },
    };
  });
}
const myRef = MyRef&amp;#x3C;string&gt;(&quot;myCain&quot;);
const change = () =&gt; {
  myRef.value = &quot;我被修改了&quot;;
};
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded><category>技术文章</category><category>vue</category></item><item><title>js中常用的数组操作</title><link>https://cjw32.xyz/blog/article/2025091001/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025091001/</guid><description>按增删改、遍历、转换、排序反转和其他常用方法五类整理 JS 数组操作速查表，每个方法标注作用、返回值与是否改变原数组，并附可直接运行的代码示例。</description><pubDate>Tue, 09 Sep 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;js中常用的数组操作&quot;&gt;js中常用的数组操作&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#js中常用的数组操作&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;本文按「增删改 → 遍历 → 转换 → 排序反转 → 其他常用」五类，整理 JavaScript 数组的常用方法。表中统一标注：&lt;strong&gt;作用&lt;/strong&gt;、&lt;strong&gt;返回值&lt;/strong&gt;、&lt;strong&gt;是否改变原数组&lt;/strong&gt;（原数组被修改记「是」，返回新数组记「否」）。&lt;/p&gt;
&lt;h2 id=&quot;1-数组增删改&quot;&gt;1. 数组增删改&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#1-数组增删改&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;11-添加元素&quot;&gt;1.1 添加元素&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#11-添加元素&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;


































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;方法&lt;/th&gt;&lt;th&gt;作用&lt;/th&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;push()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;在数组末尾添加元素&lt;/td&gt;&lt;td&gt;新数组长度&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;unshift()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;在数组开头添加元素&lt;/td&gt;&lt;td&gt;新数组长度&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;concat()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;合并数组，返回新数组&lt;/td&gt;&lt;td&gt;新数组&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;splice()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;在指定位置插入/删除元素&lt;/td&gt;&lt;td&gt;被删除的元素数组&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; arr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;// 返回 4，arr 变为 [1, 2, 3, 4]&lt;/span&gt;
arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;unshift&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;// 返回 5，arr 变为 [0, 1, 2, 3, 4]&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; merged &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// merged: [0, 1, 2, 3, 4, 5, 6]，arr 不变&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 从索引 1 开始删除 0 个元素，插入 9&lt;/span&gt;
arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;splice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 返回 []，arr 变为 [0, 9, 1, 2, 3, 4]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;12-删除元素&quot;&gt;1.2 删除元素&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#12-删除元素&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;


































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;方法&lt;/th&gt;&lt;th&gt;作用&lt;/th&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;pop()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;删除最后一个元素&lt;/td&gt;&lt;td&gt;被删除的元素&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;shift()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;删除第一个元素&lt;/td&gt;&lt;td&gt;被删除的元素&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;splice()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;删除指定位置元素&lt;/td&gt;&lt;td&gt;被删除的元素数组&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;filter()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;过滤符合条件的元素&lt;/td&gt;&lt;td&gt;新数组&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; arr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;          &lt;span class=&quot;token comment&quot;&gt;// 返回 5，arr 变为 [1, 2, 3, 4]&lt;/span&gt;
arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;// 返回 1，arr 变为 [2, 3, 4]&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; kept &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// kept: [3, 4]，arr 不变&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;13-修改元素&quot;&gt;1.3 修改元素&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#13-修改元素&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;






















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;方法&lt;/th&gt;&lt;th&gt;作用&lt;/th&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;splice()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;替换指定位置元素&lt;/td&gt;&lt;td&gt;被删除的元素数组&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;直接索引赋值&lt;/td&gt;&lt;td&gt;&lt;code&gt;arr[i] = 值&lt;/code&gt;&lt;/td&gt;&lt;td&gt;修改后的值&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; arr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

arr&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;99&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;          &lt;span class=&quot;token comment&quot;&gt;// arr 变为 [99, 2, 3, 4, 5]&lt;/span&gt;

arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;splice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 返回 [2, 3]，arr 变为 [99, 100, 4, 5]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;2-数组遍历&quot;&gt;2. 数组遍历&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#2-数组遍历&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;




















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;方法&lt;/th&gt;&lt;th&gt;作用&lt;/th&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;forEach()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;遍历数组&lt;/td&gt;&lt;td&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;map()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;映射新数组&lt;/td&gt;&lt;td&gt;新数组&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;filter()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;过滤数组&lt;/td&gt;&lt;td&gt;新数组&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;find()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;查找第一个匹配项&lt;/td&gt;&lt;td&gt;元素或 &lt;code&gt;undefined&lt;/code&gt;&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;findIndex()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;查找第一个匹配项的索引&lt;/td&gt;&lt;td&gt;索引或 &lt;code&gt;-1&lt;/code&gt;&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;some()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;检查是否至少有一个满足条件&lt;/td&gt;&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;every()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;检查是否所有元素满足条件&lt;/td&gt;&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; arr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 依次打印 1 2 3 4 5&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; doubled &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// doubled: [2, 4, 6, 8, 10]&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; evens &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// evens: [2, 4]&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; firstEven &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;      &lt;span class=&quot;token comment&quot;&gt;// 2&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; firstEvenIdx &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;findIndex&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 1&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; hasEven &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; allEven &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;every&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;       &lt;span class=&quot;token comment&quot;&gt;// false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;3-数组转换&quot;&gt;3. 数组转换&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#3-数组转换&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;方法&lt;/th&gt;&lt;th&gt;作用&lt;/th&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;join()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;数组转字符串&lt;/td&gt;&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;toString()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;数组转字符串（逗号分隔）&lt;/td&gt;&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;Array.from()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;类数组转数组&lt;/td&gt;&lt;td&gt;新数组&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;flat()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;数组扁平化&lt;/td&gt;&lt;td&gt;新数组&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;flatMap()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;先 &lt;code&gt;map()&lt;/code&gt; 再 &lt;code&gt;flat(1)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;新数组&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; arr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;-&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;      &lt;span class=&quot;token comment&quot;&gt;// &quot;1-2-3&quot;&lt;/span&gt;
arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;// &quot;1,2,3&quot;&lt;/span&gt;

Array&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;abc&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;]&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; nested &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
nested&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;      &lt;span class=&quot;token comment&quot;&gt;// [1, 2, 3, 4]&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; mapped &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;x&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; x &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// [1, 2, 2, 4, 3, 6]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h2 id=&quot;4-数组排序--反转&quot;&gt;4. 数组排序 &amp;#x26; 反转&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#4-数组排序--反转&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;






















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;方法&lt;/th&gt;&lt;th&gt;作用&lt;/th&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;sort()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;排序（默认按 Unicode）&lt;/td&gt;&lt;td&gt;排序后的数组&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;reverse()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;反转数组&lt;/td&gt;&lt;td&gt;反转后的数组&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; arr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;         &lt;span class=&quot;token comment&quot;&gt;// 默认按字符串比较&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// arr: [1, 2, 3, 4]&lt;/span&gt;

arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;a&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; b&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; a &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; b&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 数字升序&lt;/span&gt;
arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;      &lt;span class=&quot;token comment&quot;&gt;// arr: [4, 3, 2, 1]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;注意：&lt;code&gt;sort()&lt;/code&gt; 默认把元素转成字符串按 Unicode 比较，所以 &lt;code&gt;[10, 2, 1].sort()&lt;/code&gt; 的结果是 &lt;code&gt;[1, 10, 2]&lt;/code&gt;。数字排序务必传入比较函数。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;5-其他常用方法&quot;&gt;5. 其他常用方法&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#5-其他常用方法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;table-wrapper&quot;&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;方法&lt;/th&gt;&lt;th&gt;作用&lt;/th&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;slice()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;截取子数组&lt;/td&gt;&lt;td&gt;新数组&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;includes()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;检查是否包含某元素&lt;/td&gt;&lt;td&gt;&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;indexOf()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;查找元素索引（严格相等）&lt;/td&gt;&lt;td&gt;索引或 &lt;code&gt;-1&lt;/code&gt;&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;reduce()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;从左向右累积计算&lt;/td&gt;&lt;td&gt;计算结果&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;reduceRight()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;从右向左累积计算&lt;/td&gt;&lt;td&gt;计算结果&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; arr &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;slice&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;      &lt;span class=&quot;token comment&quot;&gt;// [2, 3]，arr 不变&lt;/span&gt;
arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;includes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;      &lt;span class=&quot;token comment&quot;&gt;// true&lt;/span&gt;
arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;indexOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;       &lt;span class=&quot;token comment&quot;&gt;// 2&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; sum &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;acc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cur&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; acc &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; cur&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;       &lt;span class=&quot;token comment&quot;&gt;// 15&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; sumFromRight &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; arr&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;reduceRight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;acc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cur&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; acc &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; cur&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 15&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded><category>技术文章</category><category>面试</category></item><item><title>react中的常用hook</title><link>https://cjw32.xyz/blog/article/2025082401/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025082401/</guid><description>如题</description><pubDate>Sat, 23 Aug 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;react中的常用hook&quot;&gt;react中的常用hook&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#react中的常用hook&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h4 id=&quot;usestate&quot;&gt;useState&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#usestate&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;状态是变化的数据，是组件甚至前端应用的核心。useState有传入值和函数两个参数，返回的setState也有传入值和传入函数两种参数。&lt;/p&gt;
&lt;h4 id=&quot;useeffect&quot;&gt;useEffect&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#useeffect&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;副作用effect函数是在渲染之外额外执行的一些逻辑。它是根据第二个参数的依赖数组是否变化来决定是否执行effect，可以返回一个清理函数，在下一次effect执行前执行。&lt;/p&gt;
&lt;h4 id=&quot;uselayouteffect&quot;&gt;useLayoutEffect&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#uselayouteffect&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;作用与useEffect差不多，但是useEffect的effect函数是异步进行的，所以中间有次渲染，中间可能会有闪屏。而useLayoutEffect是同步执行的，所以中间不会闪屏，但计算量大的话会导致掉帧。&lt;/p&gt;
&lt;h4 id=&quot;usereducer&quot;&gt;useReducer&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#usereducer&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;用来封装一些修改状态的逻辑到reducer，通常setState也能胜任，但是当需要多次使用逻辑时，setState需要书写多次逻辑，使用useReducer就不需要书写多次逻辑代码，直接封装成reducer，通过action触发。当修改深层对象时，创建新对象较麻烦，可以结合使用immer。&lt;/p&gt;
&lt;h4 id=&quot;useref&quot;&gt;useRef&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#useref&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;可以用来存储dom引用或者其他内容，通过xxRef.current来取，改变它的内容不会触发重新渲染。&lt;/p&gt;
&lt;h4 id=&quot;forwardref--useimperativehandle&quot;&gt;forwardRef + useImperativeHandle&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#forwardref--useimperativehandle&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;通过forwardRef 可以从子组件转发ref到父组件，如果想要自定义ref内容可以使用useImperativeHandle。&lt;/p&gt;
&lt;h4 id=&quot;usecontext&quot;&gt;useContext&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#usecontext&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;跨层组件之间传递数据可以使用useContext。用createContext创建Context对象，用provider修改其中的值，function组件用useContext的hook来取值，class组件用Consumer来取值。&lt;/p&gt;
&lt;h4 id=&quot;memo--usememo--usecallback&quot;&gt;memo + useMemo + useCallback&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#memo--usememo--usecallback&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;memo包裹的组件只有在props变的时候才会重新渲染，useMemo、useCallback可以防止props不必要的变化，两者一般是结合使用。不过用来当做缓存计算结果等场景的时候，也可以单独用useMemo、useCallback。&lt;/p&gt;</content:encoded><category>技术文章</category><category>React</category></item><item><title>hook的闭包陷阱的成因和解决方案</title><link>https://cjw32.xyz/blog/article/2025082402/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025082402/</guid><description>如题</description><pubDate>Sat, 23 Aug 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;hook的闭包陷阱的成因和解决方案&quot;&gt;hook的闭包陷阱的成因和解决方案&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#hook的闭包陷阱的成因和解决方案&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h4 id=&quot;成因&quot;&gt;成因&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#成因&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;闭包陷阱就是effect函数等引用了state，形成了闭包，但是并没有把state写到依赖数组中，导致执行effect时用的state还是更新之前的。&lt;/p&gt;
&lt;h4 id=&quot;解决方案&quot;&gt;解决方案&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#解决方案&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;1、直接把state加到依赖数组中，这样state变化就会重新执行effect函数，引用新的state。但这样做有一个弊端就是在需要用到定时器的场景中需要保证计时器只跑一次，不然重新跑会导致定时不准。&lt;/p&gt;
&lt;p&gt;2、使用useState的函数传入形式，从参数拿到上次的state，这样就不会形成闭包了，或者用useReducer，直接dispatch action，而不是直接操作state，这样页不会形成闭包。&lt;/p&gt;
&lt;p&gt;3、使用useRef保存每次渲染的值，用到的时候从ref.current取&lt;/p&gt;</content:encoded><category>技术文章</category><category>React</category></item><item><title>React核心语法</title><link>https://cjw32.xyz/blog/article/2025082101/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025082101/</guid><description>如题</description><pubDate>Wed, 20 Aug 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;react核心语法&quot;&gt;React核心语法&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#react核心语法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;项目搭建，方法一，在项目中引入React核心文件。方法二，使用脚手架进行创建，在终端输入npx create-react-app 项目名，cd到项目文件后使用npm start启动项目&lt;/p&gt;
&lt;h4 id=&quot;tsx基本语法&quot;&gt;tsx基本语法&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#tsx基本语法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;tsx&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;span&gt;27&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;import &apos;./App.css&apos;
function App(){
    let a = &quot;1&quot;
    const fn = () =&gt; {...}
    const fn2 = (num) =&gt; {...}
    const fn2 = &amp;#x3C;T,&gt;(num:T) =&gt; {...}//如果想要支持泛型函数需要在类型后面加一个逗号，这样就不会理解为html标签
    const cls = &quot;text&quot;
    const styles = {color:&quot;red&quot;}
    let html = `&amp;#x3C;seciton&gt;&amp;#x3C;div&gt;我是div&amp;#x3C;/div&gt;&amp;#x3C;/seciton&gt;`
              let arr = [1, 2, 3, 4]
    return(
    &amp;#x3C;&gt;
        &amp;#x3C;div&gt;{a}&amp;#x3C;/div&gt; //插值格式只需一个花括号
        &amp;#x3C;div onClick={fn}&gt;&amp;#x3C;/div&gt;//事件绑定使用小驼峰
        &amp;#x3C;div onClick={() =&gt; {fn2(123)}}&gt;&amp;#x3C;/div&gt;//如果需要传参使用高阶函数
        &amp;#x3C;div id={id}&gt;&amp;#x3C;/div&gt; //绑定id
        &amp;#x3C;div className={cls}&gt;&amp;#x3C;/div&gt; //绑定class
        &amp;#x3C;div className={`${cls} aaa ccc bbb`}&gt;&amp;#x3C;/div&gt; //绑定多个class
        &amp;#x3C;div style={styles}&gt;&amp;#x3C;/div&gt; //绑定style
        &amp;#x3C;div dangerouslySetInnerHTML={{__html: html}}&gt;&amp;#x3C;/div&gt; //添加html代码片段，注意标签中不能有内容
        &amp;#x3C;div&gt;{arr.map(v =&gt; {
                return &amp;#x3C;div key={v.id}&gt;{v}&amp;#x3C;/div&gt;
            })}&amp;#x3C;/div&gt; //遍历数组
    &amp;#x3C;/&gt;
    )
}
export default App
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;usestate&quot;&gt;useState&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#usestate&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;javascript&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;span&gt;27&lt;/span&gt;&lt;span&gt;28&lt;/span&gt;&lt;span&gt;29&lt;/span&gt;&lt;span&gt;30&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; useState &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;react&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//constent是本次渲染的数据内容，setConstent是用来修改状态的函数&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;constent&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;setConstent&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;默认内容&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleClick&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;setConstent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;修改内容&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;setData&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;useState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;默认标题&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;默认内容&apos;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleClick&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;setConstent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;修改内容&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;handleClick1&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;//由于这个函数的逻辑是直接替换状态，所以要重新写一个对象,数组同理&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;setConstent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;新内容&apos;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
    	&lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        	&lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;constent&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        	&lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;button onClick&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;handleClick&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;按钮&lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
			&lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;div&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        	&lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;button onClick&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;handleClick1&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;按钮&lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;button&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
        &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded><category>技术文章</category><category>React</category></item><item><title>文件上传及文件相关操作</title><link>https://cjw32.xyz/blog/article/2025081901/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025081901/</guid><description>如题</description><pubDate>Mon, 18 Aug 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;文件上传及文件相关操作&quot;&gt;文件上传及文件相关操作&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#文件上传及文件相关操作&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h4 id=&quot;前端文件上传有两种方式&quot;&gt;前端文件上传有两种方式&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#前端文件上传有两种方式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;二进制blob通过formData传输和转为base64传输&lt;/p&gt;
&lt;h4 id=&quot;前端文件上传涉及到四种文件对象&quot;&gt;前端文件上传涉及到四种文件对象&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#前端文件上传涉及到四种文件对象&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;files：通过input标签度过来的文件对象，前端对象不能传给后端&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;input type=&quot;file&quot; name=&quot;file&quot; @change=&quot;fileChage&quot;/&gt;

&amp;#x3C;script&gt;
	fileChage(e){
        console.log(e.target.files[0])//files对象是自己创建好的，是一个数组，如果是单文件上传就是第0项
    }
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;以下是对上传的文件进行文件类型与大小的限制方法&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;input type=&quot;file&quot; name=&quot;file&quot; @change=&quot;fileChage&quot;/&gt;

&amp;#x3C;script&gt;
	fileChage(e){
        let file = e.target.files[0]
        if(file.size &gt; 10 * 24 * 24)alert(&quot;文件不能大于十兆&quot;)
        if(file.type !== &apos;video/mp4&apos;)alert(&quot;文件必须是mp4&quot;)
    }
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;blob:不可变的二进制内容，包含很多操作方法&lt;/p&gt;
&lt;p&gt;fileReader:多用与把文件读取为某种形式，如base64,text文本&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;input type=&quot;file&quot; name=&quot;file&quot; @change=&quot;fileChage&quot;/&gt;
&amp;#x3C;script&gt;
	fileChage(e){
        let file = e.target.files[0]
        let blob = new Blob([file])//将file对象转为blob对象
        let _sliceBlob = blob.slice(0,5000)//对blob进行切割
        let _sliceFile = new File([_sliceBlob],&quot;fileName.png&quot;)//将切割后的blob转为file
        let fr = new FileReader()
        fr.readAsDataURL(_sliceFile)//将切割后的文件转成base64
        fr.onload = function() {//由于FileReader是异步执行的所以需要在这里面使用
            console.log(fr.result)
        }
    }
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;注：缩略图功能就是将base64的图片展示出来，文本预览也是使用FileReader做&lt;/p&gt;
&lt;p&gt;formData:用于和后端传输的对象&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;input type=&quot;file&quot; name=&quot;file&quot; @change=&quot;fileChage&quot;/&gt;
&amp;#x3C;button @click=&quot;submit&quot;&gt;提交&amp;#x3C;/button&gt;
&amp;#x3C;script&gt;
    let _fileObj
	fileChage(e){
        let file = e.target.files[0]
 		_fileObj = file
    }
    const submit = () =&gt; {//由于formdata的作用主要是用来传递给后端，所以在提交的时候进行转换即可
        let _formData = new FormData()
        _formData.append(&quot;user&quot;,&quot;abcabc&quot;)//在给后端的信息中添加一个字段叫user，值为abcabc
        _formData.append(&quot;file&quot;,_fileObj)//在给后端的信息中添加一个字段叫file，值为_fileObj
        axios.post(&quot;/xx.com&quot;,_formData)//发送给后端
    }
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;以上实现的就是单文件上传&lt;/p&gt;
&lt;p&gt;文件的转化关系如下&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;img-frame&quot;&gt;&lt;a class=&quot;img-lightbox&quot; href=&quot;https://cjw32.xyz/blog/media/f7559cb5ed1a6cc163fa.png&quot;&gt;&lt;img src=&quot;https://cjw32.xyz/blog/media/f7559cb5ed1a6cc163fa.png&quot; alt=&quot;781d05a6460b5b6aa0e68ef177f19023.png&quot; loading=&quot;eager&quot; fetchpriority=&quot;high&quot;&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h4 id=&quot;多文件上传&quot;&gt;多文件上传&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#多文件上传&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;原理就是将多个文件一个一个发送请求给后端&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;//加上multiple属性支持一次选择多个文件，但是用户体验不好，所以我们需要在js中对其进行一些操作
&amp;#x3C;input type=&quot;file&quot; name=&quot;file&quot; @change=&quot;fileChage&quot; multiple/&gt;
&amp;#x3C;button @click=&quot;submit&quot;&gt;提交&amp;#x3C;/button&gt;
&amp;#x3C;script&gt;
    let imgList = [];
    let _fileObj;
	fileChage(e){
        if(e.target.files.lenth &gt; 1){
            imgList = imgList.concat(e.target.files)//当添加的文件数大于1的时候就将数组与之前的添加的拼接
        }else{
            imgList.push(e.target.files[0])//当添加的文件数只有1的时候就直接push
        }
 		_fileObj = file
    }
    const submit = () =&gt; {//由于formdata的作用主要是用来传递给后端，所以在提交的时候进行转换即可
        imgList.forEach((item) =&gt; {//遍历数组，将文件转为FormData
            let _formData = new FormData()
            _formData.append(item.name,item)
            axios.post(&quot;/xx.com&quot;,_formData)//发送给后端
        })
        
    }
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;切片上传&quot;&gt;切片上传&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#切片上传&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;原理：将大文件切成多片再转成formdata形式传给后端&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;vue&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&amp;#x3C;input type=&quot;file&quot; name=&quot;file&quot; @change=&quot;fileChage&quot;/&gt;
&amp;#x3C;div&gt;{{ precent }}&amp;#x3C;/div&gt;//文件上传进度展示
&amp;#x3C;button @click=&quot;submit&quot;&gt;提交&amp;#x3C;/button&gt;

&amp;#x3C;script&gt;
    let _fileObj
    let precent //用来展示文件上传进度
	fileChage(e){
        let file = e.target.files[0]
 		_fileObj = file
    }
    const submit = () =&gt; {
        let size = 2 * 1024 * 1024 //每片大小2Mb
        let fileSize = _fileObj.size
        let current = 0 //当前切到位置的基准值
        while(current &amp;#x3C; fileSize){//只要还没切完就继续
            let _formData = new FormData()
            //每次发送2Mb的切片给后端
        	_formData.append(_fileObj.name,_fileObj.silce(current,current + size))
            await axios.post(&quot;xxx.com&quot;,_formData)
            precent = Math.min((current / fileSize) * 100, 100)//上传进度
            current += size
        }
    }
&amp;#x3C;/script&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;后端方面：判断传过来的文件名一致，就拼接起来&lt;/p&gt;</content:encoded><category>面试</category><category>面试</category></item><item><title>vite的基本使用</title><link>https://cjw32.xyz/blog/article/2025081801/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025081801/</guid><description>说明 Vite 基于 ESM 直接保持模块化、省去打包编译从而获得极快热更新的特点，并给出 vite.config.js 中 resolve、build.assetsInlineLimit、server.port 与 base 四项常用配置的示例。</description><pubDate>Sun, 17 Aug 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;vite的基本使用&quot;&gt;vite的基本使用&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#vite的基本使用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;vite的最大特点是利用esm，让代码不像传统的构建工具一样去分析引入，打包构建，而是直接保持模块化，这样省去了大量的编译时间，让代码更改后的响应速度大量提升&lt;/p&gt;
&lt;p&gt;基本结构，vite的配置写在vite.config.js中&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; defineConfig &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;vite&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;defineConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//用来写文件后缀省略或者别名的地方&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;assetsInlineLimit&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20000&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//小于20000图片转成base64&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//开发模式配置&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2000&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//端口号&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;www.xxx.com&quot;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//类似于webpack的public path&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded><category>技术文章</category><category>vite</category></item><item><title>webpack的基本使用</title><link>https://cjw32.xyz/blog/article/2025081601/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025081601/</guid><description>webpack 入门全景：从安装与 commonjs 配置文件讲起，逐项说明 entry、output、mode、loader、plugins 核心配置，再覆盖 babel-loader 转译、ESLint 规范、CSS 与资源文件处理、html-webpack-plugin，最后讲单/多入口代码分割与 publicPath 的 CDN 用法。</description><pubDate>Fri, 15 Aug 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;webpack的基本使用&quot;&gt;webpack的基本使用&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#webpack的基本使用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h4 id=&quot;基本使用&quot;&gt;基本使用&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#基本使用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;安装&lt;/p&gt;
&lt;p&gt;要安装webpack5就要安装webpack-cli，以下是全局安装命令&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M5 9H7.31L7.63 6H9.63L9.31 9H11.31L11.63 6H13.63L13.31 9H15V11H13.1L12.9 13H15V15H12.69L12.37 18H10.37L10.69 15H8.69L8.37 18H6.37L6.69 15H5V13H6.9L7.1 11H5V9M9.1 11L8.9 13H10.9L11.1 11M19 6H17V14H19M19 16H17V18H19Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;bash&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; webpack webpack-cli &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;webpack配置文件应建在根目录名为webpack.config.js，格式为&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 要使用commonjs格式&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;配置属性&quot;&gt;配置属性&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#配置属性&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;entry（必填）：打包入口&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./app.js&quot;&lt;/span&gt;，
        &lt;span class=&quot;token literal-property property&quot;&gt;app2&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./app2.js&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;output（必填）:出口，即打包出来的文件的存放位置&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./app.js&quot;&lt;/span&gt;，
        &lt;span class=&quot;token literal-property property&quot;&gt;app2&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./app2.js&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;，
    &lt;span class=&quot;token literal-property property&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;//由于要使用绝对路径，所以加个__dirname，表示当前目录下的绝对路径&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;__dirname&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./dist&quot;&lt;/span&gt; 
        &lt;span class=&quot;token comment&quot;&gt;//文件名设定，name指入口名，hash:4是指哈希值取前4位，如果打包内容发生了更新，哈希值就会更新&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;[name].[chunkhash:4].bundle.js&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;mode(webpack4以后必填):可以填三个值，production(生产模式)，development（开发模式）和none（什么都不做）&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//生产模式下会对代码进行压缩和简化，提高效率&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;production&quot;&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./app.js&quot;&lt;/span&gt;，
        &lt;span class=&quot;token literal-property property&quot;&gt;app2&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./app2.js&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;，
    &lt;span class=&quot;token literal-property property&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;__dirname&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./dist&quot;&lt;/span&gt; 
        &lt;span class=&quot;token literal-property property&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;[name].[chunkhash:4].bundle.js&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;loader（非必填）:定义对某种类型文件的处理方案&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//loader基本格式，在rules中写相应配置&lt;/span&gt;
&lt;span class=&quot;token literal-property property&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;rules&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;plugins(非必填)：插件&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//基本格式&lt;/span&gt;
&lt;span class=&quot;token literal-property property&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
    
&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;配置基本格式&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;production&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//打包模式&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;optimization&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;，&lt;span class=&quot;token comment&quot;&gt;//打包入口&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//出口&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;devServer&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//插件&lt;/span&gt;
    
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;webpack处理js&quot;&gt;webpack处理js&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#webpack处理js&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;babel-loader:负责将es6转化为es5&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M5 9H7.31L7.63 6H9.63L9.31 9H11.31L11.63 6H13.63L13.31 9H15V11H13.1L12.9 13H15V15H12.69L12.37 18H10.37L10.69 15H8.69L8.37 18H6.37L6.69 15H5V13H6.9L7.1 11H5V9M9.1 11L8.9 13H10.9L11.1 11M19 6H17V14H19M19 16H17V18H19Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;bash&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; babel-loader @babel/core --save-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;babel-loader的使用&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;span&gt;25&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;span&gt;27&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token literal-property property&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;rules&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;\.js$&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;//指对所有.js文件进行处理&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//有多个loader需要使用的时候也可以写成数组形式：use[&quot;babel-loader&quot;,&quot;xxx&quot;]&lt;/span&gt;
                &lt;span class=&quot;token literal-property property&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;babel-loader&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token literal-property property&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//options中填写配置项&lt;/span&gt;
                    &lt;span class=&quot;token literal-property property&quot;&gt;presets&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//可以将以下部分写到.babelrc中&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
               &lt;span class=&quot;token comment&quot;&gt;//需要另外安装，在命令行输入npm install @babel/preset-env --save-dev&lt;/span&gt;
                            &lt;span class=&quot;token string&quot;&gt;&apos;@babel/preset-env&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                &lt;span class=&quot;token literal-property property&quot;&gt;targets&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                                    &lt;span class=&quot;token literal-property property&quot;&gt;browsers&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//通用打包规则&lt;/span&gt;
                                        &lt;span class=&quot;token string&quot;&gt;&quot;&gt;1%&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                        &lt;span class=&quot;token string&quot;&gt;&quot;last 2 versions&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                                        &lt;span class=&quot;token string&quot;&gt;&quot;not ie &amp;#x3C;=8&quot;&lt;/span&gt; 
                                    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;ESlint:代码规范设定&lt;/p&gt;
&lt;p&gt;要使用ESlint需要安装ESlint（bash输入npm install eslint eslint-webpack-plugin --save-dev）,然后在webpack.config.js文件中引用&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; eslintplugin&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;eslint-webpack-plugin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;eslintplugin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//插件&lt;/span&gt;
    
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;eslint的配置文件写在根目录下的.eslintrc.js&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;22&lt;/span&gt;&lt;span&gt;23&lt;/span&gt;&lt;span&gt;24&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;browser&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;es2021&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//继承的代码规范，常用的有eslint-config-standard和eslint-config-airbnb&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//如果要继承需要重新安装，npm install eslint-config-standard --save-dev&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&quot;standard&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&quot;plugins:vue/strongly-recommended&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//插件,提供eslint没有的规则，或者使用现成的规范&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&quot;vue&quot;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//还需要在extends继承&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;praserOptions&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;ecmaVersion&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;sourceType&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;module&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;ecmaFeature&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//如果希望代码中的jsx也检查，就加上这个&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;jsx&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;rules&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//这里写eslint的规则，在官网有&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;css文件的处理&quot;&gt;css文件的处理&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#css文件的处理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;安装css-loader，bash输入npm install css-loader style-loader mini-css-extract-plugin --save-dev,以下是css-loader的使用：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; minicss&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;mini-css-extract-plugin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;rules&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;\.css&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//处理css文件&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;//顺序很重要，css-loader是让webpack识别css文件，style-loader是将css文件以style的方式插入代码中&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;minicss&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;loader&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;style-loader&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;css-loader&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;minicss&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;test.bundle.css&quot;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//配置文件名&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;css压缩插件css-minimizer-webpack-plugin:npm install css-minimizer-webpack-plugin --save-dev,使用方法依旧引入一下，然后在plugins中new一下即可&lt;/p&gt;
&lt;h4 id=&quot;资源文件处理&quot;&gt;资源文件处理&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#资源文件处理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;webpack5自带资源文件处理，使用方式如下&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;rules&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;\.(jpg|jpeg|png|gif|svg)$&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//处理资源文件&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;asset&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;parser&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token literal-property property&quot;&gt;dataUrlCondition&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token literal-property property&quot;&gt;maxSize&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//大于5kb的文件就单独拎出来保存，小于的就转化为base64保存在js代码中&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;generator&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token literal-property property&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;[name].[chunkhash][ext]&quot;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//ext是文件后缀&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;html处理&quot;&gt;html处理&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#html处理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;安装html-webpack-plugin&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; htmlplugin&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;html-webpack-plugin&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token literal-property property&quot;&gt;plugins&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;htmlplugin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./index.html&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//模版文件&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;index.html&quot;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//处理出来文件的名字&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;代码分割&quot;&gt;代码分割&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#代码分割&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;对于单入口文件，为了避免所有的文件打包在一个js里面导致首屏加载过慢，可以在单入口文件里面把后面才需要的文件通过异步加载的方式进行引入，以减少文件体积。使用import方法或require.ensure加载的模块在打包的时候会自动拆分为一个独立文件&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//例如在3000ms后才需要使用a.js&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;setTiomeout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;./a.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;then&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;res&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//then的作用是得到返回的内容&lt;/span&gt;
        console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;对于多入口文件，为了避免重复加载同一段逻辑代码，可以将需要重复使用的代码另外缓存下来，需要在webpack.config.js中设置 splitChunks,以下代码是将第三方代码与本地代码分离的打包方法&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;11&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;14&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;16&lt;/span&gt;&lt;span&gt;17&lt;/span&gt;&lt;span&gt;18&lt;/span&gt;&lt;span&gt;19&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;optimization&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;splitChunks&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;chunks&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;all&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token literal-property property&quot;&gt;cacheGroups&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//分割规则&lt;/span&gt;
                &lt;span class=&quot;token literal-property property&quot;&gt;vendor&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token literal-property property&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token regex&quot;&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token regex-source language-regex&quot;&gt;[\\/]node_modules[\\/]&lt;/span&gt;&lt;span class=&quot;token regex-delimiter&quot;&gt;/&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token literal-property property&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;vendor.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token literal-property property&quot;&gt;chunks&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;all&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token literal-property property&quot;&gt;minChunks&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;token literal-property property&quot;&gt;common&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token literal-property property&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;common.js&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token literal-property property&quot;&gt;chunks&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;all&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token literal-property property&quot;&gt;minChunks&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;token literal-property property&quot;&gt;minSize&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;publicPath:打包出来的js，css文件要放到cdn上的时候使用&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;js&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;module&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;exports&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token literal-property property&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//出口&lt;/span&gt;
        &lt;span class=&quot;token literal-property property&quot;&gt;publicPath&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;www.xxx.com&quot;&lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;//写cdn的地址，就会自动拼接到引用js，css的路径上面去了&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded><category>技术文章</category><category>webpack</category></item><item><title>关于markdown基础语法</title><link>https://cjw32.xyz/blog/article/2025081401/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025081401/</guid><description>本篇只简单介绍一下markdown的基本语法</description><pubDate>Wed, 13 Aug 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;基础语法&quot;&gt;基础语法&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#基础语法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;标题&quot;&gt;标题&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#标题&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;# 1级标题
## 2级标题
### 3级标题
#### 4级标题
##### 5级标题
###### 6级标题
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;个人建议在标题中只用2级3级标题即可，注意&lt;code&gt;#&lt;/code&gt;与标题中间有空格。&lt;/p&gt;
&lt;h3 id=&quot;段落&quot;&gt;段落&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#段落&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;这是第一行
空行
这是第二行
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;在markdown中，段落只需要在两行文字中空出来一行即可。&lt;/p&gt;
&lt;h3 id=&quot;换行&quot;&gt;换行&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#换行&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;这是第一行。两个空格
这是第二行
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;在markdown中，换行只需要在第一行文字后添加两个空格即可。&lt;/p&gt;
&lt;p&gt;在hexo（即这个博客）里面，只需要每两行加个回车即可，不用细抠那么仔细，只需要知道这个概念即可。&lt;/p&gt;
&lt;h3 id=&quot;强调&quot;&gt;强调&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#强调&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;**加粗**
*倾斜*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;在markdown中，强调有两种语法：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;加粗，在需要加粗的内容前后用&lt;strong&gt;两&lt;/strong&gt;个 * 进行包裹，同时注意 * 要和文字挨着。&lt;/li&gt;
&lt;li&gt;倾斜，在需要倾斜的内容前后用&lt;strong&gt;一&lt;/strong&gt;个 * 进行包裹，同时注意 * 要和文字挨着。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;引用&quot;&gt;引用&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#引用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&gt; 内容
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;在markdown中，引用需要在开头添加&lt;code&gt;&gt;&lt;/code&gt;然后加一个空格即可。&lt;/p&gt;
&lt;h3 id=&quot;列表&quot;&gt;列表&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#列表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;1. 内容
2. 内容

- 内容
- 内容
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;在markdown中，分为有序列表和无序列表，有序列表为&lt;code&gt;数字.空格内容&lt;/code&gt;，无序列表为&lt;code&gt;-空格内容&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id=&quot;代码块&quot;&gt;代码块&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#代码块&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;当你在编辑这个文件的时候，你总能看见有两组三个 ` 包裹起来的内容，这个就是代码块。&lt;/p&gt;
&lt;p&gt;格式为：&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M12,17.56L16.07,16.43L16.62,10.33H9.38L9.2,8.3H16.8L17,6.31H7L7.56,12.32H14.45L14.22,14.9L12,15.5L9.78,14.9L9.64,13.24H7.64L7.93,16.43L12,17.56M4.07,3H19.93L18.5,19.2L12,21L5.5,19.2L4.07,3Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;html&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M3,3H21V21H3V3M7.73,18.04C8.13,18.89 8.92,19.59 10.27,19.59C11.77,19.59 12.8,18.79 12.8,17.04V11.26H11.1V17C11.1,17.86 10.75,18.08 10.2,18.08C9.62,18.08 9.38,17.68 9.11,17.21L7.73,18.04M13.71,17.86C14.21,18.84 15.22,19.59 16.8,19.59C18.4,19.59 19.6,18.76 19.6,17.23C19.6,15.82 18.79,15.19 17.35,14.57L16.93,14.39C16.2,14.08 15.89,13.87 15.89,13.37C15.89,12.96 16.2,12.64 16.7,12.64C17.18,12.64 17.5,12.85 17.79,13.37L19.1,12.5C18.55,11.54 17.77,11.17 16.7,11.17C15.19,11.17 14.22,12.13 14.22,13.4C14.22,14.78 15.03,15.43 16.25,15.95L16.67,16.13C17.45,16.47 17.91,16.68 17.91,17.26C17.91,17.74 17.46,18.09 16.76,18.09C15.93,18.09 15.45,17.66 15.09,17.06L13.71,17.86Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;javascript&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;等。&lt;/p&gt;
&lt;h3 id=&quot;链接&quot;&gt;链接&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#链接&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;[链接名称](链接url)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;图片&quot;&gt;图片&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#图片&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M8,3A2,2 0 0,0 6,5V9A2,2 0 0,1 4,11H3V13H4A2,2 0 0,1 6,15V19A2,2 0 0,0 8,21H10V19H8V14A2,2 0 0,0 6,12A2,2 0 0,0 8,10V5H10V3M16,3A2,2 0 0,1 18,5V9A2,2 0 0,0 20,11H21V13H20A2,2 0 0,0 18,15V19A2,2 0 0,1 16,21H14V19H16V14A2,2 0 0,1 18,12A2,2 0 0,1 16,10V5H14V3H16Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;text&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;![链接名称](链接url)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;图片就是比链接在前面多一个 !&lt;/p&gt;</content:encoded><category>技术文章</category><category>markdown</category></item><item><title>git基础语法</title><link>https://cjw32.xyz/blog/article/2025081402/</link><guid isPermaLink="true">https://cjw32.xyz/blog/article/2025081402/</guid><description>git的基本使用语法</description><pubDate>Wed, 13 Aug 2025 16:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;git常用指令&quot;&gt;git常用指令&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#git常用指令&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h2 id=&quot;基础操作&quot;&gt;基础操作&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#基础操作&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;初始化--克隆&quot;&gt;初始化 &amp;#x26; 克隆&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#初始化--克隆&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;在网上找到要克隆的仓库，复制克隆网址，输入以下代码&lt;/p&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M5 9H7.31L7.63 6H9.63L9.31 9H11.31L11.63 6H13.63L13.31 9H15V11H13.1L12.9 13H15V15H12.69L12.37 18H10.37L10.69 15H8.69L8.37 18H6.37L6.69 15H5V13H6.9L7.1 11H5V9M9.1 11L8.9 13H10.9L11.1 11M19 6H17V14H19M19 16H17V18H19Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;bash&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; init                  &lt;span class=&quot;token comment&quot;&gt;# 初始化本地仓库&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;仓库URL&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;       &lt;span class=&quot;token comment&quot;&gt;# 克隆远程仓库&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;提交更改&quot;&gt;提交更改&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#提交更改&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M5 9H7.31L7.63 6H9.63L9.31 9H11.31L11.63 6H13.63L13.31 9H15V11H13.1L12.9 13H15V15H12.69L12.37 18H10.37L10.69 15H8.69L8.37 18H6.37L6.69 15H5V13H6.9L7.1 11H5V9M9.1 11L8.9 13H10.9L11.1 11M19 6H17V14H19M19 16H17V18H19Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;bash&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; status               &lt;span class=&quot;token comment&quot;&gt;# 查看文件状态&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;文件名&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;         &lt;span class=&quot;token comment&quot;&gt;# 添加单个文件到暂存区&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;                &lt;span class=&quot;token comment&quot;&gt;# 添加所有更改到暂存区&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;描述&quot;&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;# 提交更改到本地仓库&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; commit &lt;span class=&quot;token parameter variable&quot;&gt;--amend&lt;/span&gt;       &lt;span class=&quot;token comment&quot;&gt;# 修改最后一次提交（未推送时）&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;查看历史&quot;&gt;查看历史&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#查看历史&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M5 9H7.31L7.63 6H9.63L9.31 9H11.31L11.63 6H13.63L13.31 9H15V11H13.1L12.9 13H15V15H12.69L12.37 18H10.37L10.69 15H8.69L8.37 18H6.37L6.69 15H5V13H6.9L7.1 11H5V9M9.1 11L8.9 13H10.9L11.1 11M19 6H17V14H19M19 16H17V18H19Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;bash&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; log                  &lt;span class=&quot;token comment&quot;&gt;# 查看提交历史&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; log &lt;span class=&quot;token parameter variable&quot;&gt;--oneline&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;# 简洁版提交历史&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; show &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;commit-id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;# 查看某次提交的详情&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h2 id=&quot;分支操作&quot;&gt;分支操作&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#分支操作&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M5 9H7.31L7.63 6H9.63L9.31 9H11.31L11.63 6H13.63L13.31 9H15V11H13.1L12.9 13H15V15H12.69L12.37 18H10.37L10.69 15H8.69L8.37 18H6.37L6.69 15H5V13H6.9L7.1 11H5V9M9.1 11L8.9 13H10.9L11.1 11M19 6H17V14H19M19 16H17V18H19Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;bash&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;7&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; branch               &lt;span class=&quot;token comment&quot;&gt;# 查看本地分支&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; branch &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;分支名&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;      &lt;span class=&quot;token comment&quot;&gt;# 创建新分支&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; checkout &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;分支名&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;# 切换分支&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; checkout &lt;span class=&quot;token parameter variable&quot;&gt;-b&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;分支名&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 创建并切换到新分支&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; merge &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;分支名&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;       &lt;span class=&quot;token comment&quot;&gt;# 合并指定分支到当前分支&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; branch &lt;span class=&quot;token parameter variable&quot;&gt;-d&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;分支名&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;# 删除本地分支（已合并）&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; branch &lt;span class=&quot;token parameter variable&quot;&gt;-D&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;分支名&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;   &lt;span class=&quot;token comment&quot;&gt;# 强制删除本地分支（未合并）&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;远程分支&quot;&gt;远程分支&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#远程分支&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M5 9H7.31L7.63 6H9.63L9.31 9H11.31L11.63 6H13.63L13.31 9H15V11H13.1L12.9 13H15V15H12.69L12.37 18H10.37L10.69 15H8.69L8.37 18H6.37L6.69 15H5V13H6.9L7.1 11H5V9M9.1 11L8.9 13H10.9L11.1 11M19 6H17V14H19M19 16H17V18H19Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;bash&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; fetch                &lt;span class=&quot;token comment&quot;&gt;# 拉取远程分支信息（不自动合并）&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; pull                 &lt;span class=&quot;token comment&quot;&gt;# 拉取远程分支并合并（= fetch + merge）&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push &lt;span class=&quot;token parameter variable&quot;&gt;-u&lt;/span&gt; origin &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;分支名&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 推送本地分支到远程并关联&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push origin &lt;span class=&quot;token parameter variable&quot;&gt;--delete&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;分支名&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 删除远程分支&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h2 id=&quot;撤销与回退&quot;&gt;撤销与回退&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#撤销与回退&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;撤销工作区修改&quot;&gt;撤销工作区修改&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#撤销工作区修改&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M5 9H7.31L7.63 6H9.63L9.31 9H11.31L11.63 6H13.63L13.31 9H15V11H13.1L12.9 13H15V15H12.69L12.37 18H10.37L10.69 15H8.69L8.37 18H6.37L6.69 15H5V13H6.9L7.1 11H5V9M9.1 11L8.9 13H10.9L11.1 11M19 6H17V14H19M19 16H17V18H19Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;bash&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; restore &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;文件名&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;# 撤销工作区的修改（未 add）&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; restore &lt;span class=&quot;token parameter variable&quot;&gt;--staged&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;文件名&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 撤销暂存区的修改（已 add）&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;回退提交&quot;&gt;回退提交&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#回退提交&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M5 9H7.31L7.63 6H9.63L9.31 9H11.31L11.63 6H13.63L13.31 9H15V11H13.1L12.9 13H15V15H12.69L12.37 18H10.37L10.69 15H8.69L8.37 18H6.37L6.69 15H5V13H6.9L7.1 11H5V9M9.1 11L8.9 13H10.9L11.1 11M19 6H17V14H19M19 16H17V18H19Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;bash&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; reset &lt;span class=&quot;token parameter variable&quot;&gt;--soft&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;commit-id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# 回退提交但保留更改到暂存区&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; reset &lt;span class=&quot;token parameter variable&quot;&gt;--hard&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;commit-id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# 彻底回退到指定提交（慎用！）&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; revert &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;commit-id&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;# 生成一个新提交来撤销某次提交（安全）&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;h2 id=&quot;远程仓库&quot;&gt;远程仓库&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#远程仓库&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;关联与推送&quot;&gt;关联与推送&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#关联与推送&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M5 9H7.31L7.63 6H9.63L9.31 9H11.31L11.63 6H13.63L13.31 9H15V11H13.1L12.9 13H15V15H12.69L12.37 18H10.37L10.69 15H8.69L8.37 18H6.37L6.69 15H5V13H6.9L7.1 11H5V9M9.1 11L8.9 13H10.9L11.1 11M19 6H17V14H19M19 16H17V18H19Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;bash&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; remote &lt;span class=&quot;token parameter variable&quot;&gt;-v&lt;/span&gt;            &lt;span class=&quot;token comment&quot;&gt;# 查看远程仓库地址&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; remote &lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt; origin &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;URL&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 关联远程仓库&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push origin &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;分支名&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# 推送到远程分支&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; push &lt;span class=&quot;token parameter variable&quot;&gt;--force&lt;/span&gt;         &lt;span class=&quot;token comment&quot;&gt;# 强制推送（覆盖远程，慎用！）&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;拉取更新&quot;&gt;拉取更新&lt;a class=&quot;heading-anchor&quot; tabindex=&quot;-1&quot; aria-label=&quot;heading anchor&quot; href=&quot;#拉取更新&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div class=&quot;code-block&quot;&gt;&lt;div class=&quot;code-header&quot;&gt;&lt;span class=&quot;code-lang&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M5 9H7.31L7.63 6H9.63L9.31 9H11.31L11.63 6H13.63L13.31 9H15V11H13.1L12.9 13H15V15H12.69L12.37 18H10.37L10.69 15H8.69L8.37 18H6.37L6.69 15H5V13H6.9L7.1 11H5V9M9.1 11L8.9 13H10.9L11.1 11M19 6H17V14H19M19 16H17V18H19Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;bash&lt;/span&gt;&lt;button class=&quot;code-copy&quot; type=&quot;button&quot; onclick=&quot;window.__blogCopyCode(this)&quot;&gt;&lt;svg class=&quot;mdi-icon&quot; width=&quot;1em&quot; height=&quot;1em&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;currentColor&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;span&gt;复制&lt;/span&gt;&lt;/button&gt;&lt;/div&gt;&lt;div class=&quot;code-body&quot;&gt;&lt;div class=&quot;code-gutter&quot;&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/div&gt;&lt;pre class=&quot;code-pre&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; pull origin &lt;span class=&quot;token operator&quot;&gt;&amp;#x3C;&lt;/span&gt;分支名&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# 拉取远程分支&gt;  # 拉取远程分支最新代码&lt;/span&gt;
   &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; fetch &lt;span class=&quot;token parameter variable&quot;&gt;--prune&lt;/span&gt;        &lt;span class=&quot;token comment&quot;&gt;# 同步远程已删除的分支&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content:encoded><category>技术文章</category><category>git</category></item></channel></rss>