<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://f.youzi177.cn/</id>
  <title type="text">小封鸭</title>
  <subtitle type="text">小楼一夜听春雨</subtitle>
  <updated>2026-10-25T07:58:27.000Z</updated>
  <author><name>小封鸭</name></author>
  <link rel="alternate" href="https://f.youzi177.cn/"/>
  <link rel="self" href="https://f.youzi177.cn/atom.xml"/>
  <generator uri="https://github.com/CuteLeaf/Firefly">Firefly v6.16.8</generator>
    <entry>
      <id>https://f.youzi177.cn/posts/2026101804javascript-chang-yong-api/</id>
      <title type="text">JavaScript常用API-更新中</title>
      <published>2026-10-18T07:13:35.000Z</published>
      <updated>2026-10-18T07:13:35.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026101804javascript-chang-yong-api/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>记录一些JavaScript中经常用到的一些API，方便后续可以快速查看，如字符串、数组的方法，对象的遍历，还有后续ES6的常用API</p>
<section><h1>字符串方法<a href="#字符串方法"><span>#</span></a></h1>

<table><thead><tr><th>方法</th><th>功能</th></tr></thead><tbody><tr><td><code>charAt()</code></td><td>得到指定位置的字符</td></tr><tr><td><code>substring()</code></td><td>提取子串，从a开始到b</td></tr><tr><td><code>substr()</code></td><td>提取子串，从a开始，长度为b</td></tr><tr><td><code>slice()</code></td><td>提取子串，从a开始到b结束（不包括b处）</td></tr><tr><td><code>toUpperCase()</code></td><td>将字符串转换为大写</td></tr><tr><td><code>toLowerCase()</code></td><td>将字符串转换为小写</td></tr><tr><td><code>indexOf()</code></td><td>检索字符串，返回指定内容首次出现的位置</td></tr></tbody></table><p><strong>charAt()方法</strong></p><ul>
<li>
<p>charAt()方法可以得到指定位置的字符</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>charAt</span><span>(</span><span>0</span><span>) </span><span>// '我'</span></div></div><div><div><div>2</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>charAt</span><span>(</span><span>11</span><span>) </span><span>// 'T'</span></div></div><div><div><div>3</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>charAt</span><span>(</span><span>74</span><span>) </span><span>// ''</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>substring()、substr()和slice()</strong></p><ul>
<li>
<p>substring(a, b) 方法得到从a开始到b结束（不包括b处）的子串</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>substring</span><span>(</span><span>3</span><span>, </span><span>5</span><span>) </span><span>// 'JS'</span></div></div><div><div><div>2</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>substring</span><span>(</span><span>10</span><span>, </span><span>14</span><span>) </span><span>// 'HTML'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>substring(a) 方法如果省略第二个参数，返回的子串会一直到字符串 的结尾</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>substring</span><span>(</span><span>6</span><span>) </span><span>// '我也喜欢HTML'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>substring(a, b) 中，a可以大于b，数字顺序将自动调整为小数在前</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>substring</span><span>(</span><span>5</span><span>, </span><span>3</span><span>) </span><span>// 'JS'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>substr (a, b)中，将得到从a开始的长度为b的子串</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>substr</span><span>(</span><span>3</span><span>, </span><span>2</span><span>) </span><span>// 'JS'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>substr(a, b)中，b可以省略，表示到字符串结尾</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>substr</span><span>(</span><span>3</span><span>) </span><span>// 'JS，我也喜欢HTML</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>substr (a, b)中，a可以是负数，表示倒数位置</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>substr</span><span>(</span><span>-</span><span>4</span><span>, </span><span>2</span><span>) </span><span>// HT'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>slice(a, b)方法得到从a开始到b结束（不包括b处）的子串</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>slice</span><span>(</span><span>3</span><span>, </span><span>5</span><span>) </span><span>// 'JS'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>slice(a, b)的参数a可以是负数</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>slice</span><span>(</span><span>-</span><span>4</span><span>, </span><span>-</span><span>1</span><span>) </span><span>// 'HTM'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>slice(a, b)中，参数a必须小于参数b</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>slice</span><span>(</span><span>5</span><span>, </span><span>2</span><span>) </span><span>// ''</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>对比总结</strong></p><ul>
<li>
<p>substring(a, b)和slice(a, b)功能基本一致，都是得到从a开始到b 结束（不包括b）的子串，区别：</p>
<p>① substring()可以自动交换两个参数位置，而slice()不行；</p>
<p>②slice()的参数a可以是负数，而substring()不行。</p>
</li>
<li>
<p>substr(a, b)中参数b是子串长度，而不是位置编号</p>
</li>
</ul><p><strong>toUpperCase()和toLowerCase()</strong></p><ul>
<li>
<p>toUpperCase() 转为大写</p>
</li>
<li>
<p>toLowerCase() 转为小写</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'i love you'</span><span>.</span><span>toUpperCase</span><span>(); </span><span>// 'I LOVE YOU'</span></div></div><div><div><div>2</div></div><div><span>'IMOOC'</span><span>.</span><span>toLowerCase</span><span>(); </span><span>// 'imooc'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>indexOf()</strong></p><ul>
<li>
<p>indexOf()方法返回某个指定的字符串值在字符串中首次出现的位置</p>
</li>
<li>
<p>如果要检索的字符串值没有出现，则该返回 -1</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'abcdeb'</span><span>.</span><span>indexOf</span><span>(</span><span>'b'</span><span>) </span><span>// 1</span></div></div><div><div><div>2</div></div><div><span>'abcdeb'</span><span>.</span><span>indexOf</span><span>(</span><span>'de'</span><span>) </span><span>// 3</span></div></div><div><div><div>3</div></div><div><span>'abcdeb'</span><span>.</span><span>indexOf</span><span>(</span><span>'m'</span><span>) </span><span>// -1</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h1>数组的常用方法<a href="#数组的常用方法"><span>#</span></a></h1><p>数组提供大量内置方法，主要包括添加、删除、查找、遍历、排序和转换。这里只列举一些常用的，在ES6语法中会再增加一些（slice、splice、<strong>split</strong>这三个英文非常像，初学很可能弄混，这三个是完全不一样功能的，split是字符串的方法，数组可以通过join转字符串，字符串可以使用split转为数组）</p><p><strong>添加与删除</strong>：这5个是最基础的，splice是功能最多的，push和pop是开发中最常用的</p>

<table><thead><tr><th>方法</th><th>作用</th><th>是否修改原数组</th></tr></thead><tbody><tr><td><code>push()</code></td><td>末尾添加元素</td><td>是</td></tr><tr><td><code>pop()</code></td><td>删除末尾元素</td><td>是</td></tr><tr><td><code>unshift()</code></td><td>开头添加元素</td><td>是</td></tr><tr><td><code>shift()</code></td><td>删除开头元素</td><td>是</td></tr><tr><td><code>splice()</code></td><td>添加、删除或替换指定位置元素</td><td>是</td></tr></tbody></table><p>push()方法：（末尾追加）</p><ul>
<li>
<p>push()方法用来在数组末尾推入新项，参数就是要推入 的项</p>
</li>
<li>
<p>如果要推入多项，可以用逗号隔开</p>
</li>
<li>
<p>调用push()方法后，数组会立即改变，不需要赋值</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>arr</span><span>.</span></span><span>push</span><span>(</span><span>4</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// [1, 2, 3, 4]</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>arr</span><span>.</span></span><span>push</span><span>(</span><span>5</span><span>, </span><span>6</span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// [1, 2, 3, 4, 5, 6]</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p>pop()方法：（删除末尾）</p><ul>
<li>
<p>与push()相反，pop()方法用来删除数组中的最后一项</p>
</li>
<li>
<p>pop()方法不仅会删除数组末项，而且会返回被删除的项</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>item</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>pop</span><span>();</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>);  </span></span><span>// [1, 2, 3]</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>item</span><span>);  </span></span><span>// 4</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p>unshift()方法：（头部插入）</p><ul>
<li>
<p>unshift()方法用来在数组头尾插入新项，参数就是要 插入的项</p>
</li>
<li>
<p>如果要插入多项，可以用逗号隔开</p>
</li>
<li>
<p>调用unshift()方法后，数组会立即改变，不需要赋值</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>arr</span><span>.</span></span><span>unshift</span><span>(</span><span>1</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// [1, 2, 3, 4]</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>arr</span><span>.</span></span><span>unshift</span><span>(</span><span>-</span><span>1</span><span>, </span><span>0</span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// [-1, 0, 1, 2, 3, 4]</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p>shift()方法：（删除头部）</p><ul>
<li>
<p>与unshift()相反，shift()方法用来删除数组中下标为0 的项</p>
</li>
<li>
<p>shift()方法不仅会删除数组末项，而且会返回被删除的项</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>item</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>shift</span><span>();</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// [20, 30]</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>item</span><span>); </span></span><span>// 10</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p>splice()方法</p><ul>
<li>
<p>splice()方法第一个参数是从哪个下标开始，第二个参数是删除多少个项</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>arr</span><span>.</span></span><span>splice</span><span><span>(</span><span>起始下标</span><span>, </span><span>删除个数</span><span>)</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>'A'</span><span>,</span><span>'B'</span><span>,</span><span>'C'</span><span>,</span><span>'D'</span><span>,</span><span>'E'</span><span>,</span><span>'F'</span><span>,</span><span>'G'</span><span>];</span></div></div><div><div><div>2</div></div><div><span><span>arr</span><span>.</span></span><span>splice</span><span>(</span><span>3</span><span>,</span><span>2</span><span>,</span><span>'X'</span><span>,</span><span>'Y'</span><span>,</span><span>'Z'</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>);</span></span></div></div><div><div><div>4</div></div><div><span>// 下标3开始，连续替换2项；这种说法错误的</span></div></div><div><div><div>5</div></div><div><span>// 准确是：下标3开始，连续删除2项，然后插入新元素</span></div></div><div><div><div>6</div></div><div><span>// [ 'A', 'B', 'C', 'X', 'Y', 'Z','F', 'G']</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>splice()方法可以用于在指定位置插入新项（第二个参数设置0，就没有删除项）</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>arr</span><span>.</span></span><span>splice</span><span><span>(</span><span>起始下标</span><span>, </span></span><span>0</span><span><span>, </span><span>新元素</span><span>)</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>5</span><span>, </span><span>6</span><span>];</span></div></div><div><div><div>2</div></div><div><span><span>arr</span><span>.</span></span><span>splice</span><span>(</span><span>2</span><span>, </span><span>0</span><span>, </span><span>3</span><span>, </span><span>4</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// [1, 2, 3, 4, 5, 6]</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>splice()方法可以用于删除指定项；result返回被删除的项</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>arr</span><span>.</span></span><span>splice</span><span><span>(</span><span>起始下标</span><span>, </span><span>删除个数</span><span>)</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>, </span><span>40</span><span>];</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>splice</span><span>(</span><span>1</span><span>, </span><span>1</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>);    </span></span><span>// [10, 30, 40]</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>); </span></span><span>// [20]</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>splice()方法会以数组形式返回被删除的项</p>
</li>
</ul><p><strong>查找与判断：</strong></p>

<table><thead><tr><th>方法</th><th>作用</th><th>返回值</th></tr></thead><tbody><tr><td><code>indexOf()</code></td><td>查找元素首次出现的位置</td><td>下标或 -1</td></tr><tr><td><code>lastIndexOf()</code></td><td>查找元素最后出现的位置</td><td>下标或 -1</td></tr><tr><td><code>includes()</code></td><td>判断是否包含元素</td><td>布尔值</td></tr><tr><td><code>find()</code></td><td>查找第一个符合条件的元素</td><td>元素或 undefined</td></tr><tr><td><code>findIndex()</code></td><td>查找第一个符合条件的元素下标</td><td>下标或 -1</td></tr><tr><td><code>some()</code></td><td>是否至少一个元素符合条件</td><td>布尔值</td></tr><tr><td><code>every()</code></td><td>是否所有元素符合条件</td><td>布尔值</td></tr></tbody></table><p>indexOf()方法的功能是搜索数组中的元素，并返回它所 在的位置，如果元素不存在，则返回-1</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>'A'</span><span>, </span><span>'B'</span><span>, </span><span>'C'</span><span>, </span><span>'D'</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>.</span></span><span>indexOf</span><span>(</span><span>'B'</span><span>)); </span><span>// 1</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>.</span></span><span>indexOf</span><span>(</span><span>'Z'</span><span>)); </span><span>// -1</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>includes()方法的功能是判断一个数组是否包含一个指定 的值，返回布尔值</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>'A'</span><span>, </span><span>'B'</span><span>, </span><span>'C'</span><span>];</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>.</span></span><span>includes</span><span>(</span><span>'B'</span><span>)); </span><span>// true</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>.</span></span><span>includes</span><span>(</span><span>'Z'</span><span>)); </span><span>// false</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>截取、合并与转换</strong></p>

<table><thead><tr><th>方法</th><th>作用</th><th>是否修改原数组</th></tr></thead><tbody><tr><td><code>slice()</code></td><td>截取数组片段</td><td>否</td></tr><tr><td><code>concat()</code></td><td>合并数组</td><td>否</td></tr><tr><td><code>join()</code></td><td>将数组连接成字符串</td><td>否</td></tr><tr><td><code>reverse()</code></td><td>反转数组</td><td>是</td></tr><tr><td><code>sort()</code></td><td>对数组排序</td><td>是</td></tr><tr><td><code>flat()</code></td><td>展平嵌套数组</td><td>否</td></tr></tbody></table><p>slice()方法：slice()方法用于得到子数组，slice(a, b)截取的子数组从下标为a的项开始，到下标为 b（但不包括下标为b的项）结束</p><ul>
<li>
<p>标准写法</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>'A'</span><span>,</span><span>'B'</span><span>,</span><span>'C'</span><span>,</span><span>'D'</span><span>,</span><span>'E'</span><span>,</span><span>'F'</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>slice</span><span>(</span><span>1</span><span>, </span><span>4</span><span>);</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>); </span></span><span>// ['B','C','D'] 从下标 1 开始；（B）到下标 4 结束（不包含4）所以是：B、C、D</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>);    </span></span><span>// ['A','B','C','D','E','F']</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>slice()如果不提供第二个参数，则表示从指定项开始，提 取所有后续所有项作为子数组</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>'A'</span><span>,</span><span>'B'</span><span>,</span><span>'C'</span><span>,</span><span>'D'</span><span>,</span><span>'E'</span><span>,</span><span>'F'</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>slice</span><span>(</span><span>2</span><span>);</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>); </span></span><span>// ['C','D','E','F']</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>slice(a, b)方法不会更改原有数组，返回的是截取的数组</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>slice</span><span>(</span><span>1</span><span>, </span><span>3</span><span>);</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>); </span></span><span>// [2, 3]</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>);    </span></span><span>// [1, 2, 3, 4]  ✔ 原数组不变</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>slice()方法的参数允许为负数，表示数组的倒数第几项</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>'A'</span><span>,</span><span>'B'</span><span>,</span><span>'C'</span><span>,</span><span>'D'</span><span>,</span><span>'E'</span><span>,</span><span>'F'</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>slice</span><span>(</span><span>-</span><span>3</span><span>);</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>); </span></span><span>// ['D','E','F']</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p>concat()方法</p><ul>
<li>
<p>concat()方法可以合并连结多个数组</p>
</li>
<li>
<p>concat()方法不会改变原数组</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr1</span><span> </span></span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>];</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>arr2</span><span> </span></span><span>=</span><span> [</span><span>5</span><span>, </span><span>6</span><span>, </span><span>7</span><span>, </span><span>8</span><span>];</span></div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>arr3</span><span> </span></span><span>=</span><span> [</span><span>9</span><span>, </span><span>10</span><span>, </span><span>11</span><span>];</span></div></div><div><div><div>4</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span><span> </span><span>arr1</span><span>.</span></span><span>concat</span><span><span>(</span><span>arr2</span><span> , </span><span>arr3</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>);</span></span></div></div><div><div><div>6</div></div><div><span>// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p>join()方法</p><ul>
<li>
<p><strong>数组的join()方法</strong>可以使数组转为字符串；<strong>字符串的split() 方法</strong>可以使字符串转为数组。</p>
</li>
<li>
<p>join()的参数表示以什么字符作为连接符，如果留空则默 认以逗号分隔，如同调用toString()方法</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>'A'</span><span>, </span><span>'B'</span><span>, </span><span>'C'</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>str</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>join</span><span>(</span><span>'-'</span><span>);</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>str</span><span>); </span></span><span>// "A-B-C"</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>split()的参数表示以什么字符拆分字符串，一般不能留空</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>str</span><span> </span></span><span>=</span><span> </span><span>"A-B-C"</span><span>;</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span><span> </span><span>str</span><span>.</span></span><span>split</span><span>(</span><span>'-'</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// ["A", "B", "C"]</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p>reverse()方法</p><ul>
<li>
<p>reverse()方法用来将一个数组中的全部项顺序置反</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>"A"</span><span>,</span><span>"B"</span><span>,</span><span>"C"</span><span>,</span><span>"D"</span><span>];</span></div></div><div><div><div>2</div></div><div><span><span>arr</span><span>.</span></span><span>reverse</span><span>();</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// ["D","C","B","A"]</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102502vuejs-chu-shi/</id>
      <title type="text">Vue.js初识</title>
      <published>2026-10-25T07:58:27.000Z</published>
      <updated>2026-10-25T07:58:27.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102502vuejs-chu-shi/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102501sass-ji-chu-yu-fa/</id>
      <title type="text">sass基础语法</title>
      <published>2026-10-25T06:57:41.000Z</published>
      <updated>2026-10-25T06:57:41.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102501sass-ji-chu-yu-fa/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>Sass 是一种 CSS 预处理器，在 CSS 基础上提供了变量、嵌套、模块化、Mixin（混入）、运算和条件判断等功能，能够提高 CSS 的开发效率与可维护性。Sass 代码需要经过编译，最终转换为浏览器能够识别的普通 CSS。</p>
<section><h1>Sass 环境搭建<a href="#sass-环境搭建"><span>#</span></a></h1><section><h2>Sass 与 SCSS 的区别<a href="#sass-与-scss-的区别"><span>#</span></a></h2><p>Sass 提供两种语法格式：推荐使用 SCSS，因为它与普通 CSS 的语法基本一致。</p>

<table><thead><tr><th>对比</th><th>SCSS</th><th>Sass</th></tr></thead><tbody><tr><td>文件后缀</td><td><code>.scss</code></td><td><code>.sass</code></td></tr><tr><td>大括号 <code>{}</code></td><td>需要</td><td>不需要</td></tr><tr><td>分号 <code>;</code></td><td>需要</td><td>不需要</td></tr><tr><td>CSS 语法兼容性</td><td>兼容 CSS</td><td>使用缩进语法</td></tr><tr><td>推荐程度</td><td>推荐</td><td>较少使用</td></tr></tbody></table></section><section><h2>安装 Sass<a href="#安装-sass"><span>#</span></a></h2><p>首先需要安装 Node.js，然后通过 npm 安装 Sass。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>npm install -d sass</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>编译 SCSS 文件<a href="#编译-scss-文件"><span>#</span></a></h2><p>创建两个文件：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>project/</span></div></div><div><div><div>2</div></div><div><span>├── index.html</span></div></div><div><div><div>3</div></div><div><span>├── style.scss</span></div></div><div><div><div>4</div></div><div><span>└── style.css</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>编写 <code>style.scss</code>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>$primary-color</span><span>: </span></span><span>#</span><span>409eff</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>width: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>height: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>background-color: </span><span>$primary-color</span><span>;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>执行编译：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>npx sass style.scss style.css</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>生成的 <code>style.css</code>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>height: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>background-color: </span><span>#</span><span>409eff</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>在 HTML 中引入：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>link</span><span> </span><span>rel</span><span>=</span><span>"stylesheet"</span><span> </span><span>href</span><span>=</span><span>"./style.css"</span><span> /&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>浏览器只能直接使用编译后的 CSS。</p></section><section><h2>自动监听文件变化<a href="#自动监听文件变化"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>npx sass --watch style.scss:style.css</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>修改 SCSS 文件后，Sass 会自动重新编译 CSS。</p><p>如果需要监听整个目录：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>npx sass --watch scss:css</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>将 <code>scss</code> 目录中的样式编译到 <code>css</code> 目录。</p></section></section>
<section><h1>基本语法<a href="#基本语法"><span>#</span></a></h1><section><h2>注释<a href="#注释"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 单行注释，不会输出到 CSS</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>/* 多行注释，通常会输出到非压缩 CSS */</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>基本嵌套<a href="#基本嵌套"><span>#</span></a></h2><p>普通 CSS：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.nav</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background: </span><span>#</span><span>333</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>.nav</span><span> </span><span>a</span><span> {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>color: </span><span>white</span><span>;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div><span>.nav</span><span> </span><span>a</span><span>:hover</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>color: </span><span>red</span><span>;</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>SCSS：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.nav</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background: </span><span>#</span><span>333</span><span>;</span></div></div><div><div><div>3</div></div><div><span>  </span><span>a</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>color: </span><span>white</span><span>;</span></div></div><div><div><div>5</div></div><div><span>    </span><span>&amp;</span><span>:hover</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>      </span></span><span>color: </span><span>red</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其中 <code>&amp;</code> 表示当前嵌套规则的父选择器。</p></section><section><h2>父选择器 <code>&amp;</code><a href="#父选择器-"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.button</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>color: </span><span>#</span><span>333</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>  </span><span>&amp;</span><span>:hover</span><span> {</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>color: </span><span>red</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>  </span><span>&amp;</span><span>.active</span><span> {</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>color: </span><span>blue</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>  </span><span>&amp;--primary</span><span> {</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>background: </span><span>#</span><span>409eff</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>  </span><span>.icon</span><span> {</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>width: </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>19</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>编译后的选择器：</p>

<table><thead><tr><th>SCSS</th><th>CSS</th></tr></thead><tbody><tr><td><code>&amp;:hover</code></td><td><code>.button:hover</code></td></tr><tr><td><code>&amp;.active</code></td><td><code>.button.active</code></td></tr><tr><td><code>&amp;--primary</code></td><td><code>.button--primary</code></td></tr><tr><td><code>.icon</code></td><td><code>.button .icon</code></td></tr></tbody></table></section><section><h2>属性嵌套<a href="#属性嵌套"><span>#</span></a></h2><p>SCSS 还支持对具有相同前缀的 CSS 属性进行嵌套。实际开发中，普通属性写法通常更直观，按需使用即可。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>font</span><span>: {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>size: </span><span><span>16</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>weight: </span><span>bold</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>family: </span><span>Arial</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>margin: {</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>top: </span><span><span>10</span><span>px</span></span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>bottom: </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>编译后：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>16</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>font-weight: </span><span>bold</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>font-family: </span><span>Arial</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>margin-top: </span><span><span>10</span><span>px</span></span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>margin-bottom: </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>变量入门<a href="#变量入门"><span>#</span></a></h2></section><section><h2>定义与使用变量<a href="#定义与使用变量"><span>#</span></a></h2><p>Sass 使用 <code>$</code> 定义变量。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>$primary-color</span><span>: </span></span><span>#</span><span>409eff</span><span>;</span></div></div><div><div><div>2</div></div><div><span><span>$font-size</span><span>: </span></span><span><span>16</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>$border-radius</span><span>: </span></span><span><span>8</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>.button</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>background: </span><span>$primary-color</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>font-size: </span><span>$font-size</span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>border-radius: </span><span>$border-radius</span><span>;</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>编译后：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.button</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background: </span><span>#</span><span>409eff</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>16</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>border-radius: </span><span><span>8</span><span>px</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>变量适合统一管理项目中的颜色、字体大小、间距和圆角等属性。</p></section><section><h2>变量作用域<a href="#变量作用域"><span>#</span></a></h2><p>局部变量通常只在当前作用域内有效。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>$color</span><span>: </span></span><span>red</span><span>; </span><span>// 全局变量</span></div></div><div><div><div>2</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>$color</span><span>: </span><span>blue</span><span>; </span><span>// 局部变量</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>color: </span><span>$color</span><span>;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div><span>.title</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>color: </span><span>$color</span><span>;</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>编译后：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>color: </span><span>blue</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>.title</span><span> {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>color: </span><span>red</span><span>;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>变量运算<a href="#变量运算"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>$width</span><span>: </span></span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>2</div></div><div><span><span>$gap</span><span>: </span></span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>width: </span><span>$width</span><span><span> </span><span>+</span><span> </span></span><span>$gap</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>padding: </span><span>$gap</span><span><span> </span><span>*</span><span> </span></span><span>2</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>margin: </span><span>$gap</span><span><span> </span><span>-</span><span> </span></span><span><span>5</span><span>px</span></span><span>;</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>编译后：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>220</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>padding: </span><span><span>40</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>margin: </span><span><span>15</span><span>px</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>Sass 变量与 CSS 变量<a href="#sass-变量与-css-变量"><span>#</span></a></h2>

<table><thead><tr><th>对比</th><th>Sass 变量</th><th>CSS 变量</th></tr></thead><tbody><tr><td>声明</td><td><code>$color: red;</code></td><td><code>--color: red;</code></td></tr><tr><td>使用</td><td><code>$color</code></td><td><code>var(--color)</code></td></tr><tr><td>生效阶段</td><td>编译时</td><td>浏览器运行时</td></tr><tr><td>JS 动态修改</td><td>不支持直接修改</td><td>支持</td></tr><tr><td>主要用途</td><td>样式复用、编译配置</td><td>动态主题、实时样式变化</td></tr></tbody></table></section></section>
<section><h1>嵌套，代码拆分及引入<a href="#嵌套代码拆分及引入"><span>#</span></a></h1><p>当项目样式较多时，可以将 SCSS 拆分为多个文件，按照功能管理。</p><section><h2>文件拆分<a href="#文件拆分"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>project/</span></div></div><div><div><div>2</div></div><div><span>├── index</span><span>.html</span></div></div><div><div><div>3</div></div><div><span>├── scss/</span></div></div><div><div><div>4</div></div><div><span>│   ├── _variables</span><span>.scss</span></div></div><div><div><div>5</div></div><div><span>│   ├── _mixins</span><span>.scss</span></div></div><div><div><div>6</div></div><div><span>│   ├── _reset</span><span>.scss</span></div></div><div><div><div>7</div></div><div><span>│   ├── _index</span><span>.scss</span></div></div><div><div><div>8</div></div><div><span>│   └── </span><span>main</span><span>.scss</span></div></div><div><div><div>9</div></div><div><span>└── css/</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>└── </span><span>main</span><span>.css</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>以 <code>_</code> 开头的 SCSS 文件称为 Partial（局部文件），一般作为模块供其他文件加载，不单独编译成 CSS。</p></section><section><h2>@use 加载模块<a href="#use-加载模块"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>_variables</span><span>.scss</span></div></div><div><div><div>2</div></div><div><span><span>$primary-color</span><span>: </span></span><span>#</span><span>409eff</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>$font-size</span><span>: </span></span><span><span>16</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span>main</span><span>.scss</span></div></div><div><div><div>5</div></div><div><span>@use</span><span> </span><span>"variables"</span><span>;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>color: </span><span>variables</span><span>.</span><span>$primary-color</span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>font-size: </span><span>variables</span><span>.</span><span>$font-size</span><span>;</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>可以使用 <code>as</code> 定义别名：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@use</span><span> </span><span>"variables"</span><span> </span><span>as</span><span> </span><span>v</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>color: </span><span>v</span><span>.</span><span>$primary-color</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>也可以使用 <code>as *</code>，省略命名空间：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@use</span><span> </span><span>"variables"</span><span> </span><span>as</span><span> </span><span>*</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>color: </span><span>$primary-color</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>实际开发中推荐保留命名空间，避免不同模块之间出现命名冲突。</p></section><section><h2>@forward 转发模块<a href="#forward-转发模块"><span>#</span></a></h2><p>假设存在两个模块：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>_variables</span><span>.scss</span></div></div><div><div><div>2</div></div><div><span><span>$primary-color</span><span>: </span></span><span>#</span><span>409eff</span><span>;</span></div></div><div><div><div>3</div></div><div><span>_mixins</span><span>.scss</span></div></div><div><div><div>4</div></div><div><span>@mixin</span><span> </span><span>flex-center</span><span> {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>justify-content: </span><span>center</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>align-items: </span><span>center</span><span>;</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>可以通过 <code>_index.scss</code> 统一转发：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@forward</span><span> </span><span>"variables"</span><span>;</span></div></div><div><div><div>2</div></div><div><span>@forward</span><span> </span><span>"mixins"</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>然后在 <code>main.scss</code> 中使用：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@use</span><span> </span><span>"index"</span><span> </span><span>as</span><span> </span><span>s</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>color: </span><span>s</span><span>.</span><span>$primary-color</span><span>;</span></div></div><div><div><div>5</div></div><div><span>  </span><span>@include</span><span> </span><span>s</span><span>.</span><span>flex-center</span><span>;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>@use、@forward 和 @import 的区别<a href="#useforward-和-import-的区别"><span>#</span></a></h2>

<table><thead><tr><th>指令</th><th>功能</th><th>推荐情况</th></tr></thead><tbody><tr><td><code>@use</code></td><td>加载模块并使用其成员</td><td>推荐</td></tr><tr><td><code>@forward</code></td><td>转发模块的公共成员</td><td>推荐</td></tr><tr><td><code>@import</code></td><td>旧式模块导入方式</td><td>已废弃</td></tr></tbody></table><p>新项目应当使用 <code>@use</code> 和 <code>@forward</code> 管理 SCSS 模块。</p></section></section>
<section><h1>Mixin混入的使用<a href="#mixin混入的使用"><span>#</span></a></h1><p>Mixin 用于定义可以重复使用的样式代码块，类似于函数，可以传递参数。</p><section><h2>定义和调用 Mixin<a href="#定义和调用-mixin"><span>#</span></a></h2><p>使用 <code>@mixin</code> 定义，使用 <code>@include</code> 调用。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@mixin</span><span> </span><span>flex-center</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>justify-content: </span><span>center</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>align-items: </span><span>center</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>8</div></div><div><span>  </span><span>@include</span><span> </span><span>flex-center</span><span>;</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>12</div></div><div><span>  </span><span>@include</span><span> </span><span>flex-center</span><span>;</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>编译后：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>justify-content: </span><span>center</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>align-items: </span><span>center</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>justify-content: </span><span>center</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>align-items: </span><span>center</span><span>;</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>带参数的 Mixin<a href="#带参数的-mixin"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@mixin</span><span> </span><span>flex-center</span><span>(</span><span>$gap</span><span>) {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>justify-content: </span><span>center</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>align-items: </span><span>center</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>gap: </span><span>$gap</span><span>;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>9</div></div><div><span>  </span><span>@include</span><span> </span><span>flex-center</span><span>(</span><span><span>10</span><span>px</span></span><span>);</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>13</div></div><div><span>  </span><span>@include</span><span> </span><span>flex-center</span><span>(</span><span><span>20</span><span>px</span></span><span>);</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>默认参数<a href="#默认参数"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@mixin</span><span> </span><span>box-style</span><span>(</span></div></div><div><div><div>2</div></div><div><span>  </span><span><span>$color</span><span>:</span></span><span> </span><span>#</span><span>409eff</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span><span>$radius</span><span>:</span></span><span> </span><span><span>8</span><span>px</span></span></div></div><div><div><div>4</div></div><div><span>) {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>background: </span><span>$color</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>border-radius: </span><span>$radius</span><span>;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>.box1</span><span> {</span></div></div><div><div><div>10</div></div><div><span>  </span><span>@include</span><span> </span><span>box-style</span><span>;</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>.box2</span><span> {</span></div></div><div><div><div>14</div></div><div><span>  </span><span>@include</span><span> </span><span>box-style</span><span>(</span><span>red</span><span>, </span><span><span>12</span><span>px</span></span><span>);</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>也可以通过参数名指定传参：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box3</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>@include</span><span> </span><span>box-style</span><span>(</span><span>$radius</span><span>: </span><span><span>20</span><span>px</span></span><span>);</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>@content 插入样式代码块<a href="#content-插入样式代码块"><span>#</span></a></h2><p><code>@content</code> 是 Mixin 中的重要语法，表示接收并插入调用时传入的样式代码块。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@mixin</span><span> </span><span>hover</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>&amp;</span><span>:hover</span><span> {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>@content</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>.button</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>color: </span><span>#</span><span>333</span><span>;</span></div></div><div><div><div>9</div></div><div><span>  </span><span>@include</span><span> </span><span>hover</span><span> {</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>color: </span><span>red</span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>background: </span><span>#</span><span>eee</span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>编译后：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.button</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>color: </span><span>#</span><span>333</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>.button</span><span>:hover</span></span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>color: </span><span>red</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>background: </span><span>#</span><span>eee</span><span>;</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>@content</code> 常用于封装媒体查询、伪类等需要传入不同样式的场景。</p></section></section>
<section><h1>媒体查询与Mixin 的配合使用<a href="#媒体查询与mixin-的配合使用"><span>#</span></a></h1><p>使用 Mixin 可以将媒体查询中的断点统一封装，避免在多个地方重复编写断点。</p><section><h2>普通媒体查询<a href="#普通媒体查询"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>padding: </span><span><span>10</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>  </span><span>@media</span><span> (min-width: </span><span><span>768</span><span>px</span></span><span>) {</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>padding: </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>  </span><span>@media</span><span> (min-width: </span><span><span>1200</span><span>px</span></span><span>) {</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>padding: </span><span><span>30</span><span>px</span></span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这种写法可以直接使用，但当项目中的媒体查询较多时，可以使用 Mixin 统一管理。</p></section><section><h2>封装媒体查询 Mixin<a href="#封装媒体查询-mixin"><span>#</span></a></h2><div><figure><figcaption><span>_mixins.scss</span></figcaption><pre><code><div><div><div>1</div></div><div><span>@mixin</span><span> </span><span>respond</span><span>(</span><span>$device</span><span>) {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>@if</span><span> </span><span>$device</span><span><span> </span><span>==</span><span> tablet {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>@media</span><span> (min-width: </span><span><span>768</span><span>px</span></span><span>) {</span></div></div><div><div><div>4</div></div><div><span>      </span><span>@content</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>} </span><span>@else if</span><span> </span><span>$device</span><span><span> </span><span>==</span><span> desktop {</span></span></div></div><div><div><div>7</div></div><div><span>    </span><span>@media</span><span> (min-width: </span><span><span>1200</span><span>px</span></span><span>) {</span></div></div><div><div><div>8</div></div><div><span>      </span><span>@content</span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>核心语法：</p>

<table><thead><tr><th>语法</th><th>功能</th></tr></thead><tbody><tr><td><code>@mixin</code></td><td>定义混入</td></tr><tr><td><code>@include</code></td><td>调用混入</td></tr><tr><td><code>@if</code></td><td>条件判断</td></tr><tr><td><code>@else if</code></td><td>多条件判断</td></tr><tr><td><code>@content</code></td><td>插入调用时传入的样式</td></tr></tbody></table></section><section><h2>使用媒体查询 Mixin<a href="#使用媒体查询-mixin"><span>#</span></a></h2><div><figure><figcaption><span>main.scss</span></figcaption><pre><code><div><div><div>1</div></div><div><span>@use</span><span> </span><span>"mixins"</span><span> </span><span>as</span><span> </span><span>m</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>padding: </span><span><span>10</span><span>px</span></span><span>;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>  </span><span>@include</span><span> </span><span>m</span><span>.</span><span>respond</span><span>(tablet) {</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>padding: </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>  </span><span>@include</span><span> </span><span>m</span><span>.</span><span>respond</span><span>(desktop) {</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>padding: </span><span><span>30</span><span>px</span></span><span>;</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>编译后：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>padding: </span><span><span>10</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>@media</span><span> (min-width: </span><span><span>768</span><span>px</span></span><span>) {</span></div></div><div><div><div>7</div></div><div><span>  </span><span>.container</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>padding: </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>@media</span><span> (min-width: </span><span><span>1200</span><span>px</span></span><span>) {</span></div></div><div><div><div>13</div></div><div><span>  </span><span>.container</span><span> {</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>padding: </span><span><span>30</span><span>px</span></span><span>;</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>16</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h2>实际案例：响应式网格布局<a href="#实际案例响应式网格布局"><span>#</span></a></h2><p>HTML：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> class="card-list"&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> class="card"&gt;卡片1&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> class="card"&gt;卡片2&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> class="card"&gt;卡片3&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> class="card"&gt;卡片4&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>SCSS：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@use</span><span> </span><span>"mixins"</span><span> </span><span>as</span><span> </span><span>m</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>.card-list</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>display: </span><span>grid</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>grid-template-columns: </span><span><span>1</span><span>fr</span></span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>gap: </span><span><span>16</span><span>px</span></span><span>;</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>  </span><span>// 平板：两列</span></div></div><div><div><div>9</div></div><div><span>  </span><span>@include</span><span> </span><span>m</span><span>.</span><span>respond</span><span>(tablet) {</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>grid-template-columns: </span><span>repeat</span><span>(</span><span>2</span><span>, </span><span><span>1</span><span>fr</span></span><span>);</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>  </span><span>// 桌面：四列</span></div></div><div><div><div>14</div></div><div><span>  </span><span>@include</span><span> </span><span>m</span><span>.</span><span>respond</span><span>(desktop) {</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>grid-template-columns: </span><span>repeat</span><span>(</span><span>4</span><span>, </span><span><span>1</span><span>fr</span></span><span>);</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>17</div></div><div><span>}</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>.card</span><span> {</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>padding: </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>21</div></div><div><span><span>  </span></span><span>color: </span><span>white</span><span>;</span></div></div><div><div><div>22</div></div><div><span><span>  </span></span><span>background: </span><span>#</span><span>409eff</span><span>;</span></div></div><div><div><div>23</div></div><div><span><span>  </span></span><span>border-radius: </span><span><span>8</span><span>px</span></span><span>;</span></div></div><div><div><div>24</div></div><div><span><span>  </span></span><span>text-align: </span><span>center</span><span>;</span></div></div><div><div><div>25</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102305-wei-xin-xiao-cheng-xu-chang-yong-api/</id>
      <title type="text">微信小程序常用Api</title>
      <published>2026-10-23T13:12:56.000Z</published>
      <updated>2026-10-23T13:12:56.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102305-wei-xin-xiao-cheng-xu-chang-yong-api/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>本文学习微信小程序的常用API，内容整体分为配置、逻辑、样式、结构4个部分，也可以分为全局和页面级别</p>
<section><h1>目录结构<a href="#目录结构"><span>#</span></a></h1><p>小程序项目可以分为两个级别：全局和页面级别，全局可以配置小程序整体信息，页面级别主要由配置、逻辑、样式、结构4个部分组成，详细：<a href="https://developers.weixin.qq.com/miniprogram/dev/framework/structure.html" target="_blank">官方文档</a></p></section>
<section><h1>全局配置文件<a href="#全局配置文件"><span>#</span></a></h1><p>使用全局配置制作菜单栏</p><p><code>app.json</code></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>  </span><span>"tabBar"</span><span>: {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>"list"</span><span>: [{</span></div></div><div><div><div>3</div></div><div><span>      </span><span>"pagePath"</span><span>: </span><span>"pages/index/index"</span><span>,</span></div></div><div><div><div>4</div></div><div><span>      </span><span>"text"</span><span>: </span><span>"首页"</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>}, {</span></div></div><div><div><div>6</div></div><div><span>      </span><span>"pagePath"</span><span>: </span><span>"pages/logs/logs"</span><span>,</span></div></div><div><div><div>7</div></div><div><span>      </span><span>"text"</span><span>: </span><span>"日志"</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>}]</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>},</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>详细的全局配置文件：<a href="https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html" target="_blank">官方文档</a>，总体的配置也很简单，文档可以这样看，配置项就是整体可以配置的内容，可以配置什么功能，常用的有entryPagePath、pages、window、tabBar和networkTimeout，下面的就是对配置项的详细描述</p></section>
<section><h1>页面级别配置文件<a href="#页面级别配置文件"><span>#</span></a></h1><p>每一个小程序页面也可以使用同名 <code>.json</code> 文件来对本页面的窗口表现进行配置，页面中配置项会覆盖 <code>app.json</code> 的 <code>window</code> 中相同的配置项。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>{</span></div></div><div><div><div>2</div></div><div><span>  </span><span>"navigationBarBackgroundColor"</span><span>: </span><span>"#ffffff"</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>"navigationBarTextStyle"</span><span>: </span><span>"black"</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>"navigationBarTitleText"</span><span>: </span><span>"微信接口功能演示"</span><span>,</span></div></div><div><div><div>5</div></div><div><span>  </span><span>"backgroundColor"</span><span>: </span><span>"#eeeeee"</span><span>,</span></div></div><div><div><div>6</div></div><div><span>  </span><span>"backgroundTextStyle"</span><span>: </span><span>"light"</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>完整配置项说明请参考 <a href="https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/page" target="_blank">小程序页面配置</a> 。</p></section>
<section><h1>全局逻辑中的生命周期函数<a href="#全局逻辑中的生命周期函数"><span>#</span></a></h1><p>关于全局逻辑中的生命周期函数可以参考文档，除了生命周期函数的说明外，文档也列举了一些推荐和不推荐写法，如现在并不推荐使用 <code>App()</code> 中的参数，而是使用对应的 <code>wx</code> 调用来代替。  <a href="https://developers.weixin.qq.com/miniprogram/dev/reference/api/App.html#onLaunch-Object-object" target="_blank">文档地址</a></p><p>onLaunch：小程序启动的时候自动执行，带一个参数；小程序初始化完成时触发，全局只触发一次。这里需要注意，如果短时间内多次打开是执行一次，如果长时间再打开，这时候onLaunch就会重新执行一次</p><div><figure><figcaption><span>app.js</span></figcaption><pre><code><div><div><div>1</div></div><div><span>App</span><span>({</span></div></div><div><div><div>2</div></div><div><span>  </span><span>onLaunch</span><span><span>(</span><span>options</span><span>){</span></span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'onLaunch'</span><span><span>,</span><span>options</span><span>);</span></span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>})</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>参数值可以参考：<a href="https://developers.weixin.qq.com/miniprogram/dev/api/base/app/life-cycle/wx.getLaunchOptionsSync.html" target="_blank">官方文档</a>，也可以使用 <a href="https://developers.weixin.qq.com/miniprogram/dev/api/base/app/life-cycle/wx.getLaunchOptionsSync.html" target="_blank">wx.getLaunchOptionsSync</a> 获取</p><p>onShow：小程序启动，或从后台进入前台显示时触发。一样也会带一个参数，onShow只要是退出重新进入小程序都会执行的一个函数，无论时间间隔的长短，这是与onLaunch区别，注意：onShow是onLaunch后的一个函数，也就是onLaunch是先执行，后才执行onShow</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span> </span><span>onShow</span><span><span>(</span><span>options</span><span>){</span></span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'onShow'</span><span><span>,</span><span>options</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>},</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>参数值可以参考：<a href="https://developers.weixin.qq.com/miniprogram/dev/api/base/app/app-event/wx.onAppShow.html" target="_blank">官方文档</a>，也可以使用 <a href="https://developers.weixin.qq.com/miniprogram/dev/api/base/app/app-event/wx.onAppShow.html" target="_blank">wx.onAppShow</a> 获取</p><p>onHide：小程序从前台进入后台时触发。一样也有一个参数，这个参数可以了解用户退出后的去向，可以和onShow配对理解。一个显示一个退出</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span> </span><span>onHide</span><span><span>(</span><span>options</span><span>){</span></span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'onHide'</span><span><span>,</span><span>options</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span><span> </span></span><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>onError：小程序发生脚本错误或 API 调用报错时触发。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 不推荐的写法</span></div></div><div><div><div>2</div></div><div><span>App</span><span>({</span></div></div><div><div><div>3</div></div><div><span>  </span><span>onLaunch</span><span><span>(</span><span>options</span><span>) {</span></span></div></div><div><div><div>4</div></div><div><span>    </span><span>// 在启动时执行</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>6</div></div><div><span>  </span><span>onError</span><span><span>(</span><span>msg</span><span>) {</span></span></div></div><div><div><div>7</div></div><div><span>    </span><span>// 发生脚本错误时执行</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>msg</span><span>)</span></span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>10</div></div><div><span>})</span></div></div><div><div><div>11</div></div><div><span>// 推荐的写法</span></div></div><div><div><div>12</div></div><div><span>App</span><span>()</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span><span>wx</span><span>.</span></span><span>onError</span><span>(</span><span>function</span><span> () {</span></div></div><div><div><div>15</div></div><div><span>  </span><span>// 发生脚本错误时执行</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>msg</span><span>)</span></span></div></div><div><div><div>17</div></div><div><span>})</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>// 在启动时执行</span></div></div><div><div><div>20</div></div><div><span>var</span><span><span> </span><span>options</span><span> </span></span><span>=</span><span><span> </span><span>wx</span><span>.</span></span><span>getLaunchOptionsSync</span><span>()</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>推荐写法中，原来放在 <code>onLaunch()</code> 里的初始化代码，可以直接放在 <code>app.js</code> 顶层执行，也可以封装成初始化函数后主动调用。</p><div><div><div><figure><figcaption><span>app.js</span><span>展开</span><span>收起</span></figcaption><pre><code><div><div><div>1</div></div><div><span>App</span><span>();</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>// 监听全局错误</span></div></div><div><div><div>4</div></div><div><span><span>wx</span><span>.</span></span><span>onError</span><span><span>((</span><span>msg</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'全局错误：'</span><span><span>, </span><span>msg</span><span>);</span></span></div></div><div><div><div>6</div></div><div><span>});</span></div></div><div><div><div>7</div></div><div><span>// 获取启动参数</span></div></div><div><div><div>8</div></div><div><span>const</span><span> </span><span>options</span><span> </span><span>=</span><span><span> </span><span>wx</span><span>.</span></span><span>getLaunchOptionsSync</span><span>();</span></div></div><div><div><div>9</div></div><div><span>// 初始化用户信息</span></div></div><div><div><div>10</div></div><div><span>function</span><span> </span><span>initUser</span><span>() {</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'初始化用户信息'</span><span>);</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div><span>// 封装启动逻辑</span></div></div><div><div><div>14</div></div><div><span>function</span><span> </span><span>initApp</span><span>() {</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'小程序启动了'</span><span>);</span></div></div><div><div><div>16</div></div><div><span>  </span><span>const</span><span> </span><span>token</span><span> </span><span>=</span><span><span> </span><span>wx</span><span>.</span></span><span>getStorageSync</span><span>(</span><span>'token'</span><span>);</span></div></div><div><div><div>17</div></div><div><span>  </span><span>initUser</span><span>();</span></div></div><div><div><div>18</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'启动参数'</span><span><span>, </span><span>options</span><span>);</span></span></div></div><div><div><div>19</div></div><div><span>}</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>// 主动执行初始化</span></div></div><div><div><div>22</div></div><div><span>initApp</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h1>全局方法及数据的定义及调用方式<a href="#全局方法及数据的定义及调用方式"><span>#</span></a></h1><p>全局的方法，怎么在页面级别的js中调用呢，小程序提供了一个getApp的接口，需要注意的是，这里的sayHello需要写在App内，也就是不能用推荐写法，当然现在这种写法也不推荐了，可以通过模块化来实现同样功能，<a href="https://developers.weixin.qq.com/miniprogram/dev/reference/api/getApp.html" target="_blank">文档地址</a></p><div><figure><figcaption><span>app.js</span></figcaption><pre><code><div><div><div>1</div></div><div><span>App</span><span>({</span></div></div><div><div><div>2</div></div><div><span>   </span><span>sayHello</span><span>(){</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'hello word'</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption><span>pages\index\index.js</span></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>app</span><span> </span><span>=</span><span> </span><span>getApp</span><span>()</span></div></div><div><div><div>2</div></div><div><span>Page</span><span>({</span></div></div><div><div><div>3</div></div><div><span>onLoad</span><span>(){</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>app</span><span>.</span><span>sayHello</span><span>()</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>})</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>页面级别的生命周期函数<a href="#页面级别的生命周期函数"><span>#</span></a></h1><p>在页面运行的某个时刻执行的函数，其实页面级别的生命周期函数和全局的差不多，只不过语义上有差别，页面级别有6个生命周期函数，具体可以参考文档：<a href="https://developers.weixin.qq.com/miniprogram/dev/reference/api/Page.html" target="_blank">官方文档</a></p><p>onLoad：页面加载时触发。一个页面只会调用一次，可以在 onLoad 的参数中获取打开当前页面路径中的参数。</p><p>onShow：页面显示/切入前台时触发。</p><p>onReady：页面初次渲染完成时触发。一个页面只会调用一次，代表页面已经准备妥当，可以和视图层进行交互</p><p>onHide：页面隐藏/切入后台时触发。 如 <a href="https://developers.weixin.qq.com/miniprogram/dev/api/navigate/wx.navigateToMiniProgram.html" target="_blank">wx.navigateTo</a> 或底部 <code>tab</code> 切换到其他页面，小程序切入后台等。</p><p>onUnload：页面卸载时触发。如<a href="https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.redirectTo.html" target="_blank">wx.redirectTo</a>或<a href="https://developers.weixin.qq.com/miniprogram/dev/api/navigate/wx.navigateBackMiniProgram.html" target="_blank">wx.navigateBack</a>到其他页面时</p><p>onRouteDone：路由动画完成时触发。如 <a href="https://developers.weixin.qq.com/miniprogram/dev/api/navigate/wx.navigateToMiniProgram.html" target="_blank">wx.navigateTo</a> 页面完全推入后 或 <a href="https://developers.weixin.qq.com/miniprogram/dev/api/navigate/wx.navigateBackMiniProgram.html" target="_blank">wx.navigateBack</a> 页面完全恢复时。</p><p>除了上面6个外，还有很多其他在特定操作下自动触发的函数，如下拉刷新、用户点击右上角转发，用户点击右上角转发到朋友圈等等</p></section>
<section><h1>页面逻辑层数据的定义及与页面的串联<a href="#页面逻辑层数据的定义及与页面的串联"><span>#</span></a></h1><p>事件的文档：<a href="https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html#%E4%BA%8B%E4%BB%B6%E7%9A%84%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F" target="_blank">官方文档</a></p><p>数据绑定：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Page</span><span>({</span></div></div><div><div><div>2</div></div><div><span>  </span><span>data</span><span>:</span><span>{</span></div></div><div><div><div>3</div></div><div><span>    </span><span>num</span><span>:</span><span>'1'</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>5</div></div><div><span>})</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>view</span><span>&gt;{{num}}&lt;/</span><span>view</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>点击事件：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>changename</span><span>(){</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'changename'</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>view</span><span> </span><span>class</span><span>=</span><span>"container"</span><span> </span><span>bind</span><span>:</span><span>tap</span><span>=</span><span>"changename"</span><span><span>&gt;</span><span>{</span><span>{</span><span>num</span><span>}</span><span>}</span><span>&lt;/</span></span><span>view</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>点击改变数据</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Page</span><span>({</span></div></div><div><div><div>2</div></div><div><span>  </span><span>data</span><span>:</span><span>{</span></div></div><div><div><div>3</div></div><div><span>    </span><span>num</span><span>:</span><span>'1'</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>5</div></div><div><span>  </span><span>changename</span><span>(){</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'changename'</span><span>);</span></div></div><div><div><div>7</div></div><div><span>   </span><span>this</span><span>.</span><span>setData</span><span>({</span></div></div><div><div><div>8</div></div><div><span>    </span><span>num</span><span>:</span><span>'2'</span></div></div><div><div><div>9</div></div><div><span><span>   </span></span><span>})</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>})</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>view</span><span> </span><span>class</span><span>=</span><span>"container"</span><span> </span><span>bind:tap</span><span>=</span><span>"changename"</span><span>&gt;{{num}}&lt;/</span><span>view</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>逻辑层中的 API<a href="#逻辑层中的-api"><span>#</span></a></h1><p>官方API文档：<a href="https://developers.weixin.qq.com/miniprogram/dev/api/" target="_blank">文档</a> api调用一般都是通过wx.调用的</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>wx</span><span>.</span></span><span>showModal</span><span>({</span></div></div><div><div><div>2</div></div><div><span>    </span><span>title</span><span>:</span><span> </span><span>'提示'</span><span>,</span></div></div><div><div><div>3</div></div><div><span>    </span><span>content</span><span>:</span><span> </span><span>'这是一个模态弹窗'</span><span>,</span></div></div><div><div><div>4</div></div><div><span>})</span></div></div><div><div><div>5</div></div><div><span><span>wx</span><span>.</span></span><span>request</span><span>({</span></div></div><div><div><div>6</div></div><div><span>    </span><span>url</span><span>:</span><span>'https://www.fastmock.site/mock/fdf9557ad5613aec6428d08d90f25b45/weixin/api/getDate'</span><span>,</span></div></div><div><div><div>7</div></div><div><span>    </span><span>success</span><span><span>(</span><span>res</span><span>){</span></span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>res</span><span>);</span></span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span>})</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>视图层的数据绑定<a href="#视图层的数据绑定"><span>#</span></a></h1><p>视图层包括WXML和WXSS，可以理解为HTML5和CSS3，只不过一些属性可能不支持；</p><p>在小程序没有DOM的概念，有组件的概念，view是最小的组件，可以理解为div</p><p>实现判断，点击显示隐藏功能：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>view</span><span> </span><span>class</span><span>=</span><span>"flex"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span> </span></span><span>&lt;</span><span>button</span><span>  </span><span>bind:tap</span><span>=</span><span>"changename"</span><span>&gt;{{msg}}&lt;/</span><span>button</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>view</span><span> </span><span>wx:if</span><span>=</span><span>"{{!show}}"</span><span>&gt;hello&lt;/</span><span>view</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>&lt;</span><span>view</span><span> </span><span>hidden</span><span>=</span><span>"{{show}}"</span><span>&gt;hidden&lt;/</span><span>view</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>&lt;</span><span>checkbox</span><span> </span><span>checked</span><span>=</span><span>"{{true}}"</span><span>&gt;选择框&lt;/</span><span>checkbox</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span>&lt;/</span><span>view</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Page</span><span>({</span></div></div><div><div><div>2</div></div><div><span>  </span><span>data</span><span>:</span><span>{</span></div></div><div><div><div>3</div></div><div><span>    </span><span>msg</span><span>:</span><span>'点击显示'</span><span>,</span></div></div><div><div><div>4</div></div><div><span>    </span><span>show</span><span>:</span><span>true</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>6</div></div><div><span>  </span><span>changename</span><span>(){</span></div></div><div><div><div>7</div></div><div><span>    </span><span>if</span><span>(</span><span>!</span><span>this</span><span>.</span><span>data</span><span>.</span><span>show</span><span>){</span></div></div><div><div><div>8</div></div><div><span>      </span><span>this</span><span>.</span><span>setData</span><span>({</span></div></div><div><div><div>9</div></div><div><span>        </span><span>msg</span><span>:</span><span>'点击显示'</span><span>,</span></div></div><div><div><div>10</div></div><div><span>        </span><span>show</span><span>:</span><span>true</span></div></div><div><div><div>11</div></div><div><span><span>         </span></span><span>})</span></div></div><div><div><div>12</div></div><div><span>         </span><span>return</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span> </span><span>this</span><span>.</span><span>setData</span><span>({</span></div></div><div><div><div>15</div></div><div><span>  </span><span>msg</span><span>:</span><span>'点击隐藏'</span><span>,</span></div></div><div><div><div>16</div></div><div><span>  </span><span>show</span><span>:</span><span>false</span></div></div><div><div><div>17</div></div><div><span><span>   </span></span><span>})</span></div></div><div><div><div>18</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>19</div></div><div><span>})</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.flex</span><span>{</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>flex-direction: </span><span>column</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>justify-content: </span><span>center</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>align-items: </span><span>center</span><span>;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>wx，但是hidden是隐藏的意思，true就是隐藏，这个和vue的逻辑是相反的</p></section>
<section><h1>视图层循环展示内容<a href="#视图层循环展示内容"><span>#</span></a></h1><p>循环语句</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>view</span><span> </span><span>class</span><span>=</span><span>"flex"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span> </span></span><span>&lt;</span><span>view</span><span> </span><span>wx:for</span><span>=</span><span>"{{list}}"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span> </span></span><span>{{item.title}}</span></div></div><div><div><div>4</div></div><div><span><span> </span></span><span>{{item.dec}}</span></div></div><div><div><div>5</div></div><div><span><span> </span></span><span>&lt;/</span><span>view</span><span>&gt;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>&lt;/</span><span>view</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Page</span><span>({</span></div></div><div><div><div>2</div></div><div><span>  </span><span>data</span><span>:</span><span>{</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>    </span><span>list</span><span>:</span><span>[</span></div></div><div><div><div>5</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>6</div></div><div><span>        </span><span>title</span><span>:</span><span>'我是标题1'</span><span>,</span></div></div><div><div><div>7</div></div><div><span>        </span><span>dec</span><span>:</span><span>'描述1'</span></div></div><div><div><div>8</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>9</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>10</div></div><div><span>        </span><span>title</span><span>:</span><span>'我是标题2'</span><span>,</span></div></div><div><div><div>11</div></div><div><span>        </span><span>dec</span><span>:</span><span>'描述2'</span></div></div><div><div><div>12</div></div><div><span><span>      </span></span><span>}, {</span></div></div><div><div><div>13</div></div><div><span>        </span><span>title</span><span>:</span><span>'我是标题3'</span><span>,</span></div></div><div><div><div>14</div></div><div><span>        </span><span>dec</span><span>:</span><span>'描述3'</span></div></div><div><div><div>15</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>]</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>18</div></div><div><span>})</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h1>视图层代码的拆分<a href="#视图层代码的拆分"><span>#</span></a></h1><p>这里是页面嵌入：include 不推荐</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>view</span><span> </span><span>class</span><span>=</span><span>"flex"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span> </span></span><span>&lt;</span><span>view</span><span>&gt;header&lt;/</span><span>view</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;</span><span>include</span><span> </span><span>src</span><span>=</span><span>"./content.wxml"</span><span> /&gt;</span></div></div><div><div><div>4</div></div><div><span>&lt;</span><span>view</span><span>&gt;footer&lt;/</span><span>view</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>&lt;/</span><span>view</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>view</span><span>&gt;content1&lt;/</span><span>view</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>view</span><span>&gt;{{content}}&lt;/</span><span>view</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>include其实就把页面嵌入到另外页面中，这里{{content}}也是可以正常使用index.js定义的数据的</p><p>引入其他文件中的子模板：<code>&lt;template&gt;</code> 和 <code>&lt;import&gt;</code> 推荐</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>view</span><span> </span><span>class</span><span>=</span><span>"flex"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span> </span></span><span>&lt;</span><span>view</span><span>&gt;header&lt;/</span><span>view</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;</span><span>import</span><span> </span><span>src</span><span>=</span><span>"./content.wxml"</span><span>/&gt;</span></div></div><div><div><div>4</div></div><div><span>&lt;</span><span>template</span><span> </span><span>is</span><span>=</span><span>"content"</span><span> </span><span>data</span><span>=</span><span>"{{ content }}"</span><span>/&gt;</span></div></div><div><div><div>5</div></div><div><span>&lt;</span><span>view</span><span>&gt;footer&lt;/</span><span>view</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span>&lt;/</span><span>view</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>template</span><span> </span><span>name</span><span>=</span><span>"content"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>view</span><span>&gt;content1&lt;/</span><span>view</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;</span><span>view</span><span>&gt;{{content}}&lt;/</span><span>view</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>&lt;/</span><span>template</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>组件&amp;样式<a href="#组件样式"><span>#</span></a></h1><p>页面是由一个一个组件组成的，对于一些样式基本相同的组件，就可以封装成一个组件，供其他页面使用文档地址：<a href="https://developers.weixin.qq.com/miniprogram/dev/framework/component-framework/" target="_blank">自定义组件</a></p><p>样式尺寸单位：</p><ul>
<li>布局：使用 <code>%</code>、<code>rpx</code>、<code>vw</code> 等相对单位，实现自适应。</li>
<li>字体：优先使用 <code>px</code>，保证字体大小稳定。</li>
<li>媒体查询：针对平板、PC 等大屏幕，适当调整字体大小和布局。</li>
<li>Flex / Grid：配合相对单位，实现更加灵活的响应式布局。</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102304html-he-css-he-js-zhong-de-xing-neng-you-hua/</id>
      <title type="text">HTML、CSS和JS中的性能优化</title>
      <published>2026-10-23T05:47:15.000Z</published>
      <updated>2026-10-23T05:47:15.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102304html-he-css-he-js-zhong-de-xing-neng-you-hua/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>图片优化<a href="#图片优化"><span>#</span></a></h1><p>图片通常是网页中体积较大的资源，优化图片可以减少网络传输量，提高页面加载速度。</p><section><h2>1. 选择合适的图片格式<a href="#1-选择合适的图片格式"><span>#</span></a></h2>

<table><thead><tr><th>格式</th><th>特点</th><th>适用场景</th></tr></thead><tbody><tr><td>JPEG / JPG</td><td>有损压缩，兼容性好</td><td>照片、复杂图片</td></tr><tr><td>PNG</td><td>支持透明，无损压缩</td><td>需要无损质量的图片</td></tr><tr><td>WebP</td><td>支持有损、无损压缩及透明</td><td>网页图片，推荐</td></tr><tr><td>AVIF</td><td>通常具有较高压缩效率</td><td>对体积要求较高的图片</td></tr><tr><td>SVG</td><td>矢量图，放大不失真</td><td>图标、Logo、简单图形</td></tr></tbody></table><p>推荐： 普通网页图片优先考虑 WebP、AVIF，图标和简单矢量图形考虑 SVG。</p></section><section><h2>2. 压缩图片体积<a href="#2-压缩图片体积"><span>#</span></a></h2><ul>
<li>使用图片压缩工具减少文件大小。</li>
<li>避免使用尺寸远大于实际显示区域的图片。</li>
<li>根据图片用途调整压缩质量。</li>
<li>使用响应式图片，为不同屏幕提供不同尺寸的资源。</li>
</ul><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;img</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>src="image-800.webp"</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>srcset="</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>image-400.webp 400w,</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>image-800.webp 800w,</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>image-1200.webp 1200w</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>"</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>sizes="(max-width: 600px) 100vw, 800px"</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>alt="示例图片"</span></div></div><div><div><div>10</div></div><div><span>/&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>浏览器会结合显示尺寸、设备像素密度等因素选择合适的图片。</p></section><section><h2>3. 其他图片优化手段<a href="#3-其他图片优化手段"><span>#</span></a></h2><ul>
<li>懒加载：非首屏图片滚动到附近时再加载。</li>
<li>预加载：提前获取首屏关键图片。</li>
<li>CDN：使用内容分发网络加速图片传输。</li>
<li>设置宽高：提前为图片预留空间，减少布局偏移。</li>
<li>CSS 替代图片：简单渐变、阴影、边框等效果可以直接用 CSS 实现。</li>
</ul><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;img</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>src="image.webp"</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>width="800"</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>height="450"</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>alt="示例图片"</span></div></div><div><div><div>6</div></div><div><span>/&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h1>动画优化<a href="#动画优化"><span>#</span></a></h1><p>动画优化的核心是：尽量减少布局计算和绘制开销，让动画保持流畅。</p><section><h2>1. 优先使用 transform 和 opacity<a href="#1-优先使用-transform-和-opacity"><span>#</span></a></h2><p>不同 CSS 属性对渲染性能的影响不同。</p>

<table><thead><tr><th>属性</th><th>可能触发的渲染工作</th><th>推荐程度</th></tr></thead><tbody><tr><td>width、height</td><td>布局、绘制、合成</td><td>尽量避免频繁动画</td></tr><tr><td>top、left</td><td>布局、绘制、合成</td><td>尽量避免频繁动画</td></tr><tr><td>background-color</td><td>绘制、合成</td><td>可以使用</td></tr><tr><td>transform</td><td>通常只需合成</td><td>推荐</td></tr><tr><td>opacity</td><td>通常只需合成</td><td>推荐</td></tr></tbody></table><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>transition: transform 0.3s ease;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>.box:hover {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>transform: translateX(100px);</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>相比不断修改 <code>left</code>，使用 <code>transform</code> 通常具有更好的动画性能。</p></section><section><h2>2. 使用 requestAnimationFrame<a href="#2-使用-requestanimationframe"><span>#</span></a></h2><p>需要通过 JavaScript 实现动画时，可以使用 <code>requestAnimationFrame()</code>。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const box = document.querySelector('.box');</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>let x = 0;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>function animate() {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>x += 1;</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>box.style.transform = `translateX(${x}px)`;</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>if (x &lt; 300) {</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>requestAnimationFrame(animate);</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>requestAnimationFrame(animate);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>其优势：</p><ul>
<li>让动画更新与浏览器绘制节奏协调。</li>
<li>页面处于后台时，通常会暂停回调。</li>
<li>避免使用固定 <code>setInterval</code> 频率造成不必要的动画更新。</li>
</ul></section><section><h2>3. 其他动画优化<a href="#3-其他动画优化"><span>#</span></a></h2><ul>
<li>避免同时执行大量复杂动画。</li>
<li>不要在动画循环中频繁交替读取、修改布局属性。</li>
<li>对复杂动画可适当使用 <code>will-change</code>，但不要滥用。</li>
<li>对持续动画优先考虑 CSS Animation 或 Web Animations API。</li>
<li>为需要减少动态效果的用户支持 <code>prefers-reduced-motion</code>。</li>
</ul></section></section>
<section><h1>CSS 优化<a href="#css-优化"><span>#</span></a></h1><p>CSS 优化主要是减少文件体积、降低样式计算和渲染成本。</p><section><h2>1. 精简 CSS 文件<a href="#1-精简-css-文件"><span>#</span></a></h2><ul>
<li>删除未使用的样式。</li>
<li>合并重复声明。</li>
<li>使用生产环境 CSS 压缩。</li>
<li>避免引入大量实际用不到的 CSS 框架样式。</li>
<li>将非关键页面的样式按需加载。</li>
</ul></section><section><h2>2. 合理使用 CSS 选择器<a href="#2-合理使用-css-选择器"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/* 不推荐：不必要的复杂嵌套 */</span></div></div><div><div><div>2</div></div><div><span>.container .content ul li a span {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>color: red;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>/* 推荐：通过 class 定位 */</span></div></div><div><div><div>7</div></div><div><span>.menu-title {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>color: red;</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>优先使用语义清晰的 class，减少不必要的深层选择器。</p><p>不过，现代浏览器已经对 CSS 选择器进行了大量优化，选择器复杂度通常不是主要性能瓶颈，不必为性能而刻意避免后代选择器等正常写法。</p></section><section><h2>3. 避免频繁触发布局计算<a href="#3-避免频繁触发布局计算"><span>#</span></a></h2><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 不推荐：反复读取布局，再修改尺寸</span></div></div><div><div><div>2</div></div><div><span>elements.forEach((element) =&gt; {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>const width = element.offsetWidth;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>element.style.width = `${width + 10}px`;</span></div></div><div><div><div>5</div></div><div><span>});</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>// 推荐：集中读取，再集中修改</span></div></div><div><div><div>8</div></div><div><span>const widths = elements.map((element) =&gt; element.offsetWidth);</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>elements.forEach((element, index) =&gt; {</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>element.style.width = `${widths[index] + 10}px`;</span></div></div><div><div><div>12</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这种做法可以减少浏览器被迫同步计算布局的情况。</p></section><section><h2>4. 其他 CSS 优化<a href="#4-其他-css-优化"><span>#</span></a></h2><ul>
<li>使用 CSS 变量统一管理重复的设计值。</li>
<li>对复杂、独立组件按需考虑 <code>contain</code>。</li>
<li>对较长的非首屏内容，可以考虑 <code>content-visibility: auto</code>。</li>
<li>动画尽量使用 <code>transform</code> 和 <code>opacity</code>。</li>
</ul></section></section>
<section><h1>DOM 优化<a href="#dom-优化"><span>#</span></a></h1><p>DOM 优化主要是减少不必要的节点创建、查询和修改操作。</p><section><h2>1. 减少 DOM 节点数量<a href="#1-减少-dom-节点数量"><span>#</span></a></h2><p>过多的 DOM 节点会增加浏览器的样式计算、布局和内存开销。</p><p>优化方式：</p><ul>
<li>避免无意义的多层标签嵌套。</li>
<li>对大量数据使用分页。</li>
<li>长列表可以使用虚拟列表。</li>
<li>不需要展示的内容尽量不提前生成大量 DOM。</li>
</ul></section><section><h2>2. 批量操作 DOM<a href="#2-批量操作-dom"><span>#</span></a></h2><p>使用 <code>DocumentFragment</code> 可以先组织节点，再一次性插入页面。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const ul = document.querySelector('ul');</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>const fragment = document.createDocumentFragment();</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>for (let i = 0; i &lt; 1000; i++) {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>const li = document.createElement('li');</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>li.textContent = `第 ${i} 项`;</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>fragment.appendChild(li);</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>ul.appendChild(fragment);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>相比每创建一个元素就插入页面，这样可以减少对已连接 DOM 的重复操作。</p></section><section><h2>3. 减少重复查询 DOM<a href="#3-减少重复查询-dom"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 不推荐：反复查询相同元素</span></div></div><div><div><div>2</div></div><div><span>for (let i = 0; i &lt; 100; i++) {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>document.querySelector('.box').textContent = i;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// 推荐：缓存 DOM 引用</span></div></div><div><div><div>7</div></div><div><span>const box = document.querySelector('.box');</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>for (let i = 0; i &lt; 100; i++) {</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>box.textContent = i;</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果不需要每次修改都立即展示结果，还可以只设置一次最终值，进一步减少 DOM 更新。</p></section><section><h2>4. 其他 DOM 优化<a href="#4-其他-dom-优化"><span>#</span></a></h2><ul>
<li>尽量复用已有节点。</li>
<li>避免频繁读取 <code>offsetWidth</code>、<code>getBoundingClientRect()</code> 等布局信息。</li>
<li>对大量数据使用分页或虚拟滚动。</li>
<li>使用 Vue 等框架时，合理使用 <code>key</code>、<code>computed</code> 等机制，避免不必要的组件更新。</li>
</ul></section></section>
<section><h1>事件代理<a href="#事件代理"><span>#</span></a></h1><p>事件代理（Event Delegation）也叫事件委托，是指利用事件冒泡，将多个子元素的事件统一交给父元素处理。</p><section><h2>1. 为什么使用事件代理？<a href="#1-为什么使用事件代理"><span>#</span></a></h2><p>假设列表中有 1000 个按钮。</p><p>传统方式：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>document.querySelectorAll('.btn').forEach((btn) =&gt; {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>btn.addEventListener('click', () =&gt; {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console.log('按钮被点击');</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>5</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这种方式需要为每个按钮注册事件监听器。</p><p>使用事件代理：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;ul id="list"&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;li&gt;&lt;button class="btn"&gt;按钮1&lt;/button&gt;&lt;/li&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;li&gt;&lt;button class="btn"&gt;按钮2&lt;/button&gt;&lt;/li&gt;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>&lt;li&gt;&lt;button class="btn"&gt;按钮3&lt;/button&gt;&lt;/li&gt;</span></div></div><div><div><div>5</div></div><div><span>&lt;/ul&gt;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>&lt;script&gt;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>const list = document.querySelector('#list');</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>list.addEventListener('click', (event) =&gt; {</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>const btn = event.target.closest('.btn');</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>if (!btn || !list.contains(btn)) return;</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>console.log('按钮被点击');</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>17</div></div><div><span>&lt;/script&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>无论列表中有多少个按钮，都只需要在父元素上注册一个事件监听器。</p></section><section><h2>2. 事件代理的优点<a href="#2-事件代理的优点"><span>#</span></a></h2><ul>
<li>减少事件监听器数量。</li>
<li>方便统一管理事件。</li>
<li>动态创建的子元素也能响应事件。</li>
<li>特别适合列表、表格等具有大量相似子元素的场景。</li>
</ul><p>注意：事件代理主要适用于能够冒泡的事件，并不是所有事件都适合委托。</p></section></section>
<section><h1>事件稀释<a href="#事件稀释"><span>#</span></a></h1><p>事件稀释是指减少高频事件处理函数的执行次数，避免频繁执行带来性能问题。</p><p>常见方法是防抖（Debounce）和节流（Throttle）。</p><section><h2>1. 防抖 Debounce<a href="#1-防抖-debounce"><span>#</span></a></h2><p>在连续触发事件时，只有停止触发一段时间后，才执行事件处理函数。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function debounce(fn, delay) {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>let timer = null;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>return function (...args) {</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>clearTimeout(timer);</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>timer = setTimeout(() =&gt; {</span></div></div><div><div><div>8</div></div><div><span><span>      </span></span><span>fn.apply(this, args);</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>}, delay);</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>};</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>// 用户停止输入300ms后才执行</span></div></div><div><div><div>14</div></div><div><span>input.addEventListener(</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>'input',</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>debounce(() =&gt; {</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>console.log('发送搜索请求');</span></div></div><div><div><div>18</div></div><div><span><span>  </span></span><span>}, 300)</span></div></div><div><div><div>19</div></div><div><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>常见场景：搜索框输入、表单验证、输入联想等。</p></section><section><h2>2. 节流 Throttle<a href="#2-节流-throttle"><span>#</span></a></h2><p>在连续触发事件时，限制函数的执行频率，让函数在指定时间间隔内最多执行一次。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function throttle(fn, delay) {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>let lastTime = 0;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>return function (...args) {</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>const now = Date.now();</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>if (now - lastTime &gt;= delay) {</span></div></div><div><div><div>8</div></div><div><span><span>      </span></span><span>lastTime = now;</span></div></div><div><div><div>9</div></div><div><span><span>      </span></span><span>fn.apply(this, args);</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>};</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>// 最多每100ms执行一次</span></div></div><div><div><div>15</div></div><div><span>window.addEventListener(</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>'scroll',</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>throttle(() =&gt; {</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>console.log(window.scrollY);</span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>}, 100),</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>{ passive: true }</span></div></div><div><div><div>21</div></div><div><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>常见场景：滚动监听、窗口大小变化、限制按钮连续操作等。</p></section><section><h2>3. 防抖和节流的区别<a href="#3-防抖和节流的区别"><span>#</span></a></h2>

<table><thead><tr><th>对比</th><th>防抖</th><th>节流</th></tr></thead><tbody><tr><td>核心思想</td><td>停止触发后再执行</td><td>按固定时间间隔限制执行</td></tr><tr><td>连续触发</td><td>不断重新计时</td><td>期间仍可定期执行</td></tr><tr><td>适用场景</td><td>搜索输入</td><td>滚动监听</td></tr></tbody></table></section></section>
<section><h1>图片懒加载<a href="#图片懒加载"><span>#</span></a></h1><p>图片懒加载（Lazy Loading）是指页面初始化时不立即加载所有图片，而是在图片接近可视区域时再加载。</p><section><h2>1. 原生懒加载（推荐）<a href="#1-原生懒加载推荐"><span>#</span></a></h2><p>现代浏览器已经支持通过 <code>loading</code> 属性实现懒加载。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!-- 非首屏图片 --&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;img</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>src="image.webp"</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>loading="lazy"</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>width="800"</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>height="450"</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>alt="示例图片"</span></div></div><div><div><div>8</div></div><div><span>/&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>作用</th></tr></thead><tbody><tr><td><code>eager</code></td><td>立即加载，默认值</td></tr><tr><td><code>lazy</code></td><td>延迟加载，接近可视区域时加载</td></tr></tbody></table></section><section><h2>2. JavaScript 实现懒加载<a href="#2-javascript-实现懒加载"><span>#</span></a></h2><p>如果需要自定义图片加载时机，可以使用 <code>IntersectionObserver</code> API。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;img data-src="image.webp" class="lazy-img" alt="示例图片" /&gt;</span></div></div><div><div><div>2</div></div><div><span>const images = document.querySelectorAll('.lazy-img');</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>const observer = new IntersectionObserver((entries) =&gt; {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>entries.forEach((entry) =&gt; {</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>if (!entry.isIntersecting) return;</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>const img = entry.target;</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>img.src = img.dataset.src;</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>observer.unobserve(img);</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>14</div></div><div><span>}, {</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>rootMargin: '200px'</span></div></div><div><div><div>16</div></div><div><span>});</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>images.forEach((img) =&gt; observer.observe(img));</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>这里的 <code>rootMargin: '200px'</code> 表示可以在图片进入可视区域前提前触发加载。</p><p>实际开发中，普通图片优先使用原生 <code>loading="lazy"</code>，只有存在特殊需求时再考虑 <code>IntersectionObserver</code>。</p></section></section>
<section><h1>图片预加载<a href="#图片预加载"><span>#</span></a></h1><p>图片预加载（Preloading）是指提前请求后续需要的图片资源，减少真正展示时的等待时间。</p><section><h2>1. HTML 预加载（推荐用于关键图片）<a href="#1-html-预加载推荐用于关键图片"><span>#</span></a></h2><p>通过 <code>&lt;link rel="preload"&gt;</code> 提前加载图片。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;head&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;link</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>rel="preload"</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>as="image"</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>href="/images/banner.webp"</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>fetchpriority="high"</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>/&gt;</span></div></div><div><div><div>8</div></div><div><span>&lt;/head&gt;</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>&lt;body&gt;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>&lt;img</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>src="/images/banner.webp"</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>fetchpriority="high"</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>alt="首页 Banner"</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>/&gt;</span></div></div><div><div><div>16</div></div><div><span>&lt;/body&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>适用场景：首屏 Banner、关键背景图片等，尤其是浏览器无法在初始 HTML 中直接发现的关键图片。</p><p>如果首屏图片已经通过 HTML 中的 <code>&lt;img&gt;</code> 很早被浏览器发现，通常可以直接设置 <code>fetchpriority="high"</code>，不一定需要额外预加载。</p></section><section><h2>2. JavaScript 预加载<a href="#2-javascript-预加载"><span>#</span></a></h2><p>使用 <code>Image</code> 对象提前请求图片资源。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function preloadImage(src) {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>const img = new Image();</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>img.src = src;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>return img;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>preloadImage('/images/banner-2.webp');</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>适用场景：轮播图下一张图片、即将打开的图片预览等。</p></section><section><h2>3. 图片懒加载与预加载的区别<a href="#3-图片懒加载与预加载的区别"><span>#</span></a></h2>

<table><thead><tr><th>对比</th><th>图片懒加载</th><th>图片预加载</th></tr></thead><tbody><tr><td>核心思想</td><td>延迟加载</td><td>提前加载</td></tr><tr><td>主要目的</td><td>减少初始请求</td><td>减少展示等待</td></tr><tr><td>适用场景</td><td>非首屏图片</td><td>关键图片、即将使用的图片</td></tr><tr><td>常用技术</td><td><code>loading="lazy"</code></td><td><code>rel="preload"</code>、<code>Image</code></td></tr><tr><td>注意事项</td><td>首屏关键图片不宜懒加载</td><td>避免预加载大量非关键图片</td></tr></tbody></table><p>预加载应合理控制数量，否则过多的预加载请求可能争抢网络带宽，反而影响关键资源。</p></section></section>
<section><h1>总结<a href="#总结"><span>#</span></a></h1>

<table><thead><tr><th>优化方向</th><th>核心优化技术</th></tr></thead><tbody><tr><td>图片优化</td><td>压缩、WebP / AVIF、响应式图片、CDN</td></tr><tr><td>动画优化</td><td>transform、opacity、requestAnimationFrame</td></tr><tr><td>CSS 优化</td><td>压缩、按需加载、减少不必要的布局计算</td></tr><tr><td>DOM 优化</td><td>减少节点、批量操作、虚拟列表</td></tr><tr><td>事件代理</td><td>事件冒泡、父元素统一监听</td></tr><tr><td>事件稀释</td><td>防抖、节流</td></tr><tr><td>图片懒加载</td><td>loading=“lazy”、IntersectionObserver</td></tr><tr><td>图片预加载</td><td>preload、fetchpriority、Image</td></tr></tbody></table><p>对于现代 Vue 3 项目，很多底层 DOM 更新优化已经由框架处理。实际开发时，更值得优先掌握的是：图片格式与加载策略、事件代理、防抖节流、动画性能，以及避免不必要的组件和 DOM 更新。</p></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102303-wang-luo-qing-qiu-guo-cheng-zhong-xing-neng-you-hua/</id>
      <title type="text">网络请求过程中性能优化</title>
      <published>2026-10-23T05:46:50.000Z</published>
      <updated>2026-10-23T05:46:50.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102303-wang-luo-qing-qiu-guo-cheng-zhong-xing-neng-you-hua/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>这里只是列出一些优化方向，优化点，主要是网络请求过程中、页面加载渲染和JavaScript脚本的优化</p>
<section><h1>网络请求过程中的优化点<a href="#网络请求过程中的优化点"><span>#</span></a></h1><section><h2>减少 HTTP 请求数量<a href="#减少-http-请求数量"><span>#</span></a></h2><p>每次网络请求都会产生一定的开销，可以通过以下方法优化：</p><ul>
<li>合并请求：将多个相关接口合并，减少重复请求。</li>
<li>按需请求：只请求当前页面需要的数据。</li>
<li>避免重复请求：对相同的请求进行缓存或复用。</li>
<li>资源复用：相同的 JS、CSS 等静态资源尽量共享浏览器缓存。</li>
</ul><p>注意：使用 HTTP/2、HTTP/3 后，不必为了减少请求数量而盲目合并所有 JS、CSS 文件。合理拆分资源更有利于缓存和按需加载。</p></section><section><h2>减小资源体积<a href="#减小资源体积"><span>#</span></a></h2><p>资源体积越小，通常下载速度越快。</p>

<table><thead><tr><th>优化方式</th><th>说明</th></tr></thead><tbody><tr><td>Gzip / Brotli 压缩</td><td>压缩 HTML、CSS、JS 等文本资源</td></tr><tr><td>代码压缩</td><td>删除注释、空格等不必要内容</td></tr><tr><td>Tree Shaking</td><td>移除未使用的代码</td></tr><tr><td>图片压缩</td><td>减少图片文件大小</td></tr><tr><td>图片格式优化</td><td>优先考虑 WebP、AVIF 等现代格式</td></tr><tr><td>字体优化</td><td>使用 WOFF2、字体子集化等方式</td></tr><tr><td>按需打包</td><td>避免将所有依赖打包进首页</td></tr></tbody></table><p>例如，使用 Vite 构建生产项目时，通常会自动压缩 JS、CSS，并支持 Tree Shaking。</p></section><section><h2>使用浏览器缓存<a href="#使用浏览器缓存"><span>#</span></a></h2><p>利用缓存避免重复下载资源。</p>

<table><thead><tr><th>缓存类型</th><th>说明</th></tr></thead><tbody><tr><td>强缓存</td><td>资源未过期时，直接使用本地缓存，不需要请求服务器确认</td></tr><tr><td>协商缓存</td><td>向服务器验证资源是否发生变化，未变化时返回 304</td></tr><tr><td>应用层缓存</td><td>使用内存、Cache API 等保存和复用数据</td></tr></tbody></table><p>实际项目中，常见的缓存策略是：</p><ul>
<li>HTML：及时验证是否有更新。</li>
<li>带内容哈希的 JS、CSS、图片：设置较长时间的强缓存。</li>
<li>API 数据：根据业务特点设置缓存策略。</li>
</ul></section><section><h2>使用 CDN 加速<a href="#使用-cdn-加速"><span>#</span></a></h2><p>CDN（内容分发网络）可以将静态资源分发到不同地区的节点，让用户从距离较近的节点获取资源。</p><p>常见的 CDN 资源包括图片、字体、CSS、JavaScript 等。</p><p>CDN 的主要作用是减少传输延迟、减轻源站压力、提高资源访问速度。</p></section><section><h2>优化请求时机和优先级<a href="#优化请求时机和优先级"><span>#</span></a></h2><p>不是所有资源都需要在页面打开时立即请求。</p><ul>
<li>预加载（preload）：提前加载当前页面即将用到的关键资源。</li>
<li>预连接（preconnect）：提前建立与重要跨域服务器的连接。</li>
<li>懒加载（lazy loading）：非首屏资源等到需要时再加载。</li>
<li>预获取（prefetch）：浏览器空闲或合适时机，提前获取未来可能使用的资源。</li>
</ul><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!-- 预连接到资源服务器 --&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>link</span><span> </span><span>rel</span><span>=</span><span>"preconnect"</span><span> </span><span>href</span><span>=</span><span>"https://cdn.example.com"</span><span> /&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>&lt;!-- 预加载关键字体 --&gt;</span></div></div><div><div><div>5</div></div><div><span>&lt;</span><span>link</span></div></div><div><div><div>6</div></div><div><span>  </span><span>rel</span><span>=</span><span>"preload"</span></div></div><div><div><div>7</div></div><div><span>  </span><span>href</span><span>=</span><span>"/fonts/main.woff2"</span></div></div><div><div><div>8</div></div><div><span>  </span><span>as</span><span>=</span><span>"font"</span></div></div><div><div><div>9</div></div><div><span>  </span><span>type</span><span>=</span><span>"font/woff2"</span></div></div><div><div><div>10</div></div><div><span>  </span><span>crossorigin</span></div></div><div><div><div>11</div></div><div><span>/&gt;</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>&lt;!-- 非首屏图片懒加载 --&gt;</span></div></div><div><div><div>14</div></div><div><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"/images/banner-2.webp"</span><span> </span><span>loading</span><span>=</span><span>"lazy"</span><span> </span><span>alt</span><span>=</span><span>"banner"</span><span> /&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意：首屏关键图片一般不建议使用 <code>loading="lazy"</code>，否则可能延迟首屏显示。</p></section><section><h2>6. 优化接口请求<a href="#6-优化接口请求"><span>#</span></a></h2><p>接口本身也会影响页面性能。</p><ul>
<li>避免接口重复调用。</li>
<li>对搜索输入等高频操作使用防抖。</li>
<li>对不再需要的请求使用 <code>AbortController</code> 取消。</li>
<li>使用分页加载，避免一次返回过多数据。</li>
<li>优化后端数据库查询，缩短接口响应时间。</li>
</ul><p>例如搜索建议：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>timer</span><span>;</span></span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>function</span><span> </span><span>handleSearch</span><span><span>(</span><span>keyword</span><span>) {</span></span></div></div><div><div><div>4</div></div><div><span>  </span><span>clearTimeout</span><span><span>(</span><span>timer</span><span>);</span></span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>timer</span><span> </span><span>=</span><span> </span><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>fetch</span><span>(</span><span>`/api/search?q=</span><span>${</span><span>encodeURIComponent</span><span><span>(</span><span>keyword</span><span>)</span></span><span>}</span><span>`</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}, </span><span>300</span><span>);</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>用户连续输入时，不必每输入一个字符就立即发送一次请求。</p></section></section>
<section><h1>页面加载渲染和JavaScript脚本中的优化点<a href="#页面加载渲染和javascript脚本中的优化点"><span>#</span></a></h1><section><h2>优化页面首次渲染<a href="#优化页面首次渲染"><span>#</span></a></h2><p>浏览器渲染页面的主要过程：</p><p><img alt="" /></p><p>常见优化方式：</p><ul>
<li>优先加载关键资源：首屏需要的 CSS、字体、图片优先加载。</li>
<li>减少阻塞资源：非关键 JavaScript 延迟执行，减少影响首屏渲染的资源。</li>
<li>减少 DOM 数量：避免创建大量无意义的嵌套节点。</li>
<li>使用 SSR / SSG：适合的场景可以提前生成 HTML，减少首屏等待客户端 JavaScript 渲染的时间。</li>
<li>避免不必要的重定向：缩短页面开始加载的等待时间。</li>
</ul><p>尤其需要关注首屏最大内容元素（LCP）的加载时间。</p></section><section><h2>优化 JavaScript 加载与执行<a href="#优化-javascript-加载与执行"><span>#</span></a></h2><p>普通的 JavaScript 脚本可能阻塞 HTML 解析。</p><p>可以通过 <code>async</code>、<code>defer</code> 优化。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!--</span><span><span> </span><span>普通脚本</span><span>：</span><span>执行时阻塞</span><span> </span></span><span>HTML</span><span><span> </span><span>解析</span><span> </span></span><span>--&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>script</span><span> </span><span>src</span><span>=</span><span>"a.js"</span><span>&gt;&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>&lt;!--</span><span><span> </span><span>async</span><span>：</span><span>并行下载</span><span>，</span><span>下载完成后尽快执行</span><span> </span></span><span>--&gt;</span></div></div><div><div><div>5</div></div><div><span>&lt;</span><span>script</span><span> </span><span>async</span><span> </span><span>src</span><span>=</span><span>"b.js"</span><span>&gt;&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>&lt;!--</span><span><span> </span><span>defer</span><span>：</span><span>并行下载</span><span>，</span></span><span>HTML</span><span><span> </span><span>解析完成后按顺序执行</span><span> </span></span><span>--&gt;</span></div></div><div><div><div>8</div></div><div><span>&lt;</span><span>script</span><span> </span><span>defer</span><span> </span><span>src</span><span>=</span><span>"c.js"</span><span>&gt;&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>&lt;!--</span><span> </span><span>ES</span><span><span> </span><span>Module</span><span>：</span><span>默认具有类似</span><span> </span><span>defer</span><span> </span><span>的行为</span><span> </span></span><span>--&gt;</span></div></div><div><div><div>11</div></div><div><span>&lt;</span><span>script</span><span> </span><span>type</span><span>=</span><span>"module"</span><span> </span><span>src</span><span>=</span><span>"main.js"</span><span>&gt;&lt;/</span><span>script</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>对比</th><th>普通脚本</th><th>async</th><th>defer</th></tr></thead><tbody><tr><td>并行下载</td><td>❌</td><td>✅</td><td>✅</td></tr><tr><td>执行时可能阻塞 HTML 解析</td><td>✅</td><td>✅</td><td>❌</td></tr><tr><td>保证多个脚本按文档顺序执行</td><td>✅</td><td>❌</td><td>✅</td></tr><tr><td>适用场景</td><td>必须立即执行</td><td>独立脚本</td><td>有依赖关系的脚本</td></tr></tbody></table><p>实际开发中，推荐使用 <code>defer</code> 或 ES Module 加载需要操作 DOM 的应用脚本。</p></section><section><h2>减少重排和重绘<a href="#减少重排和重绘"><span>#</span></a></h2><ul>
<li>重排（Reflow / Layout）：元素尺寸、位置等发生变化，浏览器需要重新计算布局。</li>
<li>重绘（Repaint）：元素外观发生变化，需要重新绘制相关内容。</li>
</ul><p>常见优化方式：</p><ul>
<li>避免频繁修改元素尺寸、位置。</li>
<li>避免在循环中反复读取布局信息后立即修改样式。</li>
<li>批量修改 DOM 或 CSS。</li>
<li>对动画优先使用 <code>transform</code>、<code>opacity</code>，减少布局计算。</li>
</ul><p>例如：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/* 不推荐：动画过程中可能触发布局计算 */</span></div></div><div><div><div>2</div></div><div><span>.</span><span>box</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>transition</span><span>: </span><span>left</span><span> 0.3</span><span>s</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>.</span><span>box</span><span><span>:</span><span>hover</span><span> {</span></span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>left</span><span>: 100</span><span>px</span><span>;</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>/* 推荐：使用 transform 实现位移 */</span></div></div><div><div><div>11</div></div><div><span>.</span><span>box</span><span> {</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>transition</span><span>: </span><span>transform</span><span> 0.3</span><span>s</span><span>;</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>.</span><span>box</span><span><span>:</span><span>hover</span><span> {</span></span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>transform</span><span>: </span><span>translateX</span><span><span>(100</span><span>px</span><span>);</span></span></div></div><div><div><div>17</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h2>减少 JavaScript 主线程阻塞<a href="#减少-javascript-主线程阻塞"><span>#</span></a></h2><p>JavaScript 中存在大量同步计算时，会阻塞主线程，影响页面交互和绘制。</p><p>常见优化方式：</p><ul>
<li>拆分长任务：避免一个同步任务持续执行过长时间。</li>
<li>使用 Web Worker：将适合的计算密集型任务放到工作线程。</li>
<li>按需加载模块：使用动态 <code>import()</code> 加载暂时用不到的代码。</li>
<li>减少第三方脚本：避免加载不必要的统计、广告和其他外部脚本。</li>
</ul><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 按需加载模块</span></div></div><div><div><div>2</div></div><div><span>const</span><span> { </span><span>calculate</span><span> } </span><span>=</span><span> </span><span>await</span><span> </span><span>import</span><span>(</span><span>'./calculate.js'</span><span>);</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>calculate</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>需要注意：<code>async/await</code> 不能使大量同步计算自动变成非阻塞任务。对于复杂计算，可以考虑 Web Worker。</p></section><section><h2>优化高频事件处理<a href="#优化高频事件处理"><span>#</span></a></h2><p><code>scroll</code>、<code>resize</code>、<code>pointermove</code> 等事件可能频繁触发。</p><p>可以使用：</p>

<table><thead><tr><th>优化方式</th><th>适用场景</th></tr></thead><tbody><tr><td>防抖（debounce）</td><td>搜索框输入、窗口大小变化后的计算</td></tr><tr><td>节流（throttle）</td><td>滚动监听、连续拖拽计算</td></tr><tr><td>requestAnimationFrame</td><td>跟随浏览器刷新节奏更新动画</td></tr><tr><td>passive 事件监听</td><td>不需要阻止默认滚动行为的触摸、滚轮监听</td></tr></tbody></table><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>ticking</span><span> </span></span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>window</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'scroll'</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span>  </span><span>if</span><span><span> (</span><span>ticking</span><span>) </span></span><span>return</span><span>;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>ticking</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>  </span><span>requestAnimationFrame</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>window</span><span>.</span></span><span>scrollY</span><span>);</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>ticking</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>12</div></div><div><span>}, { </span><span>passive</span><span>:</span><span> </span><span>true</span><span> });</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>优化长列表渲染<a href="#优化长列表渲染"><span>#</span></a></h2><p>当页面需要展示大量数据时，例如一次渲染 10000 条数据，会产生较多 DOM 节点。</p><p>可以使用：</p><ul>
<li>分页加载：每次只加载部分数据。</li>
<li>无限滚动：滚动到底部时继续加载。</li>
<li>虚拟列表（Virtual List）：只渲染可视区域及附近的列表项。</li>
</ul><p>其中虚拟列表适合大量数据的滚动场景，能显著减少实际 DOM 节点数量。</p></section></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102302-yi-dong-web-kai-fa-chang-jian-wen-ti/</id>
      <title type="text">移动Web开发常见问题</title>
      <published>2026-10-23T02:33:21.000Z</published>
      <updated>2026-10-23T02:33:21.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102302-yi-dong-web-kai-fa-chang-jian-wen-ti/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>1px边框<a href="#1px边框"><span>#</span></a></h1><p>高清屏幕下，1px边框会变粗那变粗的原因是什么？</p><p>原因：CSS 像素和设备物理像素不一定是 1&lt;1&gt; 的关系。</p><p>设备像素比（DPR）计算公式：</p><p>[ DPR=\frac{设备物理像素}{CSS像素} ]</p><p>例如：</p>

<table><thead><tr><th>DPR</th><th>1 CSS px 对应的物理像素</th></tr></thead><tbody><tr><td>1</td><td>1 × 1</td></tr><tr><td>2</td><td>2 × 2</td></tr><tr><td>3</td><td>3 × 3</td></tr></tbody></table><p>假设手机 DPR = 3，那么 CSS 中的 <code>1px</code> 边框通常会占据约 3 个物理像素的厚度。示意图：相同的 1 CSS px 边框在不同 DPR 下的物理像素厚度。</p><section><h2>解决方案一：使用小数像素<a href="#解决方案一使用小数像素"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>border: </span><span><span>0.5</span><span>px</span></span><span><span> </span><span>solid</span><span> </span></span><span>#</span><span>ddd</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>写法简单，但不同浏览器、DPR 下的绘制效果可能不同，不保证最终恰好是一个物理像素。</p></section><section><h2>解决方案二：伪元素 + transform<a href="#解决方案二伪元素--transform"><span>#</span></a></h2><p>需要实现较细的底边框时，可以使用伪元素。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>position: </span><span>relative</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>.box</span><span>::after</span></span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>content: </span><span>""</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>position: </span><span>absolute</span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>left: </span><span>0</span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>right: </span><span>0</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>bottom: </span><span>0</span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>height: </span><span><span>1</span><span>px</span></span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>background-color: </span><span>#</span><span>ddd</span><span>;</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>transform-origin: </span><span>bottom</span><span>;</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>/* DPR &gt;= 2 */</span></div></div><div><div><div>17</div></div><div><span>@media</span><span> (min-resolution: </span><span><span>2</span><span>dppx</span></span><span>) {</span></div></div><div><div><div>18</div></div><div><span>  </span><span><span>.box</span><span>::after</span></span><span> {</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>transform: </span><span>scaleY</span><span>(</span><span>0.5</span><span>);</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>21</div></div><div><span>}</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>/* DPR &gt;= 3 */</span></div></div><div><div><div>24</div></div><div><span>@media</span><span> (min-resolution: </span><span><span>3</span><span>dppx</span></span><span>) {</span></div></div><div><div><div>25</div></div><div><span>  </span><span><span>.box</span><span>::after</span></span><span> {</span></div></div><div><div><div>26</div></div><div><span><span>    </span></span><span>transform: </span><span>scaleY</span><span>(</span><span>0.333333</span><span>);</span></div></div><div><div><div>27</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>28</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>核心原理是：先绘制 <code>1px</code> 的线，再通过 <code>transform</code> 缩小其视觉厚度。这段代码主要针对常见的 DPR 2、3 屏幕。实际开发建议： 普通边框直接使用 <code>1px</code> 即可。只有设计稿明确要求极细边框时，才需要额外处理。</p></section></section>
<section><h1>click事件300ms延迟<a href="#click事件300ms延迟"><span>#</span></a></h1><section><h2>问题描述<a href="#问题描述"><span>#</span></a></h2><p>早期移动浏览器中，手指点击元素后，<code>click</code> 事件可能延迟约 300ms 才执行。</p></section><section><h2>产生原因<a href="#产生原因"><span>#</span></a></h2><p>浏览器需要判断用户是在单击还是双击缩放页面。</p></section><section><h2>解决方案一：设置 viewport（推荐）<a href="#解决方案一设置-viewport推荐"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;meta</span></div></div><div><div><div>2</div></div><div><span>  </span><span>name="viewport"</span></div></div><div><div><div>3</div></div><div><span>  </span><span>content="width=</span><span>device-width</span><span><span>,</span><span> </span></span><span>initial-scale</span><span>=1.0"</span></div></div><div><div><div>4</div></div><div><span>/&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>现代主流移动浏览器对已适配移动视口的页面，通常已经移除了这类延迟。</p></section><section><h2>解决方案二：touch-action<a href="#解决方案二touch-action"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>button</span><span>,</span></div></div><div><div><div>2</div></div><div><span>a</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>touch-action: </span><span>manipulation</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>touch-action: manipulation</code> 允许正常滚动、双指缩放，但禁用双击缩放等手势，从而避免浏览器为了识别双击而推迟 <code>click</code>。</p></section><section><h2>解决方案三：使用 Touch 事件（了解即可）<a href="#解决方案三使用-touch-事件了解即可"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>button</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelector</span><span>(</span><span>'button'</span><span>);</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>button</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'touchend'</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'手指离开'</span><span>);</span></div></div><div><div><div>5</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>touchend</code> 不需要等待浏览器生成 <code>click</code>，但是还需要自行处理滑动、点击识别以及兼容性事件等问题。</p><p>实际开发建议： 现在正常使用 <code>click</code> 就可以，不必为了消除 300ms 延迟而统一改用 <code>touchend</code>，也通常不需要引入旧的 FastClick 库。</p></section></section>
<section><h1>Touch事件点击穿透<a href="#touch事件点击穿透"><span>#</span></a></h1><section><h2>问题描述<a href="#问题描述-1"><span>#</span></a></h2><p>当一个元素监听 <code>touchend</code>，另一个元素监听 <code>click</code>，并且两个元素位置重叠时，可能出现点击穿透。</p><p>例如：点击弹窗关闭按钮，弹窗关闭之后，下方按钮也被意外触发。</p></section><section><h2>产生原因<a href="#产生原因-1"><span>#</span></a></h2><p>触摸操作结束后，浏览器在某些情况下还会生成兼容性的鼠标事件和 <code>click</code> 事件。若上层元素在 <code>touchend</code> 时被移除，后续 <code>click</code> 可能落到下层元素上。具体表现取决于浏览器及事件处理方式。</p></section><section><h2>解决方案一：统一使用 click（推荐）<a href="#解决方案一统一使用-click推荐"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>overlay</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelector</span><span>(</span><span>'.overlay'</span><span>);</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>button</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelector</span><span>(</span><span>'.button'</span><span>);</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// 上层弹窗</span></div></div><div><div><div>5</div></div><div><span><span>overlay</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'click'</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>overlay</span><span>.</span><span>remove</span><span>();</span></div></div><div><div><div>7</div></div><div><span>});</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>// 下层按钮</span></div></div><div><div><div>10</div></div><div><span><span>button</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'click'</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'底层按钮被点击'</span><span>);</span></div></div><div><div><div>12</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>上层通过自身的 <code>click</code> 事件关闭，可以避免前面所述的“<code>touchend</code> 先删除上层、<code>click</code> 后触发下层”问题。</p></section><section><h2>解决方案二：阻止默认行为<a href="#解决方案二阻止默认行为"><span>#</span></a></h2><p>如果确实需要使用 Touch 事件，可以阻止触摸操作生成后续兼容性鼠标事件。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>overlay</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelector</span><span>(</span><span>'.overlay'</span><span>);</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>overlay</span><span>.</span></span><span>addEventListener</span><span>(</span></div></div><div><div><div>4</div></div><div><span>  </span><span>'touchend'</span><span>,</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>(</span><span>event</span><span>) </span><span>=&gt;</span><span> {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>if</span><span><span> (</span><span>event</span><span>.</span></span><span>cancelable</span><span>) {</span></div></div><div><div><div>7</div></div><div><span><span>      </span></span><span>event</span><span>.</span><span>preventDefault</span><span>();</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>overlay</span><span>.</span><span>remove</span><span>();</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>{ </span><span>passive</span><span>:</span><span> </span><span>false</span><span> }</span></div></div><div><div><div>13</div></div><div><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意：<code>preventDefault()</code> 可能影响默认交互行为，不能随意对所有触摸事件调用。</p></section><section><h2>解决方案三：使用 Pointer Events<a href="#解决方案三使用-pointer-events"><span>#</span></a></h2><p>Pointer Events 可以统一处理鼠标、触摸屏和触控笔。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>button</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointerdown'</span><span><span>, (</span><span>event</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>event</span><span>.</span></span><span>pointerType</span><span>);</span></div></div><div><div><div>3</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>但需要注意：Pointer Events 并不会自动消除所有点击穿透问题。对于普通按钮，依然优先使用 <code>click</code>。</p><p>实际开发建议： 普通按钮、弹窗开关使用 <code>click</code>；需要拖拽、滑动等连续手势时再使用 Pointer Events 或 Touch Events。</p></section></section>
<section><h1>移动端图片<a href="#移动端图片"><span>#</span></a></h1><p>移动端图片常见问题包括：图片超出屏幕、图片变形、高分辨率屏幕下图片模糊，以及图片体积过大导致加载缓慢。</p><section><h2>图片自适应<a href="#图片自适应"><span>#</span></a></h2><p>图片原始宽度大于移动端容器时，可能发生横向溢出。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>img</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>max-width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>height: </span><span>auto</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>max-width: 100%</code> 限制图片最大宽度不超过容器，<code>height: auto</code> 保持原始宽高比。</p></section><section><h2>图片裁剪<a href="#图片裁剪"><span>#</span></a></h2><p>对于商品卡片、头像和文章封面，通常需要固定图片区域的尺寸。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>img</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>aspect-ratio: </span><span>16</span><span> / </span><span>9</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>object-fit: </span><span>cover</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>cover</code> 常用于封面和商品图，<code>contain</code> 常用于需要完整展示的图片。</p></section><section><h2>高清屏图片模糊<a href="#高清屏图片模糊"><span>#</span></a></h2><p>假设图片在网页中显示宽度为 <code>200px</code>：</p>

<table><thead><tr><th>DPR</th><th>理想图片资源宽度</th></tr></thead><tbody><tr><td>1</td><td>200px</td></tr><tr><td>2</td><td>400px</td></tr><tr><td>3</td><td>600px</td></tr></tbody></table><p>如果图片分辨率不够，在高 DPR 屏幕中可能显得模糊。</p><p>可以使用 <code>srcset</code> 提供不同分辨率的图片：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>img</span></div></div><div><div><div>2</div></div><div><span>  </span><span>src</span><span>=</span><span>"image-200.jpg"</span></div></div><div><div><div>3</div></div><div><span>  </span><span>srcset</span><span>=</span><span>"</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>image-200.jpg 1x,</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>image-400.jpg 2x,</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>image-600.jpg 3x</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>"</span></div></div><div><div><div>8</div></div><div><span>  </span><span>width</span><span>=</span><span>"200"</span></div></div><div><div><div>9</div></div><div><span>  </span><span>alt</span><span>=</span><span>"示例图片"</span></div></div><div><div><div>10</div></div><div><span>/&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>浏览器会根据设备环境选择合适的图片资源。</p></section><section><h2>响应式图片<a href="#响应式图片"><span>#</span></a></h2><p>对于不同屏幕宽度，可以提供不同尺寸的图片资源：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>img</span></div></div><div><div><div>2</div></div><div><span>  </span><span>src</span><span>=</span><span>"image-800.jpg"</span></div></div><div><div><div>3</div></div><div><span>  </span><span>srcset</span><span>=</span><span>"</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>image-400.jpg 400w,</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>image-800.jpg 800w,</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>image-1200.jpg 1200w</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>"</span></div></div><div><div><div>8</div></div><div><span>  </span><span>sizes</span><span>=</span><span>"(max-width: 768px) 100vw, 800px"</span></div></div><div><div><div>9</div></div><div><span>  </span><span>alt</span><span>=</span><span>"响应式图片"</span></div></div><div><div><div>10</div></div><div><span>/&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其中：</p><ul>
<li><code>srcset</code>：提供可供选择的图片及其实际宽度。</li>
<li><code>sizes</code>：告诉浏览器图片预计显示多宽。</li>
</ul><p>浏览器会结合显示尺寸、DPR 等条件选择资源，而不需要通过 JavaScript 手动切换图片。</p></section><section><h2>图片懒加载<a href="#图片懒加载"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>img</span></div></div><div><div><div>2</div></div><div><span>  </span><span>src</span><span>=</span><span>"image.jpg"</span></div></div><div><div><div>3</div></div><div><span>  </span><span>loading</span><span>=</span><span>"lazy"</span></div></div><div><div><div>4</div></div><div><span>  </span><span>width</span><span>=</span><span>"800"</span></div></div><div><div><div>5</div></div><div><span>  </span><span>height</span><span>=</span><span>"450"</span></div></div><div><div><div>6</div></div><div><span>  </span><span>alt</span><span>=</span><span>"示例图片"</span></div></div><div><div><div>7</div></div><div><span>/&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>loading="lazy"</code> 表示推迟加载距离视口较远的图片，可以减少初始页面加载负担。</p><p>图片应尽量提供 <code>width</code> 和 <code>height</code>，为加载前的图片预留空间，减少布局偏移。首屏关键图片一般不要随意使用懒加载。</p></section><section><h2>图片底部空白<a href="#图片底部空白"><span>#</span></a></h2><p><code>img</code> 默认是行内替换元素，基线对齐可能导致图片底部出现空隙。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>img</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: </span><span>block</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>通常可以直接解决。</p></section></section>
<section><h1>总结<a href="#总结"><span>#</span></a></h1>

<table><thead><tr><th>常见问题</th><th>原因</th><th>推荐解决方案</th></tr></thead><tbody><tr><td>1px 边框偏粗</td><td>DPR 导致物理像素厚度不同</td><td>普通边框用 <code>1px</code>，极细线用伪元素缩放</td></tr><tr><td>click 300ms 延迟</td><td>历史上的双击缩放判断</td><td>viewport、<code>touch-action: manipulation</code></td></tr><tr><td>Touch 点击穿透</td><td>触摸后产生兼容性 click 事件</td><td>普通交互统一使用 <code>click</code></td></tr><tr><td>图片超出屏幕</td><td>图片宽度大于容器</td><td><code>max-width: 100%</code></td></tr><tr><td>图片拉伸变形</td><td>容器与图片比例不同</td><td><code>object-fit</code></td></tr><tr><td>高清图片模糊</td><td>图片资源分辨率不足</td><td><code>srcset</code></td></tr><tr><td>图片加载缓慢</td><td>图片体积大、加载过多</td><td>合理尺寸、现代格式、懒加载</td></tr><tr><td>图片底部空白</td><td>行内元素基线对齐</td><td><code>display: block</code></td></tr></tbody></table><p>学习重点： 这四类问题中，300ms 延迟和 Touch 点击穿透是比较典型的历史移动端兼容性问题，了解原理即可。现代项目更值得掌握的是 Pointer Events、响应式图片、DPR 以及图片加载优化，这些知识在 Vue 3、移动 H5 等项目里仍然经常使用。</p></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102301-yi-dong-web-duan-shi-jian/</id>
      <title type="text">移动Web端事件</title>
      <published>2026-10-22T23:21:23.000Z</published>
      <updated>2026-10-22T23:21:23.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102301-yi-dong-web-duan-shi-jian/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>z在早期的时候，是没有移动端事件，大部分鼠标事件在移动端一样有用，后面苹果推出了touch 触摸事件，后续浏览器跟进，微软推出pointer指针事件（统一鼠标、触摸、笔），那在PC和移动端表现有什么区别，为什么要学习，举一个轮播图例子，正常在pc端通过点击左右按钮切换轮播，而在移动端，可以通过触摸滑动图片实现轮播的切换</p>
<section><h1>Touch 触摸事件<a href="#touch-触摸事件"><span>#</span></a></h1><section><h2>Touch事件基础<a href="#touch事件基础"><span>#</span></a></h2><p>touch事件类型有以下4种：</p>

<table><thead><tr><th>事件</th><th>触发时机</th></tr></thead><tbody><tr><td><code>touchstart</code></td><td>手指接触屏幕</td></tr><tr><td><code>touchmove</code></td><td>手指在屏幕上移动</td></tr><tr><td><code>touchend</code></td><td>手指离开屏幕</td></tr><tr><td><code>touchcancel</code></td><td>触摸操作被浏览器或系统中断</td></tr></tbody></table><p>示例：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// touch事件类型</span></div></div><div><div><div>2</div></div><div><span>// touchstart touchmove touchend touchcancel</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>$box</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>'box'</span><span>);</span></div></div><div><div><div>4</div></div><div><span>//触摸开始</span></div></div><div><div><div>5</div></div><div><span><span>$box</span><span>.</span></span><span>addEventListener</span><span>(</span></div></div><div><div><div>6</div></div><div><span>  </span><span>'touchstart'</span><span>,</span></div></div><div><div><div>7</div></div><div><span>  </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'手指接触屏幕'</span><span><span>, </span><span>e</span><span>);</span></span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>10</div></div><div><span>  </span><span>false</span><span>,</span></div></div><div><div><div>11</div></div><div><span>);</span></div></div><div><div><div>12</div></div><div><span>// 移动</span></div></div><div><div><div>13</div></div><div><span><span>$box</span><span>.</span></span><span>addEventListener</span><span>(</span></div></div><div><div><div>14</div></div><div><span>  </span><span>'touchmove'</span><span>,</span></div></div><div><div><div>15</div></div><div><span>  </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'手指在屏幕上移动'</span><span><span>, </span><span>e</span><span>);</span></span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>18</div></div><div><span>  </span><span>false</span><span>,</span></div></div><div><div><div>19</div></div><div><span>);</span></div></div><div><div><div>20</div></div><div><span>// 离开</span></div></div><div><div><div>21</div></div><div><span><span>$box</span><span>.</span></span><span>addEventListener</span><span>(</span></div></div><div><div><div>22</div></div><div><span>  </span><span>'touchend'</span><span>,</span></div></div><div><div><div>23</div></div><div><span>  </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>24</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'手指离开屏幕'</span><span><span>, </span><span>e</span><span>);</span></span></div></div><div><div><div>25</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>26</div></div><div><span>  </span><span>false</span><span>,</span></div></div><div><div><div>27</div></div><div><span>);</span></div></div><div><div><div>28</div></div><div><span>// 触摸操作被浏览器或系统中断</span></div></div><div><div><div>29</div></div><div><span><span>$box</span><span>.</span></span><span>addEventListener</span><span>(</span></div></div><div><div><div>30</div></div><div><span>  </span><span>'touchcancel'</span><span>,</span></div></div><div><div><div>31</div></div><div><span>  </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>32</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'触摸操作被浏览器或系统中断'</span><span><span>, </span><span>e</span><span>);</span></span></div></div><div><div><div>33</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>34</div></div><div><span>  </span><span>false</span><span>,</span></div></div><div><div><div>35</div></div><div><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>注意：即使触摸点移出目标元素，touchmove事件依然会持续触发，前提是手指一直触摸不要离开屏幕的触摸滑动，而mousemove这个鼠标事件不会触发；</p><p>Touch事件在pc端不会触发，鼠标事件在PC和移动端都会触发；touch事件的特征检测可以通过 <code>'ontouchstart' in window</code>检测是否支持，返回一个布尔值</p></section><section><h2>Touch事件的event对象<a href="#touch事件的event对象"><span>#</span></a></h2><p><strong>event对象常用属性</strong></p>

<table><thead><tr><th>属性 / 方法</th><th>作用</th></tr></thead><tbody><tr><td><code>event.touches</code></td><td>当前仍接触屏幕的所有触摸点</td></tr><tr><td><code>event.targetTouches</code></td><td>当前仍接触屏幕，且最初在事件目标元素上开始触摸的触摸点</td></tr><tr><td><code>event.changedTouches</code></td><td>本次事件中发生变化的触摸点</td></tr><tr><td><code>event.target</code></td><td>最初触发事件的元素</td></tr><tr><td><code>event.currentTarget</code></td><td>当前绑定事件处理程序的元素</td></tr><tr><td><code>event.type</code></td><td>事件类型，如 <code>touchstart</code></td></tr><tr><td><code>event.cancelable</code></td><td>当前事件是否可以取消默认行为</td></tr><tr><td><code>event.preventDefault()</code></td><td>阻止浏览器的默认行为</td></tr></tbody></table><p>其中，<code>touches</code>、<code>targetTouches</code> 和 <code>changedTouches</code> 是 Touch 事件最重要的三个属性。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'touchstart'</span><span><span>, (</span><span>event</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>event</span><span>.</span></span><span>touches</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>event</span><span>.</span></span><span>targetTouches</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>event</span><span>.</span></span><span>changedTouches</span><span>);</span></div></div><div><div><div>5</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>触摸点的常用属性</strong></p><p>上面的三个属性返回的都是 <code>TouchList</code> 对象，可以通过下标获取其中的触摸点。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'touchstart'</span><span><span>, (</span><span>event</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>const</span><span> </span><span>touch</span><span> </span><span>=</span><span><span> </span><span>event</span><span>.</span></span><span>changedTouches</span><span>[</span><span>0</span><span>];</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>touch</span><span>.</span></span><span>clientX</span><span>);</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>touch</span><span>.</span></span><span>clientY</span><span>);</span></div></div><div><div><div>6</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>常用的触摸点属性如下：</p>

<table><thead><tr><th>属性</th><th>作用</th></tr></thead><tbody><tr><td><code>identifier</code></td><td>触摸点的唯一标识，用于区分不同触摸点</td></tr><tr><td><code>target</code></td><td>该触摸点最初开始触摸的元素</td></tr><tr><td><code>clientX</code> / <code>clientY</code></td><td>触摸点相对于浏览器视口的坐标</td></tr><tr><td><code>pageX</code> / <code>pageY</code></td><td>触摸点相对于整个文档的坐标</td></tr><tr><td><code>screenX</code> / <code>screenY</code></td><td>触摸点相对于屏幕的坐标</td></tr><tr><td><code>radiusX</code> / <code>radiusY</code></td><td>触摸接触区域的椭圆半径</td></tr><tr><td><code>rotationAngle</code></td><td>触摸接触区域的旋转角度</td></tr><tr><td><code>force</code></td><td>触摸压力值，通常在 0 到 1 之间</td></tr></tbody></table><p>日常开发中，最常用的是 <code>clientX</code>、<code>clientY</code>，例如获取手指的位置、计算滑动距离。</p><p><strong>阻止浏览器的默认行为</strong></p><p>移动端触摸操作可能触发浏览器的默认行为，例如页面滚动、缩放等。</p><p>可以使用 <code>event.preventDefault()</code> 阻止可取消的默认行为。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span></div></div><div><div><div>2</div></div><div><span>  </span><span>'touchmove'</span><span>,</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>(</span><span>event</span><span>) </span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>event</span><span>.</span><span>preventDefault</span><span>();</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>{ </span><span>passive</span><span>:</span><span> </span><span>false</span><span> },</span></div></div><div><div><div>7</div></div><div><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这里需要注意两点：</p><ul>
<li><code>preventDefault()</code> 是阻止默认行为，不是阻止事件冒泡；阻止冒泡使用 <code>stopPropagation()</code>。</li>
<li>现代浏览器中，部分触摸事件监听器默认可能采用被动监听（<code>passive</code>）。被动监听器中调用 <code>preventDefault()</code> 无法阻止默认行为，因此需要时应明确设置 <code>{ passive: false }</code>。</li>
</ul><p>实际开发建议： 如果只是要控制页面是否允许滚动或缩放，优先考虑 CSS 的 <code>touch-action</code>；只有确实需要通过 JavaScript 取消默认行为时，再使用 <code>preventDefault()</code>。</p><p><strong>单指拖拽</strong></p><p>单指拖拽是指用户用一根手指按住元素并移动，从而改变元素的位置。</p><p>实现思路：</p><ol>
<li><code>touchstart</code>：记录手指初始坐标和元素初始位置。</li>
<li><code>touchmove</code>：计算手指移动距离，更新元素位置。</li>
<li><code>touchend</code>：结束拖拽。</li>
</ol><p>示例代码</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box"</span><span>&gt;拖动我&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>  </span><span>.box</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>position: </span><span>fixed</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>left: </span><span><span>50</span><span>px</span></span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>top: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>width: </span><span><span>120</span><span>px</span></span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>height: </span><span><span>120</span><span>px</span></span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>background-color: </span><span>skyblue</span><span>;</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>justify-content: </span><span>center</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>align-items: </span><span>center</span><span>;</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>touch-action: </span><span>none</span><span>;</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>user-select: </span><span>none</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>19</div></div><div><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>20</div></div><div><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>21</div></div><div><span>  </span><span>const</span><span> </span><span>box</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelector</span><span>(</span><span>'.box'</span><span>);</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>  </span><span>let</span><span><span> </span><span>startX</span><span> </span></span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>24</div></div><div><span>  </span><span>let</span><span><span> </span><span>startY</span><span> </span></span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>25</div></div><div><span>  </span><span>let</span><span><span> </span><span>startLeft</span><span> </span></span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>26</div></div><div><span>  </span><span>let</span><span><span> </span><span>startTop</span><span> </span></span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>27</div></div><div><span>  </span><span>let</span><span><span> </span><span>dragging</span><span> </span></span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span><span>  </span></span><span>box</span><span>.</span><span>addEventListener</span><span>(</span></div></div><div><div><div>30</div></div><div><span>    </span><span>'touchstart'</span><span>,</span></div></div><div><div><div>31</div></div><div><span><span>    </span></span><span>(</span><span>event</span><span>) </span><span>=&gt;</span><span> {</span></div></div><div><div><div>32</div></div><div><span>      </span><span>// 只允许单指拖拽</span></div></div><div><div><div>33</div></div><div><span>      </span><span>if</span><span><span> (</span><span>event</span><span>.</span></span><span>touches</span><span>.</span><span>length</span><span> </span><span>!==</span><span> </span><span>1</span><span>) {</span></div></div><div><div><div>34</div></div><div><span><span>        </span></span><span>dragging</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>35</div></div><div><span>        </span><span>return</span><span>;</span></div></div><div><div><div>36</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>37</div></div><div>
</div></div><div><div><div>38</div></div><div><span>      </span><span>const</span><span> </span><span>touch</span><span> </span><span>=</span><span><span> </span><span>event</span><span>.</span></span><span>changedTouches</span><span>[</span><span>0</span><span>];</span></div></div><div><div><div>39</div></div><div><span>      </span><span>const</span><span> </span><span>rect</span><span> </span><span>=</span><span><span> </span><span>box</span><span>.</span></span><span>getBoundingClientRect</span><span>();</span></div></div><div><div><div>40</div></div><div>
</div></div><div><div><div>41</div></div><div><span>      </span><span>// 记录手指初始坐标</span></div></div><div><div><div>42</div></div><div><span><span>      </span></span><span>startX</span><span> </span><span>=</span><span><span> </span><span>touch</span><span>.</span></span><span>clientX</span><span>;</span></div></div><div><div><div>43</div></div><div><span><span>      </span></span><span>startY</span><span> </span><span>=</span><span><span> </span><span>touch</span><span>.</span></span><span>clientY</span><span>;</span></div></div><div><div><div>44</div></div><div>
</div></div><div><div><div>45</div></div><div><span>      </span><span>// 记录元素初始位置</span></div></div><div><div><div>46</div></div><div><span><span>      </span></span><span>startLeft</span><span> </span><span>=</span><span><span> </span><span>rect</span><span>.</span></span><span>left</span><span>;</span></div></div><div><div><div>47</div></div><div><span><span>      </span></span><span>startTop</span><span> </span><span>=</span><span><span> </span><span>rect</span><span>.</span></span><span>top</span><span>;</span></div></div><div><div><div>48</div></div><div>
</div></div><div><div><div>49</div></div><div><span><span>      </span></span><span>dragging</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>50</div></div><div><span><span>    </span></span><span>},</span></div></div><div><div><div>51</div></div><div><span><span>    </span></span><span>{ </span><span>passive</span><span>:</span><span> </span><span>true</span><span> },</span></div></div><div><div><div>52</div></div><div><span><span>  </span></span><span>);</span></div></div><div><div><div>53</div></div><div>
</div></div><div><div><div>54</div></div><div><span><span>  </span></span><span>box</span><span>.</span><span>addEventListener</span><span>(</span></div></div><div><div><div>55</div></div><div><span>    </span><span>'touchmove'</span><span>,</span></div></div><div><div><div>56</div></div><div><span><span>    </span></span><span>(</span><span>event</span><span>) </span><span>=&gt;</span><span> {</span></div></div><div><div><div>57</div></div><div><span>      </span><span>if</span><span> (</span><span>!</span><span><span>dragging</span><span>) </span></span><span>return</span><span>;</span></div></div><div><div><div>58</div></div><div>
</div></div><div><div><div>59</div></div><div><span>      </span><span>// 多指触摸时取消拖拽</span></div></div><div><div><div>60</div></div><div><span>      </span><span>if</span><span><span> (</span><span>event</span><span>.</span></span><span>touches</span><span>.</span><span>length</span><span> </span><span>!==</span><span> </span><span>1</span><span>) {</span></div></div><div><div><div>61</div></div><div><span><span>        </span></span><span>dragging</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>62</div></div><div><span>        </span><span>return</span><span>;</span></div></div><div><div><div>63</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>64</div></div><div>
</div></div><div><div><div>65</div></div><div><span>      </span><span>const</span><span> </span><span>touch</span><span> </span><span>=</span><span><span> </span><span>event</span><span>.</span></span><span>touches</span><span>[</span><span>0</span><span>];</span></div></div><div><div><div>66</div></div><div>
</div></div><div><div><div>67</div></div><div><span>      </span><span>// 计算手指移动距离</span></div></div><div><div><div>68</div></div><div><span>      </span><span>const</span><span> </span><span>moveX</span><span> </span><span>=</span><span><span> </span><span>touch</span><span>.</span></span><span>clientX</span><span> </span><span>-</span><span><span> </span><span>startX</span><span>;</span></span></div></div><div><div><div>69</div></div><div><span>      </span><span>const</span><span> </span><span>moveY</span><span> </span><span>=</span><span><span> </span><span>touch</span><span>.</span></span><span>clientY</span><span> </span><span>-</span><span><span> </span><span>startY</span><span>;</span></span></div></div><div><div><div>70</div></div><div>
</div></div><div><div><div>71</div></div><div><span>      </span><span>// 更新元素位置</span></div></div><div><div><div>72</div></div><div><span><span>      </span></span><span>box</span><span>.</span><span>style</span><span>.</span><span>left</span><span> </span><span>=</span><span> </span><span>`</span><span>${</span><span>startLeft</span><span> </span><span>+</span><span> </span><span>moveX</span><span>}</span><span>px`</span><span>;</span></div></div><div><div><div>73</div></div><div><span><span>      </span></span><span>box</span><span>.</span><span>style</span><span>.</span><span>top</span><span> </span><span>=</span><span> </span><span>`</span><span>${</span><span>startTop</span><span> </span><span>+</span><span> </span><span>moveY</span><span>}</span><span>px`</span><span>;</span></div></div><div><div><div>74</div></div><div><span><span>    </span></span><span>},</span></div></div><div><div><div>75</div></div><div><span><span>    </span></span><span>{ </span><span>passive</span><span>:</span><span> </span><span>true</span><span> },</span></div></div><div><div><div>76</div></div><div><span><span>  </span></span><span>);</span></div></div><div><div><div>77</div></div><div>
</div></div><div><div><div>78</div></div><div><span><span>  </span></span><span>box</span><span>.</span><span>addEventListener</span><span>(</span><span>'touchend'</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>79</div></div><div><span><span>    </span></span><span>dragging</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>80</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>81</div></div><div>
</div></div><div><div><div>82</div></div><div><span><span>  </span></span><span>box</span><span>.</span><span>addEventListener</span><span>(</span><span>'touchcancel'</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>83</div></div><div><span><span>    </span></span><span>dragging</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>84</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>85</div></div><div><span>&lt;/</span><span>script</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>核心计算公式</p>

<table><thead><tr><th>变量</th><th>计算方式</th></tr></thead><tbody><tr><td>水平移动距离</td><td><code>moveX = 当前手指X - 初始手指X</code></td></tr><tr><td>垂直移动距离</td><td><code>moveY = 当前手指Y - 初始手指Y</code></td></tr><tr><td>元素新位置</td><td><code>初始位置 + 移动距离</code></td></tr></tbody></table><p>例如，手指初始横坐标为 <code>100px</code>，移动后变成 <code>150px</code>，那么：</p><ul>
<li>手指水平移动了 <code>50px</code>。</li>
<li>如果元素原本位于 <code>200px</code>，新位置就是 <code>250px</code>。</li>
</ul><p>注意事项</p><ul>
<li><code>touch-action: none</code> 用于禁止浏览器在该元素上执行原生平移、缩放手势，避免与自定义拖拽冲突。</li>
<li>如果改用 <code>event.preventDefault()</code> 阻止默认行为，<code>touchmove</code> 监听器需要设置 <code>{ passive: false }</code>，否则可能无法阻止。</li>
<li><code>touchend</code> 和 <code>touchcancel</code> 都要处理，避免拖拽状态没有正确结束。</li>
</ul><p>记住核心思路：记录初始位置 → 计算手指移动距离 → 更新元素位置。</p></section></section>
<section><h1>pointer指针事件<a href="#pointer指针事件"><span>#</span></a></h1><p>Pointer Events（指针事件） 是统一处理鼠标、触摸屏、触控笔等输入设备的事件机制。与 <code>Mouse Events</code> 和 <code>Touch Events</code> 相比，Pointer Events 最大的优势是：一套事件代码，可以同时处理 PC 端和移动端的交互。</p><section><h2>Pointer事件基础<a href="#pointer事件基础"><span>#</span></a></h2><p><strong>Pointer事件类型</strong></p>

<table><thead><tr><th><code>pointerdown</code></th><th>指针按下时</th><th>开始拖拽、按压</th></tr></thead><tbody><tr><td><code>pointermove</code></td><td>指针移动时</td><td>拖拽、绘图</td></tr><tr><td><code>pointerup</code></td><td>指针释放时</td><td>结束拖拽</td></tr><tr><td><code>pointercancel</code></td><td>指针操作被浏览器取消时</td><td>清理拖拽状态</td></tr><tr><td><code>pointerover</code></td><td>指针进入元素区域</td><td>悬停效果</td></tr><tr><td><code>pointerout</code></td><td>指针离开元素区域</td><td>取消悬停</td></tr><tr><td><code>pointerenter</code></td><td>指针进入元素或其子元素区域</td><td>鼠标进入</td></tr><tr><td><code>pointerleave</code></td><td>指针离开元素及其子元素区域</td><td>鼠标离开</td></tr><tr><td><code>gotpointercapture</code></td><td>元素获得指针捕获时</td><td>监听捕获状态</td></tr><tr><td><code>lostpointercapture</code></td><td>元素失去指针捕获时</td><td>监听捕获释放</td></tr><tr><td><code>pointerrawupdate</code></td><td>指针状态发生变化时，提供更直接的更新</td><td>高精度绘图等</td></tr></tbody></table><p>其中，最常用的是 <code>pointerdown</code>、<code>pointermove</code>、<code>pointerup</code>、<code>pointercancel</code></p><p>实现一个简单的拖拽操作：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>box</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelector</span><span>(</span><span>'.box'</span><span>);</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>let</span><span><span> </span><span>isDragging</span><span> </span></span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointerdown'</span><span><span>, (</span><span>e</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>isDragging</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>box</span><span>.</span><span>setPointerCapture</span><span><span>(</span><span>e</span><span>.</span></span><span>pointerId</span><span>);</span></div></div><div><div><div>8</div></div><div><span>});</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointermove'</span><span><span>, (</span><span>e</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>11</div></div><div><span>  </span><span>if</span><span> (</span><span>!</span><span><span>isDragging</span><span>) </span></span><span>return</span><span>;</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>e</span><span>.</span></span><span>clientX</span><span><span>, </span><span>e</span><span>.</span></span><span>clientY</span><span>);</span></div></div><div><div><div>14</div></div><div><span>});</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointerup'</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>isDragging</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>18</div></div><div><span>});</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointercancel'</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>21</div></div><div><span><span>  </span></span><span>isDragging</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>22</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>Pointer 事件注意事项</strong></p><ol>
<li>Pointer 事件不会自动阻止浏览器默认行为</li>
</ol><p>在移动端，浏览器默认会处理页面滚动、缩放等触摸操作。如果使用 Pointer 事件实现拖拽，可能触发 <code>pointercancel</code>，导致拖拽中断。解决方法：使用 CSS 的 <code>touch-action</code> 属性。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.</span><span>box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>touch</span><span>-</span><span><span>action</span><span>: </span><span>none</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>常见取值：</p>

<table><thead><tr><th>属性值</th><th>作用</th></tr></thead><tbody><tr><td><code>auto</code></td><td>浏览器默认处理触摸操作</td></tr><tr><td><code>none</code></td><td>禁止浏览器处理该区域的触摸平移和缩放手势</td></tr><tr><td><code>pan-x</code></td><td>允许浏览器处理水平滚动</td></tr><tr><td><code>pan-y</code></td><td>允许浏览器处理垂直滚动</td></tr><tr><td><code>manipulation</code></td><td>允许滚动和双指缩放等操作，不允许双击缩放</td></tr></tbody></table><p>注意：<code>touch-action: none</code> 应只设置在需要自定义触摸交互的区域，避免影响正常页面滚动。</p><ol>
<li>pointermove 不一定需要按下指针</li>
</ol><p><code>pointermove</code> 只要指针移动就可能触发。例如，鼠标没有按下，只是在元素内部移动，也会触发 <code>pointermove</code>。因此实现拖拽时，需要判断是否处于拖拽状态。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>isDragging</span><span> </span></span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointerdown'</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>isDragging</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>5</div></div><div><span>});</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointermove'</span><span><span>, (</span><span>e</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>8</div></div><div><span>  </span><span>if</span><span> (</span><span>!</span><span><span>isDragging</span><span>) </span></span><span>return</span><span>;</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>e</span><span>.</span></span><span>clientX</span><span><span>, </span><span>e</span><span>.</span></span><span>clientY</span><span>);</span></div></div><div><div><div>11</div></div><div><span>});</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointerup'</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>isDragging</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>15</div></div><div><span>});</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointercancel'</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>18</div></div><div><span><span>  </span></span><span>isDragging</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>19</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><ol>
<li>指针离开元素可能导致事件无法继续接收</li>
</ol><p>默认情况下，鼠标移出元素后，元素可能无法继续接收后续的 <code>pointermove</code> 和 <code>pointerup</code>。解决方法：使用指针捕获。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointerdown'</span><span><span>, (</span><span>e</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>box</span><span>.</span><span>setPointerCapture</span><span><span>(</span><span>e</span><span>.</span></span><span>pointerId</span><span>);</span></div></div><div><div><div>3</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这样即使指针移出元素，后续事件仍然可以发送到该元素。</p><p>相关 API：</p>

<table><thead><tr><th>API</th><th>作用</th></tr></thead><tbody><tr><td><code>setPointerCapture()</code></td><td>捕获指定指针</td></tr><tr><td><code>releasePointerCapture()</code></td><td>释放指定指针</td></tr><tr><td><code>hasPointerCapture()</code></td><td>判断是否捕获指定指针</td></tr></tbody></table><p>注意：<code>pointerup</code> 或 <code>pointercancel</code> 后，浏览器会自动释放指针捕获。捕获期间也不会正常触发该指针的 <code>pointerenter</code>、<code>pointerleave</code> 等边界事件。</p><ol>
<li>必须考虑 pointercancel</li>
</ol><p><code>pointerup</code> 和 <code>pointercancel</code> 并不相同。</p><ul>
<li><code>pointerup</code>：用户正常释放指针。</li>
<li><code>pointercancel</code>：浏览器或系统取消了当前指针操作。</li>
</ul><p>例如，浏览器接管触摸操作进行页面滚动时，可能触发 <code>pointercancel</code>。因此拖拽开发中，通常需要同时监听两个事件进行状态清理。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>stopDrag</span><span>() {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>isDragging</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointerup'</span><span><span>, </span><span>stopDrag</span><span>);</span></span></div></div><div><div><div>6</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointercancel'</span><span><span>, </span><span>stopDrag</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><ol>
<li>多指触摸需要区分 pointerId</li>
</ol><p>Pointer Events 支持多点触控，每个活动指针都有自己的 <code>pointerId</code>。如果只需要单指拖拽，可以记录当前操作的指针 ID，避免其他手指干扰。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>activePointerId</span><span> </span></span><span>=</span><span> </span><span>null</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointerdown'</span><span><span>, (</span><span>e</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span>  </span><span>if</span><span><span> (</span><span>activePointerId</span><span> </span></span><span>!==</span><span> </span><span>null</span><span>) </span><span>return</span><span>;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>activePointerId</span><span> </span><span>=</span><span><span> </span><span>e</span><span>.</span></span><span>pointerId</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>box</span><span>.</span><span>setPointerCapture</span><span><span>(</span><span>e</span><span>.</span></span><span>pointerId</span><span>);</span></div></div><div><div><div>8</div></div><div><span>});</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointermove'</span><span><span>, (</span><span>e</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>11</div></div><div><span>  </span><span>if</span><span><span> (</span><span>e</span><span>.</span></span><span>pointerId</span><span> </span><span>!==</span><span><span> </span><span>activePointerId</span><span>) </span></span><span>return</span><span>;</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>e</span><span>.</span></span><span>clientX</span><span><span>, </span><span>e</span><span>.</span></span><span>clientY</span><span>);</span></div></div><div><div><div>14</div></div><div><span>});</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>function</span><span> </span><span>stopDrag</span><span><span>(</span><span>e</span><span>) {</span></span></div></div><div><div><div>17</div></div><div><span>  </span><span>if</span><span><span> (</span><span>e</span><span>.</span></span><span>pointerId</span><span> </span><span>!==</span><span><span> </span><span>activePointerId</span><span>) </span></span><span>return</span><span>;</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>activePointerId</span><span> </span><span>=</span><span> </span><span>null</span><span>;</span></div></div><div><div><div>20</div></div><div><span>}</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointerup'</span><span><span>, </span><span>stopDrag</span><span>);</span></span></div></div><div><div><div>23</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointercancel'</span><span><span>, </span><span>stopDrag</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><ol>
<li>Pointer 事件可能同时触发 Mouse 事件</li>
</ol><p>为兼容旧代码，浏览器可能在 Pointer 事件之外继续触发对应的 Mouse 事件。例如，一次鼠标点击可能产生以下事件：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>pointerdown</span><span>;</span></span></div></div><div><div><div>2</div></div><div><span><span>mousedown</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span><span>pointerup</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span><span>mouseup</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span><span>click</span><span>;</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>所以，同一个交互不要同时使用 Pointer 和 Mouse 事件重复处理，否则可能执行两次业务逻辑。</p><p>另外，<code>pointerdown</code> 不完全等同于 <code>mousedown</code>：鼠标多个按键同时操作时，<code>pointerdown</code> 只在进入有按键按下的状态时触发。</p><ol>
<li>pointerenter 和 pointerleave 不支持冒泡</li>
</ol>

<table><thead><tr><th>事件</th><th>是否冒泡</th></tr></thead><tbody><tr><td><code>pointerover</code></td><td>✅</td></tr><tr><td><code>pointerout</code></td><td>✅</td></tr><tr><td><code>pointerenter</code></td><td>❌</td></tr><tr><td><code>pointerleave</code></td><td>❌</td></tr><tr><td><code>pointerdown</code></td><td>✅</td></tr><tr><td><code>pointermove</code></td><td>✅</td></tr><tr><td><code>pointerup</code></td><td>✅</td></tr></tbody></table><p>因此，使用事件委托处理指针进入、离开元素时，通常选择 <code>pointerover</code> 和 <code>pointerout</code>，并根据 <code>relatedTarget</code> 判断是否真正跨越了目标元素边界。</p><p>总结</p>

<table><thead><tr><th>注意事项</th><th>推荐做法</th></tr></thead><tbody><tr><td>浏览器默认触摸行为干扰</td><td>使用 <code>touch-action</code></td></tr><tr><td>指针未按下也能触发移动事件</td><td>判断拖拽状态</td></tr><tr><td>指针离开元素导致事件丢失</td><td>使用 <code>setPointerCapture()</code></td></tr><tr><td>指针操作可能被取消</td><td>同时处理 <code>pointercancel</code></td></tr><tr><td>多指触摸相互干扰</td><td>使用 <code>pointerId</code> 区分</td></tr><tr><td>Pointer 与 Mouse 事件可能重复</td><td>避免重复绑定相同业务逻辑</td></tr><tr><td><code>pointerenter/leave</code> 不冒泡</td><td>事件委托使用 <code>pointerover/out</code></td></tr></tbody></table><p>实际开发中，最需要掌握的是前三项加上 <code>pointercancel</code> 和 <code>pointerId</code>。 掌握这五点，基本就可以使用 Pointer Events 完成常见的 PC 与移动端拖拽、滑动交互。</p></section><section><h2>Pointer事件的event对象<a href="#pointer事件的event对象"><span>#</span></a></h2><p>Pointer 事件触发时，浏览器会向事件处理函数传入一个 <code>PointerEvent</code> 对象，用于获取指针类型、坐标、按键状态、压力等信息。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointerdown'</span><span><span>, (</span><span>event</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>event</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>event</span><span>.</span></span><span>pointerType</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>event</span><span>.</span></span><span>clientX</span><span><span>, </span><span>event</span><span>.</span></span><span>clientY</span><span>);</span></div></div><div><div><div>5</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>PointerEvent 继承自 MouseEvent，因此既可以使用鼠标事件的属性，也可以使用 Pointer 事件独有的属性。</p><ol>
<li>event 对象的常用属性</li>
</ol>

<table><thead><tr><th>属性</th><th>说明</th></tr></thead><tbody><tr><td><code>pointerId</code></td><td>当前指针的唯一标识，用于区分多个活动指针</td></tr><tr><td><code>pointerType</code></td><td>指针设备类型：<code>mouse</code>、<code>touch</code>、<code>pen</code></td></tr><tr><td><code>isPrimary</code></td><td>是否为当前指针类型的主指针</td></tr><tr><td><code>clientX</code> / <code>clientY</code></td><td>指针相对于浏览器视口的坐标</td></tr><tr><td><code>pageX</code> / <code>pageY</code></td><td>指针相对于文档的坐标</td></tr><tr><td><code>screenX</code> / <code>screenY</code></td><td>指针相对于屏幕的坐标</td></tr><tr><td><code>offsetX</code> / <code>offsetY</code></td><td>指针相对于事件目标元素内边距边缘的坐标</td></tr><tr><td><code>button</code></td><td>本次事件中发生状态变化的按键</td></tr><tr><td><code>buttons</code></td><td>当前按下的按键组合</td></tr><tr><td><code>pressure</code></td><td>指针压力，范围为 <code>0～1</code></td></tr><tr><td><code>width</code> / <code>height</code></td><td>指针接触区域的宽度和高度</td></tr><tr><td><code>target</code></td><td>事件的目标元素</td></tr><tr><td><code>currentTarget</code></td><td>当前正在执行事件监听器的元素</td></tr><tr><td><code>type</code></td><td>当前事件名称，如 <code>pointerdown</code></td></tr><tr><td><code>preventDefault()</code></td><td>阻止可取消事件的默认行为</td></tr></tbody></table><ol>
<li>pointerType：判断指针设备</li>
</ol><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointerdown'</span><span><span>, (</span><span>event</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>if</span><span><span> (</span><span>event</span><span>.</span></span><span>pointerType</span><span> </span><span>===</span><span> </span><span>'mouse'</span><span>) {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'鼠标操作'</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>} </span><span>else</span><span> </span><span>if</span><span><span> (</span><span>event</span><span>.</span></span><span>pointerType</span><span> </span><span>===</span><span> </span><span>'touch'</span><span>) {</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'触摸操作'</span><span>);</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>} </span><span>else</span><span> </span><span>if</span><span><span> (</span><span>event</span><span>.</span></span><span>pointerType</span><span> </span><span>===</span><span> </span><span>'pen'</span><span>) {</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'触控笔操作'</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>通过 <code>pointerType</code>，可以在同一套事件逻辑中区分 PC 和移动端输入设备。</p><ol>
<li>pointerId 与 isPrimary：区分多点触控</li>
</ol><ul>
<li><code>pointerId</code>：区分不同的指针，例如两根手指同时触摸屏幕，会分别对应不同的 ID。</li>
<li><code>isPrimary</code>：判断当前指针是否为该设备类型的主指针。例如，多指触摸时，通常第一根手指为主指针。</li>
</ul><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointerdown'</span><span><span>, (</span><span>event</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>if</span><span> (</span><span>!</span><span><span>event</span><span>.</span></span><span>isPrimary</span><span>) </span><span>return</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'主指针ID：'</span><span><span>, </span><span>event</span><span>.</span></span><span>pointerId</span><span>);</span></div></div><div><div><div>5</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意：<code>pointerId</code> 不是永久唯一的，指针结束后，其 ID 可能被重新使用。</p><ol>
<li>坐标属性</li>
</ol><p>最常用的是 <code>clientX</code> 和 <code>clientY</code>。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointermove'</span><span><span>, (</span><span>event</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>event</span><span>.</span></span><span>clientX</span><span><span>, </span><span>event</span><span>.</span></span><span>clientY</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>event</span><span>.</span></span><span>pageX</span><span><span>, </span><span>event</span><span>.</span></span><span>pageY</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>event</span><span>.</span></span><span>offsetX</span><span><span>, </span><span>event</span><span>.</span></span><span>offsetY</span><span>);</span></div></div><div><div><div>5</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>拖拽开发通常使用 <code>clientX/clientY</code> 计算移动距离。</p><ol>
<li>button 与 buttons：判断按键</li>
</ol>

<table><thead><tr><th>属性</th><th>常见取值</th><th>说明</th></tr></thead><tbody><tr><td><code>button</code></td><td><code>0</code></td><td>主按键（通常是鼠标左键）</td></tr><tr><td><code>button</code></td><td><code>1</code></td><td>鼠标中键</td></tr><tr><td><code>button</code></td><td><code>2</code></td><td>次按键（通常是鼠标右键）</td></tr><tr><td><code>button</code></td><td><code>-1</code></td><td>本次事件没有按键状态变化</td></tr><tr><td><code>buttons</code></td><td><code>0</code></td><td>没有按键按下</td></tr><tr><td><code>buttons</code></td><td><code>1</code></td><td>主按键处于按下状态</td></tr><tr><td><code>buttons</code></td><td><code>2</code></td><td>次按键处于按下状态</td></tr><tr><td><code>buttons</code></td><td><code>4</code></td><td>中键处于按下状态</td></tr></tbody></table><p><code>buttons</code> 是位掩码，可以同时表示多个按键。</p><p>例如，只在鼠标左键按下时执行：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>box</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'pointermove'</span><span><span>, (</span><span>event</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>if</span><span><span> (</span><span>event</span><span>.</span></span><span>pointerType</span><span> </span><span>===</span><span> </span><span>'mouse'</span><span> </span><span>&amp;&amp;</span><span><span> </span><span>event</span><span>.</span></span><span>buttons</span><span> </span><span>&amp;</span><span> </span><span>1</span><span>) {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'鼠标左键正在拖动'</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ol>
<li>其他属性（了解即可）</li>
</ol><p>这些主要用于触控笔、绘图软件等特殊场景。</p>

<table><thead><tr><th>属性</th><th>说明</th></tr></thead><tbody><tr><td><code>tiltX</code></td><td>触控笔 X 方向倾斜角度</td></tr><tr><td><code>tiltY</code></td><td>触控笔 Y 方向倾斜角度</td></tr><tr><td><code>twist</code></td><td>触控笔的旋转角度</td></tr><tr><td><code>tangentialPressure</code></td><td>触控笔的切向压力</td></tr><tr><td><code>altitudeAngle</code></td><td>触控笔相对于屏幕平面的角度</td></tr><tr><td><code>azimuthAngle</code></td><td>触控笔在屏幕平面上的方向角度</td></tr></tbody></table><p>这些属性的实际数据取决于硬件支持情况。</p><p>总结</p><p>对于普通 Web 开发，重点掌握以下属性即可：</p>

<table><thead><tr><th>使用场景</th><th>重点属性</th></tr></thead><tbody><tr><td>判断鼠标、触摸屏、触控笔</td><td><code>pointerType</code></td></tr><tr><td>单指拖拽、多点触控</td><td><code>pointerId</code>、<code>isPrimary</code></td></tr><tr><td>获取指针位置、计算拖拽距离</td><td><code>clientX</code>、<code>clientY</code></td></tr><tr><td>判断鼠标按键</td><td><code>button</code>、<code>buttons</code></td></tr><tr><td>判断事件目标</td><td><code>target</code>、<code>currentTarget</code></td></tr><tr><td>绘图、手写板</td><td><code>pressure</code>、<code>tiltX</code>、<code>tiltY</code></td></tr></tbody></table><p>学习重点： <code>pointerType</code>、<code>pointerId</code>、<code>clientX/clientY</code>、<code>button/buttons</code>。其他属性根据项目需求再掌握即可。</p></section><section><h2>单指拖拽<a href="#单指拖拽"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box"</span><span>&gt;拖动我&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>  </span><span>.box</span><span> {</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>position: </span><span>fixed</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>left: </span><span><span>50</span><span>px</span></span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>top: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>width: </span><span><span>120</span><span>px</span></span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>height: </span><span><span>120</span><span>px</span></span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>background-color: </span><span>skyblue</span><span>;</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>justify-content: </span><span>center</span><span>;</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>align-items: </span><span>center</span><span>;</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>touch-action: </span><span>none</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>user-select: </span><span>none</span><span>;</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>cursor: </span><span>grab</span><span>;</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>21</div></div><div><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>24</div></div><div><span>  </span><span>const</span><span> </span><span>box</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelector</span><span>(</span><span>'.box'</span><span>);</span></div></div><div><div><div>25</div></div><div>
</div></div><div><div><div>26</div></div><div><span>  </span><span>let</span><span><span> </span><span>startX</span><span> </span></span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>27</div></div><div><span>  </span><span>let</span><span><span> </span><span>startY</span><span> </span></span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>28</div></div><div><span>  </span><span>let</span><span><span> </span><span>startLeft</span><span> </span></span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>29</div></div><div><span>  </span><span>let</span><span><span> </span><span>startTop</span><span> </span></span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>30</div></div><div><span>  </span><span>let</span><span><span> </span><span>dragging</span><span> </span></span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>31</div></div><div><span>  </span><span>let</span><span><span> </span><span>activePointerId</span><span> </span></span><span>=</span><span> </span><span>null</span><span>;</span></div></div><div><div><div>32</div></div><div>
</div></div><div><div><div>33</div></div><div><span>  </span><span>// 记录当前按下的触摸指针</span></div></div><div><div><div>34</div></div><div><span>  </span><span>const</span><span> </span><span>activeTouches</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span>();</span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span><span>  </span></span><span>window</span><span>.</span><span>addEventListener</span><span>(</span></div></div><div><div><div>37</div></div><div><span>    </span><span>'pointerdown'</span><span>,</span></div></div><div><div><div>38</div></div><div><span><span>    </span></span><span>(</span><span>event</span><span>) </span><span>=&gt;</span><span> {</span></div></div><div><div><div>39</div></div><div><span>      </span><span>if</span><span><span> (</span><span>event</span><span>.</span></span><span>pointerType</span><span> </span><span>!==</span><span> </span><span>'touch'</span><span>) </span><span>return</span><span>;</span></div></div><div><div><div>40</div></div><div>
</div></div><div><div><div>41</div></div><div><span><span>      </span></span><span>activeTouches</span><span>.</span><span>add</span><span><span>(</span><span>event</span><span>.</span></span><span>pointerId</span><span>);</span></div></div><div><div><div>42</div></div><div>
</div></div><div><div><div>43</div></div><div><span>      </span><span>// 多指触摸时取消拖拽</span></div></div><div><div><div>44</div></div><div><span>      </span><span>if</span><span><span> (</span><span>activeTouches</span><span>.</span></span><span>size</span><span> </span><span>&gt;</span><span> </span><span>1</span><span>) {</span></div></div><div><div><div>45</div></div><div><span><span>        </span></span><span>dragging</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>46</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>47</div></div><div><span><span>    </span></span><span>},</span></div></div><div><div><div>48</div></div><div><span>    </span><span>true</span><span>,</span></div></div><div><div><div>49</div></div><div><span><span>  </span></span><span>);</span></div></div><div><div><div>50</div></div><div>
</div></div><div><div><div>51</div></div><div><span><span>  </span></span><span>box</span><span>.</span><span>addEventListener</span><span>(</span><span>'pointerdown'</span><span><span>, (</span><span>event</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>52</div></div><div><span>    </span><span>// 鼠标仅允许左键拖拽</span></div></div><div><div><div>53</div></div><div><span>    </span><span>if</span><span><span> (</span><span>event</span><span>.</span></span><span>pointerType</span><span> </span><span>===</span><span> </span><span>'mouse'</span><span> </span><span>&amp;&amp;</span><span><span> </span><span>event</span><span>.</span></span><span>button</span><span> </span><span>!==</span><span> </span><span>0</span><span>) </span><span>return</span><span>;</span></div></div><div><div><div>54</div></div><div>
</div></div><div><div><div>55</div></div><div><span>    </span><span>// 只允许单指拖拽</span></div></div><div><div><div>56</div></div><div><span>    </span><span>if</span><span><span> (</span><span>event</span><span>.</span></span><span>pointerType</span><span> </span><span>===</span><span> </span><span>'touch'</span><span> </span><span>&amp;&amp;</span><span><span> </span><span>activeTouches</span><span>.</span></span><span>size</span><span> </span><span>!==</span><span> </span><span>1</span><span>) </span><span>return</span><span>;</span></div></div><div><div><div>57</div></div><div>
</div></div><div><div><div>58</div></div><div><span>    </span><span>if</span><span><span> (</span><span>activePointerId</span><span> </span></span><span>!==</span><span> </span><span>null</span><span>) </span><span>return</span><span>;</span></div></div><div><div><div>59</div></div><div>
</div></div><div><div><div>60</div></div><div><span>    </span><span>const</span><span> </span><span>rect</span><span> </span><span>=</span><span><span> </span><span>box</span><span>.</span></span><span>getBoundingClientRect</span><span>();</span></div></div><div><div><div>61</div></div><div>
</div></div><div><div><div>62</div></div><div><span>    </span><span>// 记录指针初始坐标</span></div></div><div><div><div>63</div></div><div><span><span>    </span></span><span>startX</span><span> </span><span>=</span><span><span> </span><span>event</span><span>.</span></span><span>clientX</span><span>;</span></div></div><div><div><div>64</div></div><div><span><span>    </span></span><span>startY</span><span> </span><span>=</span><span><span> </span><span>event</span><span>.</span></span><span>clientY</span><span>;</span></div></div><div><div><div>65</div></div><div>
</div></div><div><div><div>66</div></div><div><span>    </span><span>// 记录元素初始位置</span></div></div><div><div><div>67</div></div><div><span><span>    </span></span><span>startLeft</span><span> </span><span>=</span><span><span> </span><span>rect</span><span>.</span></span><span>left</span><span>;</span></div></div><div><div><div>68</div></div><div><span><span>    </span></span><span>startTop</span><span> </span><span>=</span><span><span> </span><span>rect</span><span>.</span></span><span>top</span><span>;</span></div></div><div><div><div>69</div></div><div>
</div></div><div><div><div>70</div></div><div><span><span>    </span></span><span>dragging</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>71</div></div><div><span><span>    </span></span><span>activePointerId</span><span> </span><span>=</span><span><span> </span><span>event</span><span>.</span></span><span>pointerId</span><span>;</span></div></div><div><div><div>72</div></div><div>
</div></div><div><div><div>73</div></div><div><span>    </span><span>// 捕获指针</span></div></div><div><div><div>74</div></div><div><span><span>    </span></span><span>box</span><span>.</span><span>setPointerCapture</span><span><span>(</span><span>event</span><span>.</span></span><span>pointerId</span><span>);</span></div></div><div><div><div>75</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>76</div></div><div>
</div></div><div><div><div>77</div></div><div><span><span>  </span></span><span>box</span><span>.</span><span>addEventListener</span><span>(</span><span>'pointermove'</span><span><span>, (</span><span>event</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>78</div></div><div><span>    </span><span>if</span><span> (</span><span>!</span><span><span>dragging</span><span> </span></span><span>||</span><span><span> </span><span>event</span><span>.</span></span><span>pointerId</span><span> </span><span>!==</span><span><span> </span><span>activePointerId</span><span>) </span></span><span>return</span><span>;</span></div></div><div><div><div>79</div></div><div>
</div></div><div><div><div>80</div></div><div><span>    </span><span>// 计算指针移动距离</span></div></div><div><div><div>81</div></div><div><span>    </span><span>const</span><span> </span><span>moveX</span><span> </span><span>=</span><span><span> </span><span>event</span><span>.</span></span><span>clientX</span><span> </span><span>-</span><span><span> </span><span>startX</span><span>;</span></span></div></div><div><div><div>82</div></div><div><span>    </span><span>const</span><span> </span><span>moveY</span><span> </span><span>=</span><span><span> </span><span>event</span><span>.</span></span><span>clientY</span><span> </span><span>-</span><span><span> </span><span>startY</span><span>;</span></span></div></div><div><div><div>83</div></div><div>
</div></div><div><div><div>84</div></div><div><span>    </span><span>// 更新元素位置</span></div></div><div><div><div>85</div></div><div><span><span>    </span></span><span>box</span><span>.</span><span>style</span><span>.</span><span>left</span><span> </span><span>=</span><span> </span><span>`</span><span>${</span><span>startLeft</span><span> </span><span>+</span><span> </span><span>moveX</span><span>}</span><span>px`</span><span>;</span></div></div><div><div><div>86</div></div><div><span><span>    </span></span><span>box</span><span>.</span><span>style</span><span>.</span><span>top</span><span> </span><span>=</span><span> </span><span>`</span><span>${</span><span>startTop</span><span> </span><span>+</span><span> </span><span>moveY</span><span>}</span><span>px`</span><span>;</span></div></div><div><div><div>87</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>88</div></div><div>
</div></div><div><div><div>89</div></div><div><span>  </span><span>function</span><span> </span><span>stopDrag</span><span><span>(</span><span>event</span><span>) {</span></span></div></div><div><div><div>90</div></div><div><span>    </span><span>if</span><span><span> (</span><span>event</span><span>.</span></span><span>pointerType</span><span> </span><span>===</span><span> </span><span>'touch'</span><span>) {</span></div></div><div><div><div>91</div></div><div><span><span>      </span></span><span>activeTouches</span><span>.</span><span>delete</span><span><span>(</span><span>event</span><span>.</span></span><span>pointerId</span><span>);</span></div></div><div><div><div>92</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>93</div></div><div>
</div></div><div><div><div>94</div></div><div><span>    </span><span>if</span><span><span> (</span><span>event</span><span>.</span></span><span>pointerId</span><span> </span><span>===</span><span><span> </span><span>activePointerId</span><span>) {</span></span></div></div><div><div><div>95</div></div><div><span><span>      </span></span><span>dragging</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>96</div></div><div><span><span>      </span></span><span>activePointerId</span><span> </span><span>=</span><span> </span><span>null</span><span>;</span></div></div><div><div><div>97</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>98</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>99</div></div><div>
</div></div><div><div><div>100</div></div><div><span><span>  </span></span><span>window</span><span>.</span><span>addEventListener</span><span>(</span><span>'pointerup'</span><span><span>, </span><span>stopDrag</span><span>);</span></span></div></div><div><div><div>101</div></div><div><span><span>  </span></span><span>window</span><span>.</span><span>addEventListener</span><span>(</span><span>'pointercancel'</span><span><span>, </span><span>stopDrag</span><span>);</span></span></div></div><div><div><div>102</div></div><div><span>&lt;/</span><span>script</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102206-yi-bu-async-he-await/</id>
      <title type="text">异步async和await</title>
      <published>2026-10-22T07:17:41.000Z</published>
      <updated>2026-10-22T07:17:41.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102206-yi-bu-async-he-await/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>async和await使基于Promise的异步操作更简洁方便，Promise是解决回调地狱问题，async和await则是使异步的代码看起来像同步的代码，更容易理解</p>
<section><h1>async和await是什么<a href="#async和await是什么"><span>#</span></a></h1><p>可以声明一个async函数，表示函数里面有异步操作，一般只有在async函数中才能使用await；</p><p>await异步等待，表示紧跟在await后面的是异步的，需要等待结果，await需要和async一起使用</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>async</span><span> </span><span>function</span><span> </span><span>fn</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>const</span><span> </span><span>result</span><span> </span><span>=</span><span> </span><span>await</span><span> </span><span>异步操作</span><span><span>(</span><span>Promise对象</span><span>)</span></span></div></div><div><div><div>3</div></div><div><span><span> </span></span><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>为什么用？使异步操作更简洁方便；使异步代码看起来像同步，更容易理解</p></section>
<section><h1>使用async 和 await<a href="#使用async-和-await"><span>#</span></a></h1><p>实现一个效果，一个广告图片一开始是消失的，然后隔几秒显示，然后又消失</p><p>回调函数方式：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!</span><span>DOCTYPE</span><span> </span><span>html</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>html</span><span> </span><span>lang</span><span>=</span><span>"en"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;</span><span>head</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>&lt;</span><span>meta</span><span> </span><span>charset</span><span>=</span><span>"UTF-8"</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>&lt;</span><span>meta</span><span> </span><span>name</span><span>=</span><span>"viewport"</span><span> </span><span>content</span><span>=</span><span>"width=device-width, initial-scale=1.0"</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>&lt;</span><span>title</span><span>&gt;Document&lt;/</span><span>title</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span>    </span><span>.ad</span><span>{</span></div></div><div><div><div>9</div></div><div><span><span>      </span></span><span>display: </span><span>block</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>      </span></span><span>width: </span><span><span>300</span><span>px</span></span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>      </span></span><span>height: </span><span><span>150</span><span>px</span></span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>      </span></span><span>margin: </span><span>0</span><span><span> </span><span>auto</span><span>;</span></span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span>    </span><span>.none</span><span>{</span></div></div><div><div><div>15</div></div><div><span><span>      </span></span><span>display: </span><span>none</span><span>;</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>18</div></div><div><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>19</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"./ad.jpg"</span><span> </span><span>alt</span><span>=</span><span>""</span><span> </span><span>class</span><span>=</span><span>"ad none"</span><span> </span><span>id</span><span>=</span><span>"ad"</span><span>&gt;</span></div></div><div><div><div>21</div></div><div><span><span>  </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>22</div></div><div><span>    </span><span>//  回调函数</span></div></div><div><div><div>23</div></div><div><span>    </span><span>function</span><span> </span><span>ad</span><span> () {</span></div></div><div><div><div>24</div></div><div><span>      </span><span>// 获取DOM</span></div></div><div><div><div>25</div></div><div><span>      </span><span>const</span><span> </span><span>$ad</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>'ad'</span><span>);</span></div></div><div><div><div>26</div></div><div><span>      </span><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>27</div></div><div><span>        </span><span>// 1S后移除</span></div></div><div><div><div>28</div></div><div><span><span>        </span></span><span>$ad</span><span>.</span><span>classList</span><span>.</span><span>remove</span><span>(</span><span>'none'</span><span>)</span></div></div><div><div><div>29</div></div><div><span>        </span><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>30</div></div><div><span>          </span><span>// 2S后隐藏</span></div></div><div><div><div>31</div></div><div><span><span>          </span></span><span>$ad</span><span>.</span><span>classList</span><span>.</span><span>add</span><span>(</span><span>'none'</span><span>)</span></div></div><div><div><div>32</div></div><div><span><span>        </span></span><span>}, </span><span>2000</span><span>)</span></div></div><div><div><div>33</div></div><div><span><span>      </span></span><span>}, </span><span>1000</span><span>)</span></div></div><div><div><div>34</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>35</div></div><div><span>    </span><span>ad</span><span>()</span></div></div><div><div><div>36</div></div><div><span><span>  </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>37</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div><div><div><div>38</div></div><div><span>&lt;/</span><span>html</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>Promise方式</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>wait</span><span><span> (</span><span>ms</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>    </span><span>return</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>((</span><span>resolve</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>3</div></div><div><span>        </span><span>setTimeout</span><span><span>(</span><span>resolve</span><span>, </span><span>ms</span><span>)</span></span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>})</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>function</span><span> </span><span>ad</span><span> () {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>const</span><span> </span><span>$ad</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>'ad'</span><span>);</span></div></div><div><div><div>8</div></div><div><span>    </span><span>wait</span><span>(</span><span>1000</span><span>).</span><span>then</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>9</div></div><div><span>        </span><span>// 1S后显示ad</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>$ad</span><span>.</span><span>classList</span><span>.</span><span>remove</span><span>(</span><span>'none'</span><span>)</span></div></div><div><div><div>11</div></div><div><span>        </span><span>return</span><span> </span><span>wait</span><span>(</span><span>2000</span><span>)</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>}).</span><span>then</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>13</div></div><div><span>        </span><span>// 2S后隐藏ad</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>$ad</span><span>.</span><span>classList</span><span>.</span><span>add</span><span>(</span><span>'none'</span><span>)</span></div></div><div><div><div>15</div></div><div><span>        </span><span>return</span><span> </span><span>wait</span><span>(</span><span>3000</span><span>)</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>}).</span><span>then</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>17</div></div><div><span>        </span><span>// 3S后重新显示ad</span></div></div><div><div><div>18</div></div><div><span><span>        </span></span><span>$ad</span><span>.</span><span>classList</span><span>.</span><span>remove</span><span>(</span><span>'none'</span><span>)</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>})</span></div></div><div><div><div>20</div></div><div><span>}</span></div></div><div><div><div>21</div></div><div><span>ad</span><span>()</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>async方式</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>wait</span><span><span> (</span><span>ms</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>    </span><span>return</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>((</span><span>resolve</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>3</div></div><div><span>        </span><span>setTimeout</span><span><span>(</span><span>resolve</span><span>, </span><span>ms</span><span>)</span></span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>})</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>async</span><span> </span><span>function</span><span> </span><span>ad</span><span> () {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>const</span><span> </span><span>$ad</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>'ad'</span><span>);</span></div></div><div><div><div>8</div></div><div><span>    </span><span>await</span><span> </span><span>wait</span><span>(</span><span>1000</span><span>)</span></div></div><div><div><div>9</div></div><div><span>    </span><span>// 1S后显示ad</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>$ad</span><span>.</span><span>classList</span><span>.</span><span>remove</span><span>(</span><span>'none'</span><span>)</span></div></div><div><div><div>11</div></div><div><span>    </span><span>await</span><span> </span><span>wait</span><span>(</span><span>2000</span><span>)</span></div></div><div><div><div>12</div></div><div><span>    </span><span>// 2S后隐藏ad</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>$ad</span><span>.</span><span>classList</span><span>.</span><span>add</span><span>(</span><span>'none'</span><span>)</span></div></div><div><div><div>14</div></div><div><span>    </span><span>await</span><span> </span><span>wait</span><span>(</span><span>3000</span><span>)</span></div></div><div><div><div>15</div></div><div><span>    </span><span>// 3S后重新显示ad</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>$ad</span><span>.</span><span>classList</span><span>.</span><span>remove</span><span>(</span><span>'none'</span><span>)</span></div></div><div><div><div>17</div></div><div><span>}</span></div></div><div><div><div>18</div></div><div><span>ad</span><span>()</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h1>async函数的返回值<a href="#async函数的返回值"><span>#</span></a></h1><p>async函数的返回值是Promise对象，观察：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>async</span><span> </span><span>function</span><span> </span><span>fn</span><span> () {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>return</span><span> </span><span>'hello world'</span></div></div><div><div><div>3</div></div><div><span>    </span><span>//相当于</span></div></div><div><div><div>4</div></div><div><span>    </span><span>return</span><span> </span><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>'hello world'</span><span>)</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>fn</span><span>());</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>async函数的各种形式<a href="#async函数的各种形式"><span>#</span></a></h1><p>函数声明：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>async</span><span> </span><span>function</span><span> </span><span>fn</span><span> () {}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>函数表达式</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>fn</span><span> </span><span>=</span><span> </span><span>async</span><span> </span><span>function</span><span>(){}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>箭头函数</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>fn</span><span> </span><span>=</span><span> </span><span>async</span><span>()</span><span>=&gt;</span><span>{}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>箭头函数单参数</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>fn</span><span> </span><span>=</span><span> </span><span>async</span><span><span> </span><span>param</span><span> </span></span><span>=&gt;</span><span> {}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>对象方法</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>fn</span><span>:</span><span>async</span><span> </span><span>function</span><span>(){},</span></div></div><div><div><div>3</div></div><div><span>    </span><span>fn1</span><span>:</span><span>async</span><span> ()</span><span>=&gt;</span><span>{},</span></div></div><div><div><div>4</div></div><div><span>  </span><span>async</span><span> </span><span>fn</span><span>(){}</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>class的方法</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>ClassName</span><span>{</span></div></div><div><div><div>2</div></div><div><span>  </span><span>async</span><span> </span><span>fn</span><span>(){}</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>async函数的注意事项<a href="#async函数的注意事项"><span>#</span></a></h1><p>async函数返回值是一个成功状态的Promise，如果需要失败的，需要手动设置</p><p>第一种方式：使用Promise.reject</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>    </span><span>async</span><span> </span><span>function</span><span> </span><span>fn</span><span> () {</span></div></div><div><div><div>2</div></div><div><span>      </span><span>// return 123</span></div></div><div><div><div>3</div></div><div><span>      </span><span>return</span><span> </span><span>Promise</span><span>.</span><span>reject</span><span>(</span><span>new</span><span> </span><span>Error</span><span>(</span><span>'出错了'</span><span>))</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>    </span><span>fn</span><span>().</span><span>catch</span><span><span>(</span><span>err</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>7</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>err</span><span>);</span></span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>})</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>fn</span><span>());</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>第二种方式，使用throw new Error，当然，这没必要可以去报错，如果逻辑错误了，Promise就是失败态</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>async</span><span> </span><span>function</span><span> </span><span>fn</span><span> () {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>// return 123</span></div></div><div><div><div>3</div></div><div><span>    </span><span>// return Promise.reject(new Error('出错了'))</span></div></div><div><div><div>4</div></div><div><span>    </span><span>try</span><span> {</span></div></div><div><div><div>5</div></div><div><span>        </span><span>throw</span><span> </span><span>new</span><span> </span><span>Error</span><span>(</span><span>'出错了'</span><span>)</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>} </span><span>catch</span><span><span> (</span><span>error</span><span>) {</span></span></div></div><div><div><div>7</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>error</span><span>);</span></span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>fn</span><span>());</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>async函数可以没有await，反过来则不行</p></section>
<section><h1>await的机制<a href="#await的机制"><span>#</span></a></h1><p>沿用之前广告显示隐藏的例子</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>wait</span><span><span> (</span><span>ms</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>    </span><span>return</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>((</span><span>resolve</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>3</div></div><div><span>        </span><span>setTimeout</span><span><span>(</span><span>resolve</span><span>, </span><span>ms</span><span>)</span></span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>})</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>async</span><span> </span><span>function</span><span> </span><span>ad</span><span> () {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>const</span><span> </span><span>$ad</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>'ad'</span><span>);</span></div></div><div><div><div>8</div></div><div><span>    </span><span>await</span><span> </span><span>wait</span><span>(</span><span>1000</span><span>)</span></div></div><div><div><div>9</div></div><div><span>    </span><span>// 1S后显示ad</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>$ad</span><span>.</span><span>classList</span><span>.</span><span>remove</span><span>(</span><span>'none'</span><span>)</span></div></div><div><div><div>11</div></div><div><span>    </span><span>await</span><span> </span><span>wait</span><span>(</span><span>2000</span><span>)</span></div></div><div><div><div>12</div></div><div><span>    </span><span>// 2S后隐藏ad</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>$ad</span><span>.</span><span>classList</span><span>.</span><span>add</span><span>(</span><span>'none'</span><span>)</span></div></div><div><div><div>14</div></div><div><span>    </span><span>await</span><span> </span><span>wait</span><span>(</span><span>3000</span><span>)</span></div></div><div><div><div>15</div></div><div><span>    </span><span>// 3S后重新显示ad</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>$ad</span><span>.</span><span>classList</span><span>.</span><span>remove</span><span>(</span><span>'none'</span><span>)</span></div></div><div><div><div>17</div></div><div><span>}</span></div></div><div><div><div>18</div></div><div><span>ad</span><span>()</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>这里的<code>await wait(1000)</code>相当于阻塞了1秒后才执行后面的代码，相当于以下代码</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>wait</span><span>(</span><span>1000</span><span>).</span><span>then</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>// 1S后显示ad</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>$ad</span><span>.</span><span>classList</span><span>.</span><span>remove</span><span>(</span><span>'none'</span><span>)</span></div></div><div><div><div>4</div></div><div><span>    </span><span>return</span><span> </span><span>wait</span><span>(</span><span>2000</span><span>)</span></div></div><div><div><div>5</div></div><div><span>}).</span><span>then</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>// 2S后隐藏ad</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>$ad</span><span>.</span><span>classList</span><span>.</span><span>add</span><span>(</span><span>'none'</span><span>)</span></div></div><div><div><div>8</div></div><div><span>    </span><span>return</span><span> </span><span>wait</span><span>(</span><span>3000</span><span>)</span></div></div><div><div><div>9</div></div><div><span>}).</span><span>then</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>10</div></div><div><span>    </span><span>// 3S后重新显示ad</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>$ad</span><span>.</span><span>classList</span><span>.</span><span>remove</span><span>(</span><span>'none'</span><span>)</span></div></div><div><div><div>12</div></div><div><span>})</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>结论：async函数中的代码有先后关系，await会阻塞该async函数中代码的执行，注意：<code>await</code> 确实会暂停 <code>async</code> 函数后续代码的执行，但它不会阻塞整个 JavaScript 主线程</p></section>
<section><h1>await的值<a href="#await的值"><span>#</span></a></h1><p><code>await</code> 表达式的返回值，取决于它后面跟的是什么。<strong>核心规则：<code>await</code> 会等待 Promise 完成，并取出它成功完成时的结果；如果后面不是 Promise，则直接得到该值</strong>。</p>

<table><thead><tr><th><code>await</code> 后面的值</th><th><code>await</code> 表达式的结果</th></tr></thead><tbody><tr><td><code>Promise.resolve(100)</code></td><td><code>100</code></td></tr><tr><td><code>Promise.reject('失败')</code></td><td>抛出 <code>'失败'</code></td></tr><tr><td><code>100</code></td><td><code>100</code></td></tr><tr><td><code>'hello'</code></td><td><code>'hello'</code></td></tr><tr><td><code>{ age: 18 }</code></td><td><code>{ age: 18 }</code></td></tr><tr><td><code>fetch('/api/data')</code></td><td>请求成功后得到 <code>Response</code> 对象</td></tr></tbody></table></section>
<section><h1>await的注意事项<a href="#await的注意事项"><span>#</span></a></h1><ol>
<li>await 只能在 async 函数中使用；注意：ES 模块还支持在函数外使用顶层 <code>await</code>。</li>
</ol><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>async</span><span> </span><span>function</span><span> </span><span>fn</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>const</span><span> </span><span>result</span><span> </span><span>=</span><span> </span><span>await</span><span> </span><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>100</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>result</span><span>);</span></span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>fn</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ol>
<li>await 只暂停当前函数的后续执行；<code>await</code> 不会阻塞整个 JavaScript 主线程，其他代码仍然可以执行。</li>
</ol><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>async</span><span> </span><span>function</span><span> </span><span>fn</span><span>() {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>1</span><span>);</span></div></div><div><div><div>3</div></div><div><span>  </span><span>await</span><span> </span><span>Promise</span><span>.</span><span>resolve</span><span>();</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>2</span><span>);</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>fn</span><span>();</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>3</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ol>
<li>await 后面可以跟普通值，不一定是 Promise；如果后面不是 Promise 或其他 thenable 对象，<code>await</code> 会将其作为已经完成的值处理。</li>
</ol><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>async</span><span> </span><span>function</span><span> </span><span>fn</span><span>() {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>await</span><span> </span><span>100</span><span>); </span><span>// 100</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>await</span><span> </span><span>'hello'</span><span>); </span><span>// hello</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>fn</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ol>
<li>await 遇到 rejected Promise 会抛出错误；因此，等待可能失败的异步操作时，可以使用 <code>try...catch</code> 处理错误。</li>
</ol><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>async</span><span> </span><span>function</span><span> </span><span>fn</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>try</span><span> {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>const</span><span> </span><span>result</span><span> </span><span>=</span><span> </span><span>await</span><span> </span><span>Promise</span><span>.</span><span>reject</span><span>(</span><span>'请求失败'</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>} </span><span>catch</span><span><span> (</span><span>error</span><span>) {</span></span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>error</span><span>); </span></span><span>// 请求失败</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>fn</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ol>
<li>多个 await 默认按顺序等待</li>
</ol><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>async</span><span> </span><span>function</span><span> </span><span>fn</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>const</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>await</span><span> </span><span>task1</span><span>();</span></div></div><div><div><div>3</div></div><div><span>  </span><span>const</span><span> </span><span>b</span><span> </span><span>=</span><span> </span><span>await</span><span> </span><span>task2</span><span>();</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果 <code>task2()</code> 必须等待 <code>task1()</code> 完成后才能开始，这样写是合适的。</p><p>但如果两个任务相互独立，这样写会让它们依次执行，可以改为：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>async</span><span> </span><span>function</span><span> </span><span>fn</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>const</span><span> [</span><span>a</span><span>, </span><span>b</span><span>] </span><span>=</span><span> </span><span>await</span><span> </span><span>Promise</span><span>.</span><span>all</span><span>([</span></div></div><div><div><div>3</div></div><div><span>    </span><span>task1</span><span>(),</span></div></div><div><div><div>4</div></div><div><span>    </span><span>task2</span><span>()</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>]);</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这样两个任务可以同时启动，不必等待第一个任务完成后才启动第二个。</p><ol>
<li>不要误以为 await 会自动等待所有异步任务：例如，<code>forEach()</code> 不会等待异步回调全部执行完毕：</li>
</ol><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>async</span><span> </span><span>function</span><span> </span><span>fn</span><span>() {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>[</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>].</span><span>forEach</span><span>(</span><span>async</span><span><span> </span><span>item</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>await</span><span> </span><span>task</span><span><span>(</span><span>item</span><span>);</span></span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'执行完毕'</span><span>);</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这里的 <code>'执行完毕'</code> 不会等待所有 <code>task()</code> 完成。</p><p>如果需要依次执行，使用 <code>for...of</code>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>async</span><span> </span><span>function</span><span> </span><span>fn</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>for</span><span> (</span><span>const</span><span> </span><span>item</span><span> </span><span>of</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]) {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>await</span><span> </span><span>task</span><span><span>(</span><span>item</span><span>);</span></span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'全部执行完毕'</span><span>);</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果需要并发执行并等待全部完成，可以使用 <code>Promise.all()</code>。</p><section><h2>速记表<a href="#速记表"><span>#</span></a></h2>

<table><thead><tr><th>注意事项</th><th>核心要点</th></tr></thead><tbody><tr><td>使用位置</td><td><code>async</code> 函数中，或 ES 模块顶层</td></tr><tr><td>执行机制</td><td>暂停当前异步函数的后续执行，不阻塞主线程</td></tr><tr><td>等待对象</td><td>可以是 Promise，也可以是普通值</td></tr><tr><td>错误处理</td><td>Promise 被拒绝时，<code>await</code> 会抛出错误</td></tr><tr><td>多个任务</td><td>有依赖就顺序等待，互相独立可考虑 <code>Promise.all()</code></td></tr><tr><td>循环处理</td><td><code>forEach()</code> 不会等待异步回调完成</td></tr></tbody></table><p>其中，最值得掌握的是顺序等待与并发等待的区别，以及 <code>await</code> 的错误处理。这两点在实际开发中尤其常用。</p></section></section>
<section><h1>继发和并发<a href="#继发和并发"><span>#</span></a></h1><p>继发（顺序执行）前一个任务完成后，才开始执行下一个任务。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>async</span><span> </span><span>function</span><span> </span><span>fn</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>const</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>await</span><span> </span><span>task1</span><span>();</span></div></div><div><div><div>3</div></div><div><span>  </span><span>const</span><span> </span><span>b</span><span> </span><span>=</span><span> </span><span>await</span><span> </span><span>task2</span><span>();</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>);</span></span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>并发（同时启动）：多个任务不必等待彼此完成，可以同时启动，然后统一等待结果。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>async</span><span> </span><span>function</span><span> </span><span>fn</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>const</span><span> </span><span>p1</span><span> </span><span>=</span><span> </span><span>task1</span><span>();</span></div></div><div><div><div>3</div></div><div><span>  </span><span>const</span><span> </span><span>p2</span><span> </span><span>=</span><span> </span><span>task2</span><span>();</span></div></div><div><div><div>4</div></div><div><span>  </span><span>const</span><span> [</span><span>a</span><span>, </span><span>b</span><span>] </span><span>=</span><span> </span><span>await</span><span> </span><span>Promise</span><span>.</span><span>all</span><span><span>([</span><span>p1</span><span>, </span><span>p2</span><span>]);</span></span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>);</span></span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>项目应用实战<a href="#项目应用实战"><span>#</span></a></h1><section><h2>二级菜单<a href="#二级菜单"><span>#</span></a></h2><p>初始化代码</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!</span><span>DOCTYPE</span><span> </span><span>html</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>html</span><span> </span><span>lang</span><span>=</span><span>"en"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>head</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>meta</span><span> </span><span>charset</span><span>=</span><span>"UTF-8"</span><span> /&gt;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>&lt;</span><span>title</span><span>&gt;二级菜单&lt;/</span><span>title</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span>      </span><span>/* css reset */</span></div></div><div><div><div>8</div></div><div><span>      </span><span>*</span><span> {</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>padding: </span><span>0</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>margin: </span><span>0</span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>      </span><span>li</span><span> {</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>list-style: </span><span>none</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>      </span><span>/* menu */</span></div></div><div><div><div>17</div></div><div><span>      </span><span>.menu</span><span> {</span></div></div><div><div><div>18</div></div><div><span><span>        </span></span><span>width: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>19</div></div><div><span><span>        </span></span><span>background-color: </span><span>rgba</span><span>(</span><span>0</span><span>, </span><span>0</span><span>, </span><span>0</span><span>, </span><span>0.1</span><span>);</span></div></div><div><div><div>20</div></div><div><span><span>        </span></span><span>margin: </span><span><span>10</span><span>px</span></span><span>;</span></div></div><div><div><div>21</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>22</div></div><div><span>      </span><span>.menu-item</span><span> {</span></div></div><div><div><div>23</div></div><div><span><span>        </span></span><span>position: </span><span>relative</span><span>;</span></div></div><div><div><div>24</div></div><div><span><span>        </span></span><span>padding: </span><span><span>5</span><span>px</span></span><span>;</span></div></div><div><div><div>25</div></div><div><span><span>        </span></span><span>cursor: </span><span>pointer</span><span>;</span></div></div><div><div><div>26</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>27</div></div><div><span>      </span><span>.menu-content</span><span> {</span></div></div><div><div><div>28</div></div><div><span><span>        </span></span><span>display: </span><span>none</span><span>;</span></div></div><div><div><div>29</div></div><div><span><span>        </span></span><span>position: </span><span>absolute</span><span>;</span></div></div><div><div><div>30</div></div><div><span><span>        </span></span><span>left: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>31</div></div><div><span><span>        </span></span><span>top: </span><span>0</span><span>;</span></div></div><div><div><div>32</div></div><div><span><span>        </span></span><span>width: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>33</div></div><div><span><span>        </span></span><span>height: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>34</div></div><div><span><span>        </span></span><span>padding: </span><span>0</span><span> </span><span><span>5</span><span>px</span></span><span>;</span></div></div><div><div><div>35</div></div><div><span><span>        </span></span><span>background-color: </span><span>rgba</span><span>(</span><span>0</span><span>, </span><span>0</span><span>, </span><span>0</span><span>, </span><span>0.1</span><span>);</span></div></div><div><div><div>36</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>37</div></div><div><span>      </span><span><span>.menu-item</span><span>:hover</span></span><span> {</span></div></div><div><div><div>38</div></div><div><span><span>        </span></span><span>background-color: </span><span>rgba</span><span>(</span><span>0</span><span>, </span><span>0</span><span>, </span><span>0</span><span>, </span><span>0.4</span><span>);</span></div></div><div><div><div>39</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>40</div></div><div><span>      </span><span><span>.menu-item</span><span>:hover</span></span><span> </span><span>.menu-content</span><span> {</span></div></div><div><div><div>41</div></div><div><span><span>        </span></span><span>display: </span><span>block</span><span>;</span></div></div><div><div><div>42</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>43</div></div><div><span>      </span><span>.menu-loading</span><span> {</span></div></div><div><div><div>44</div></div><div><span><span>        </span></span><span>margin: </span><span><span>45</span><span>px</span></span><span> </span><span>0</span><span> </span><span>0</span><span> </span><span><span>92</span><span>px</span></span><span>;</span></div></div><div><div><div>45</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>46</div></div><div><span><span>    </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>47</div></div><div><span><span>  </span></span><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>48</div></div><div><span><span>  </span></span><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>49</div></div><div><span><span>    </span></span><span>&lt;</span><span>ul</span><span> </span><span>id</span><span>=</span><span>"menu"</span><span> </span><span>class</span><span>=</span><span>"menu"</span><span>&gt;</span></div></div><div><div><div>50</div></div><div><span>      </span><span>&lt;!-- &lt;li class="menu-item" data-key="hot" data-done="done"&gt;</span></div></div><div><div><div>51</div></div><div><span><span>        </span></span><span>&lt;span&gt;热门出发地&lt;/span&gt;</span></div></div><div><div><div>52</div></div><div><span><span>        </span></span><span>&lt;div class="menu-content"&gt;</span></div></div><div><div><div>53</div></div><div><span><span>          </span></span><span>&lt;img class="menu-loading" src="./loading.gif" alt="加载中" /&gt;</span></div></div><div><div><div>54</div></div><div><span><span>          </span></span><span>&lt;p&gt;内地热门城市&lt;/p&gt;</span></div></div><div><div><div>55</div></div><div><span><span>          </span></span><span>&lt;p&gt;热门景点&lt;/p&gt;</span></div></div><div><div><div>56</div></div><div><span><span>        </span></span><span>&lt;/div&gt;</span></div></div><div><div><div>57</div></div><div><span><span>      </span></span><span>&lt;/li&gt; --&gt;</span></div></div><div><div><div>58</div></div><div><span><span>    </span></span><span>&lt;/</span><span>ul</span><span>&gt;</span></div></div><div><div><div>59</div></div><div>
</div></div><div><div><div>60</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>61</div></div><div><span>      </span><span>// https://www.imooc.com/api/mall-PC/index/menu</span></div></div><div><div><div>62</div></div><div><span>      </span><span>// https://www.imooc.com/api/mall-PC/index/menu/hot</span></div></div><div><div><div>63</div></div><div><span>      </span><span>// https://www.imooc.com/api/mall-PC/index/menu/hk</span></div></div><div><div><div>64</div></div><div><span>      </span><span>function</span><span> </span><span>wait</span><span><span>(</span><span>ms</span><span>) {</span></span></div></div><div><div><div>65</div></div><div><span>        </span><span>return</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>(</span><span>resolve</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>66</div></div><div><span>          </span><span>setTimeout</span><span><span>(</span><span>resolve</span><span>, </span><span>ms</span><span>);</span></span></div></div><div><div><div>67</div></div><div><span><span>        </span></span><span>});</span></div></div><div><div><div>68</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>69</div></div><div><span>      </span><span>function</span><span> </span><span>getJSON</span><span><span>(</span><span>url</span><span>) {</span></span></div></div><div><div><div>70</div></div><div><span>        </span><span>return</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>(</span><span>resolve</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>71</div></div><div><span>          </span><span>const</span><span> </span><span>xhr</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>XMLHttpRequest</span><span>();</span></div></div><div><div><div>72</div></div><div>
</div></div><div><div><div>73</div></div><div><span><span>          </span></span><span>xhr</span><span>.</span><span>addEventListener</span><span>(</span></div></div><div><div><div>74</div></div><div><span>            </span><span>'load'</span><span>,</span></div></div><div><div><div>75</div></div><div><span>            </span><span>async</span><span> () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>76</div></div><div><span>              </span><span>if</span><span> (</span></div></div><div><div><div>77</div></div><div><span><span>                </span></span><span>(</span><span>xhr</span><span>.</span><span>status</span><span> </span><span>&gt;=</span><span> </span><span>200</span><span> </span><span>&amp;&amp;</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&lt;</span><span> </span><span>300</span><span>) </span><span>||</span></div></div><div><div><div>78</div></div><div><span><span>                </span></span><span>xhr</span><span>.</span><span>status</span><span> </span><span>===</span><span> </span><span>304</span></div></div><div><div><div>79</div></div><div><span><span>              </span></span><span>) {</span></div></div><div><div><div>80</div></div><div><span>                </span><span>// 模拟网络延迟</span></div></div><div><div><div>81</div></div><div><span>                </span><span>await</span><span> </span><span>wait</span><span>(</span><span>1000</span><span>);</span></div></div><div><div><div>82</div></div><div><span>                </span><span>resolve</span><span><span>(</span><span>xhr</span><span>.</span></span><span>response</span><span>);</span></div></div><div><div><div>83</div></div><div><span><span>              </span></span><span>}</span></div></div><div><div><div>84</div></div><div><span><span>            </span></span><span>},</span></div></div><div><div><div>85</div></div><div><span>            </span><span>false</span></div></div><div><div><div>86</div></div><div><span><span>          </span></span><span>);</span></div></div><div><div><div>87</div></div><div>
</div></div><div><div><div>88</div></div><div><span><span>          </span></span><span>xhr</span><span>.</span><span>open</span><span>(</span><span>'GET'</span><span><span>, </span><span>url</span><span>, </span></span><span>true</span><span>);</span></div></div><div><div><div>89</div></div><div>
</div></div><div><div><div>90</div></div><div><span><span>          </span></span><span>xhr</span><span>.</span><span>responseType</span><span> </span><span>=</span><span> </span><span>'json'</span><span>;</span></div></div><div><div><div>91</div></div><div>
</div></div><div><div><div>92</div></div><div><span><span>          </span></span><span>xhr</span><span>.</span><span>send</span><span>(</span><span>null</span><span>);</span></div></div><div><div><div>93</div></div><div><span><span>        </span></span><span>});</span></div></div><div><div><div>94</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>95</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>96</div></div><div><span><span>  </span></span><span>&lt;/</span><span>body</span><span>&gt;</span></div></div><div><div><div>97</div></div><div><span>&lt;/</span><span>html</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>实现：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>(</span><span>async</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>const</span><span> </span><span>url</span><span> </span><span>=</span><span> </span><span>'https://www.imooc.com/api/mall-PC/index/menu'</span></div></div><div><div><div>3</div></div><div><span>    </span><span>// 发送请求</span></div></div><div><div><div>4</div></div><div><span>    </span><span>const</span><span> </span><span>menuResult</span><span> </span><span>=</span><span> </span><span>await</span><span> </span><span>getJSON</span><span><span>(</span><span>url</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>const</span><span> </span><span>$menu</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>'menu'</span><span>)</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>menuResult</span><span>);</span></span></div></div><div><div><div>7</div></div><div><span>    </span><span>createMenu</span><span><span>(</span><span>$menu</span><span>, </span><span>menuResult</span><span>.</span></span><span>data</span><span>);</span></div></div><div><div><div>8</div></div><div><span>    </span><span>// 循环绑定事件,发送请求，获取数据，创建子菜单</span></div></div><div><div><div>9</div></div><div><span>    </span><span>const</span><span> </span><span>$item</span><span> </span><span>=</span><span><span>$menu</span><span>.</span></span><span>getElementsByClassName</span><span>(</span><span>'menu-item'</span><span>);</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>[</span><span>...</span><span><span>$item</span><span>].</span></span><span>forEach</span><span><span>(</span><span>$item</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>11</div></div><div><span><span>        </span></span><span>$item</span><span>.</span><span>addEventListener</span><span>(</span><span>'mouseenter'</span><span>, </span><span>async</span><span> () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>12</div></div><div><span>            </span><span>if</span><span><span> (</span><span>$item</span><span>.</span></span><span>dataset</span><span>.</span><span>done</span><span> </span><span>===</span><span> </span><span>'done'</span><span>) </span><span>return</span><span>;</span></div></div><div><div><div>13</div></div><div><span>            </span><span>const</span><span> </span><span>subMenuResul</span><span> </span><span>=</span><span> </span><span>await</span><span> </span><span>getJSON</span><span>(</span><span>`https://www.imooc.com/api/mall-PC/index/menu/</span><span>${</span><span>$item</span><span>.</span><span>dataset</span><span>.</span><span>key</span><span>}</span><span>`</span><span>)</span></div></div><div><div><div>14</div></div><div><span><span>            </span></span><span>$item</span><span>.</span><span>dataset</span><span>.</span><span>done</span><span> </span><span>=</span><span> </span><span>'done'</span></div></div><div><div><div>15</div></div><div><span><span>            </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>subMenuResul</span><span>);</span></span></div></div><div><div><div>16</div></div><div><span>            </span><span>createsubMenu</span><span><span>(</span><span>$item</span><span>, </span><span>subMenuResul</span><span>.</span></span><span>data</span><span>)</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>},</span><span>false</span><span>)</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>});</span></div></div><div><div><div>19</div></div><div><span>})()</span></div></div><div><div><div>20</div></div><div><span>function</span><span> </span><span>createMenu</span><span><span> (</span><span>$el</span><span>, </span><span>data</span><span>) {</span></span></div></div><div><div><div>21</div></div><div><span>    </span><span>let</span><span><span> </span><span>html</span><span> </span></span><span>=</span><span> </span><span>''</span></div></div><div><div><div>22</div></div><div><span>    </span><span>for</span><span> (</span><span>const</span><span> </span><span>item</span><span> </span><span>of</span><span><span> </span><span>data</span><span>) {</span></span></div></div><div><div><div>23</div></div><div><span><span>        </span></span><span>html</span><span> </span><span>+=</span><span> </span><span>`</span></div></div><div><div><div>24</div></div><div><span><span>          </span></span><span>&lt;li class="menu-item" data-key="</span><span>${</span><span>item</span><span>.</span><span>key</span><span>}</span><span>"&gt;</span></div></div><div><div><div>25</div></div><div><span><span>            </span></span><span>&lt;span&gt;</span><span>${</span><span>item</span><span>.</span><span>title</span><span>}</span><span>&lt;/span&gt;</span></div></div><div><div><div>26</div></div><div><span><span>            </span></span><span>&lt;div class="menu-content"&gt;</span></div></div><div><div><div>27</div></div><div><span><span>              </span></span><span>&lt;img class="menu-loading" src="./loading.gif" alt="加载中" /&gt;</span></div></div><div><div><div>28</div></div><div><span><span>             </span></span><span>`</span></div></div><div><div><div>29</div></div><div><span><span>        </span></span><span>$el</span><span>.</span><span>innerHTML</span><span> </span><span>=</span><span><span> </span><span>html</span></span></div></div><div><div><div>30</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>31</div></div><div><span>}</span></div></div><div><div><div>32</div></div><div><span>function</span><span> </span><span>createsubMenu</span><span><span> (</span><span>$el</span><span>, </span><span>data</span><span>) {</span></span></div></div><div><div><div>33</div></div><div><span>    </span><span>let</span><span><span> </span><span>html</span><span> </span></span><span>=</span><span> </span><span>''</span></div></div><div><div><div>34</div></div><div><span>    </span><span>for</span><span> (</span><span>const</span><span> </span><span>item</span><span> </span><span>of</span><span><span> </span><span>data</span><span>) {</span></span></div></div><div><div><div>35</div></div><div><span><span>        </span></span><span>html</span><span> </span><span>+=</span><span> </span><span>`</span></div></div><div><div><div>36</div></div><div><span><span>          </span></span><span>&lt;p&gt;</span><span>${</span><span>item</span><span>.</span><span>title</span><span>}</span><span>&lt;/p&gt;</span></div></div><div><div><div>37</div></div><div><span><span>         </span></span><span>`</span></div></div><div><div><div>38</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>39</div></div><div><span><span>    </span></span><span>$el</span><span>.</span><span>querySelector</span><span>(</span><span>'.menu-content'</span><span>).</span><span>innerHTML</span><span> </span><span>=</span><span><span> </span><span>html</span></span></div></div><div><div><div>40</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102205-qian-duan-ajaxfetch-yu-kua-yu-qing-qiu/</id>
      <title type="text">前端Ajax&amp;Fetch与跨域请求</title>
      <published>2026-10-22T00:55:59.000Z</published>
      <updated>2026-10-22T00:55:59.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102205-qian-duan-ajaxfetch-yu-kua-yu-qing-qiu/"/>
      <summary type="text">本文主要学习前端Ajax&amp;Fetch与跨域请求</summary>
      <content type="html"><![CDATA[<section><h1>原生Ajax<a href="#原生ajax"><span>#</span></a></h1><section><h2>初识 Ajax<a href="#初识-ajax"><span>#</span></a></h2><ul>
<li>Ajax是一种概念，XMLHttpRequest是实现的第一种方案，后续现代化使用Fetch，一般开发使用axios</li>
<li>Ajax 是 Asynchronous JavaScript and XML (异步 JavaScript 和 XML) 的简写</li>
<li>Ajax中的异步&lt;可以异步地向服务器发送请求&gt;，在等待响应的过程中，不会阻塞当前页面，浏览器可以做自己的事情。直到成功获取响应后，浏览器才开始处理响应数据</li>
<li><strong>使用 JavaScript 向服务器发送请求，并在不刷新整个页面的情况下更新页面数据。</strong></li>
<li>XML(可扩展标记语言)是前后端数据通信时传输数据的一种格式</li>
<li>XML现在已经不怎么用了，现在比较常用的是JSON</li>
<li>Ajax其实就是浏览器与服务器之间的一种异步通信方式</li>
<li>非服务器环境下，很多浏览器是无法使用Ajax，如直接打开文件，就无法使用Ajax</li>
</ul></section><section><h2>Ajax 的基本用法<a href="#ajax-的基本用法"><span>#</span></a></h2><ul>
<li>Ajax想要实现浏览器与服务器之间的异步通信，需要依靠XMLHttpRequest，它是一个构造函数</li>
<li>不论是XMLHttpRequest,还是Ajax,都没有和具体的某种数据格式绑定</li>
</ul><p><strong>XMLHttpRequest</strong></p><p>readystatechange事件监听 readyState 这个状态的变化//它的值从0~4，一共5个状态</p><ul>
<li>0&lt;未初始化&gt;。尚未调用open</li>
<li>1&lt;启动&gt;。已经调用open，但尚未调用send</li>
<li>2&lt;发送&gt;。已经调用send，但尚未接收到响应</li>
<li>3&lt;接收&gt;。已经接收到部分响应数据</li>
<li>4&lt;完成&gt;。已经接收到全部响应数据，而且已经可以在浏览器中使用了</li>
</ul><p><strong>使用步骤：</strong></p><p>为了兼容性，不要使用this，使用xhr，为了兼容性，在发送之前，监听事件</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 1. 创建一个 XMLHttpRequest 对象</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>xhr</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>XMLHttpRequest</span><span>();</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// 4.1. 监听请求状态的变化(推荐)</span></div></div><div><div><div>5</div></div><div><span><span>xhr</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'readystatechange'</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>// 5.1. 判断请求是否完成，网络层面，xhr.readyState === 4请求已经结束，可以拿到完整数据</span></div></div><div><div><div>7</div></div><div><span>    </span><span>if</span><span><span> (</span><span>xhr</span><span>.</span></span><span>readyState</span><span> </span><span>!==</span><span> </span><span>4</span><span>) </span><span>return</span><span>;</span></div></div><div><div><div>8</div></div><div><span>    </span><span>// 6.1. 判断请求是否成功，服务器层面</span></div></div><div><div><div>9</div></div><div><span>    </span><span>if</span><span><span> ((</span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&gt;=</span><span> </span><span>200</span><span> </span><span>&amp;&amp;</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&lt;</span><span> </span><span>300</span><span>) </span><span>||</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>===</span><span> </span><span>304</span><span>) {</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>})</span></div></div><div><div><div>12</div></div><div><span>// 4. 监听请求状态的变化,旧写法，兼容更好</span></div></div><div><div><div>13</div></div><div><span><span>xhr</span><span>.</span></span><span>onreadystatechange</span><span> </span><span>=</span><span> () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>14</div></div><div><span>    </span><span>// 5. 判断请求是否完成，网络层面，xhr.readyState === 4请求已经结束，可以拿到完整数据</span></div></div><div><div><div>15</div></div><div><span>    </span><span>if</span><span><span> (</span><span>xhr</span><span>.</span></span><span>readyState</span><span> </span><span>!==</span><span> </span><span>4</span><span>) </span><span>return</span><span>;</span></div></div><div><div><div>16</div></div><div><span>    </span><span>// 6. 判断请求是否成功，服务器层面</span></div></div><div><div><div>17</div></div><div><span>    </span><span>if</span><span><span> ((</span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&gt;=</span><span> </span><span>200</span><span> </span><span>&amp;&amp;</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&lt;</span><span> </span><span>300</span><span>) </span><span>||</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>===</span><span> </span><span>304</span><span>) {</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>19</div></div><div><span>}</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>// 2. 配置请求信息,准备发送请求（HTTP方法、URL,是否异步发送请求）</span></div></div><div><div><div>22</div></div><div><span><span>xhr</span><span>.</span></span><span>open</span><span>(</span><span>'GET'</span><span>, </span><span>'https://api.apihubs.cn/holiday/get'</span><span>, </span><span>true</span><span>);</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>// 3. 发送请求</span></div></div><div><div><div>25</div></div><div><span><span>xhr</span><span>.</span></span><span>send</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>完成前后端通讯：</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>url</span><span> </span><span>=</span><span> </span><span>'https://api.apihubs.cn/holiday/get'</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>xhr</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>XMLHttpRequest</span><span>();</span></div></div><div><div><div>4</div></div><div><span><span>xhr</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'readystatechange'</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>5</div></div><div><span>  </span><span>if</span><span><span> (</span><span>xhr</span><span>.</span></span><span>readyState</span><span> </span><span>!==</span><span> </span><span>4</span><span>) </span><span>return</span><span>;</span></div></div><div><div><div>6</div></div><div><span>  </span><span>if</span><span><span> (</span><span>xhr</span><span>.</span></span><span>readyState</span><span> </span><span>===</span><span> </span><span>4</span><span>) {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>if</span><span><span> ((</span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&gt;=</span><span> </span><span>200</span><span> </span><span>&amp;&amp;</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&lt;</span><span> </span><span>300</span><span>) </span><span>||</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>===</span><span> </span><span>304</span><span>) {</span></div></div><div><div><div>8</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>xhr</span><span>.</span></span><span>responseText</span><span>); </span><span>//数据作为字符串形式</span></div></div><div><div><div>9</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>typeof</span><span><span> </span><span>xhr</span><span>.</span></span><span>responseText</span><span>); </span><span>//string</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>});</span></div></div><div><div><div>13</div></div><div><span><span>xhr</span><span>.</span></span><span>open</span><span>(</span><span>'GET'</span><span><span>, </span><span>url</span><span>, </span></span><span>true</span><span>);</span></div></div><div><div><div>14</div></div><div><span><span>xhr</span><span>.</span></span><span>send</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>GET 请求<a href="#get-请求"><span>#</span></a></h2><p><strong>携带数据</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>url</span><span> </span><span>=</span><span> </span><span>'https://www.imooc.com/api/http/search/suggest'</span><span>;</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>xhr</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>XMLHttpRequest</span><span>();</span></div></div><div><div><div>3</div></div><div><span><span>xhr</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'readystatechange'</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span>    </span><span>if</span><span><span> (</span><span>xhr</span><span>.</span></span><span>readyState</span><span> </span><span>!==</span><span> </span><span>4</span><span>) </span><span>return</span><span>;</span></div></div><div><div><div>5</div></div><div><span>    </span><span>if</span><span><span> (</span><span>xhr</span><span>.</span></span><span>readyState</span><span> </span><span>===</span><span> </span><span>4</span><span>) {</span></div></div><div><div><div>6</div></div><div><span>        </span><span>if</span><span><span> ((</span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&gt;=</span><span> </span><span>200</span><span> </span><span>&amp;&amp;</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&lt;</span><span> </span><span>300</span><span>) </span><span>||</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>===</span><span> </span><span>304</span><span>) {</span></div></div><div><div><div>7</div></div><div><span><span>            </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>xhr</span><span>.</span></span><span>responseText</span><span>); </span><span>//数据作为字符串形式</span></div></div><div><div><div>8</div></div><div><span><span>            </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>typeof</span><span><span> </span><span>xhr</span><span>.</span></span><span>responseText</span><span>); </span><span>//string</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>});</span></div></div><div><div><div>12</div></div><div><span>//get通过请求头携带</span></div></div><div><div><div>13</div></div><div><span><span>xhr</span><span>.</span></span><span>open</span><span>(</span><span>'GET'</span><span>, </span><span>`</span><span>${</span><span>url</span><span>}</span><span>?words=js`</span><span>, </span><span>true</span><span>);</span></div></div><div><div><div>14</div></div><div><span><span>xhr</span><span>.</span></span><span>send</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>数据编码</strong></p><p>如果在get请求中携带中文，浏览器会自动编码，也就是说，其实直接传中文也没问题。但是不同浏览器的编码不同，后端最终得到的也会不一样的数据，所以需要统一编码，使用encodeURIComponent，还有的原因就是<strong>不是所有场景都会自动编码</strong>，如果使用浏览器 XHR、fetch通常会自动处理，但是自己拼接特殊字符，会有问题，encodeURIComponent编码不是很推荐，推荐使用URLSearchParams</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>name</span><span> </span><span>=</span><span> </span><span>'张三&amp;李四'</span><span>;</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>xhr</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>XMLHttpRequest</span><span>();</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>xhr</span><span>.</span></span><span>open</span><span>(</span><span>'GET'</span><span>, </span><span>`/test?name=</span><span>${</span><span>name</span><span>}</span><span>`</span><span>);</span></div></div><div><div><div>5</div></div><div><span>//浏览器发送/test?name=张三&amp;李四</span></div></div><div><div><div>6</div></div><div><span>//后端解析，参数就被截留了</span></div></div><div><div><div>7</div></div><div><span>//name = 张三</span></div></div><div><div><div>8</div></div><div><span>//李四 = ''</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>//正确写法</span></div></div><div><div><div>11</div></div><div><span>const</span><span> </span><span>name</span><span> </span><span>=</span><span> </span><span>encodeURIComponent</span><span>(</span><span>'张三&amp;李四'</span><span>);</span></div></div><div><div><div>12</div></div><div><span><span>xhr</span><span>.</span></span><span>open</span><span>(</span><span>'GET'</span><span>, </span><span>`/test?name=</span><span>${</span><span>name</span><span>}</span><span>`</span><span>);</span></div></div><div><div><div>13</div></div><div><span>//浏览器发送 /test?name=%E5%BC%A0%E4%B8%89%26%E6%9D%8E%E5%9B%9B</span></div></div><div><div><div>14</div></div><div><span>//后端解析：张三&amp;李四</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>使用encodeURIComponent来编码</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>url</span><span> </span><span>=</span><span> </span><span>'http://localhost:3000/get'</span><span>;</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>xhr</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>XMLHttpRequest</span><span>();</span></div></div><div><div><div>3</div></div><div><span><span>xhr</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'readystatechange'</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span>  </span><span>if</span><span><span> (</span><span>xhr</span><span>.</span></span><span>readyState</span><span> </span><span>!==</span><span> </span><span>4</span><span>) </span><span>return</span><span>;</span></div></div><div><div><div>5</div></div><div><span>  </span><span>if</span><span><span> (</span><span>xhr</span><span>.</span></span><span>readyState</span><span> </span><span>===</span><span> </span><span>4</span><span>) {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>if</span><span><span> ((</span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&gt;=</span><span> </span><span>200</span><span> </span><span>&amp;&amp;</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&lt;</span><span> </span><span>300</span><span>) </span><span>||</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>===</span><span> </span><span>304</span><span>) {</span></div></div><div><div><div>7</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>xhr</span><span>.</span></span><span>responseText</span><span>); </span><span>//数据作为字符串形式</span></div></div><div><div><div>8</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>typeof</span><span><span> </span><span>xhr</span><span>.</span></span><span>responseText</span><span>); </span><span>//string</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>});</span></div></div><div><div><div>12</div></div><div><span>//get通过请求头携带</span></div></div><div><div><div>13</div></div><div><span>//encodeURIComponent编码</span></div></div><div><div><div>14</div></div><div><span><span>xhr</span><span>.</span></span><span>open</span><span>(</span></div></div><div><div><div>15</div></div><div><span>  </span><span>'GET'</span><span>,</span></div></div><div><div><div>16</div></div><div><span>  </span><span>`</span><span>${</span><span>url</span><span>}</span><span>?username=</span><span>${</span><span>encodeURIComponent</span><span>(</span><span>'</span><span>林</span><span>'</span><span>)</span><span>}</span><span>&amp;age=18`</span><span>,</span></div></div><div><div><div>17</div></div><div><span>  </span><span>true</span><span>,</span></div></div><div><div><div>18</div></div><div><span>);</span></div></div><div><div><div>19</div></div><div><span><span>xhr</span><span>.</span></span><span>send</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>encodeURIComponent详细解析</strong></p><p><code>encodeURIComponent</code> 是一个<strong>字符串编码函数</strong>，可以在任何需要的地方调用它，不一定非得写在模板字符串里面。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//写法 1：直接写</span></div></div><div><div><div>2</div></div><div><span><span>xhr</span><span>.</span></span><span>open</span><span>(</span></div></div><div><div><div>3</div></div><div><span>  </span><span>'GET'</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>`</span><span>${</span><span>url</span><span>}</span><span>?username=</span><span>${</span><span>encodeURIComponent</span><span>(</span><span>'</span><span>林</span><span>'</span><span>)</span><span>}</span><span>&amp;age=18`</span><span>,</span></div></div><div><div><div>5</div></div><div><span>  </span><span>true</span></div></div><div><div><div>6</div></div><div><span>);</span></div></div><div><div><div>7</div></div><div><span>//写法 2：先编码，再拼接</span></div></div><div><div><div>8</div></div><div><span>const</span><span> </span><span>username</span><span> </span><span>=</span><span> </span><span>encodeURIComponent</span><span>(</span><span>'林'</span><span>);</span></div></div><div><div><div>9</div></div><div><span><span>xhr</span><span>.</span></span><span>open</span><span>(</span></div></div><div><div><div>10</div></div><div><span>  </span><span>'GET'</span><span>,</span></div></div><div><div><div>11</div></div><div><span>  </span><span>`</span><span>${</span><span>url</span><span>}</span><span>?username=</span><span>${</span><span>username</span><span>}</span><span>&amp;age=18`</span><span>,</span></div></div><div><div><div>12</div></div><div><span>  </span><span>true</span></div></div><div><div><div>13</div></div><div><span>//写法 3：多个参数自己拼</span></div></div><div><div><div>14</div></div><div><span><span>const</span><span> </span><span>params</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>15</div></div><div><span>  </span><span>username</span><span>:</span><span> </span><span>'林'</span><span>,</span></div></div><div><div><div>16</div></div><div><span>  </span><span>age</span><span>:</span><span> </span><span>18</span></div></div><div><div><div>17</div></div><div><span>};</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span><span>const</span><span> </span><span>query</span><span> </span></span><span>=</span><span><span> </span><span>Object</span><span>.</span></span><span>entries</span><span><span>(</span><span>params</span><span>)</span></span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>.</span><span>map</span><span><span>(([</span><span>k</span><span>, </span><span>v</span><span>]) </span></span><span>=&gt;</span><span> </span><span>`</span><span>${</span><span>k</span><span>}</span><span>=</span><span>${</span><span>encodeURIComponent</span><span><span>(</span><span>v</span><span>)</span></span><span>}</span><span>`</span><span>)</span></div></div><div><div><div>21</div></div><div><span><span>  </span></span><span>.</span><span>join</span><span>(</span><span>'&amp;'</span><span>);</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span><span>xhr</span><span>.</span></span><span>open</span><span>(</span><span>'GET'</span><span>, </span><span>`</span><span>${</span><span>url</span><span>}</span><span>?</span><span>${</span><span>query</span><span>}</span><span>`</span><span>, </span><span>true</span><span>);</span></div></div><div><div><div>24</div></div><div><span>//写法 4：封装一个函数</span></div></div><div><div><div>25</div></div><div><span>function</span><span> </span><span>stringify</span><span><span>(</span><span>params</span><span>) {</span></span></div></div><div><div><div>26</div></div><div><span>  </span><span>return</span><span><span> </span><span>Object</span><span>.</span></span><span>entries</span><span><span>(</span><span>params</span><span>)</span></span></div></div><div><div><div>27</div></div><div><span><span>    </span></span><span>.</span><span>map</span><span><span>(([</span><span>k</span><span>, </span><span>v</span><span>]) </span></span><span>=&gt;</span><span> </span><span>`</span><span>${</span><span>k</span><span>}</span><span>=</span><span>${</span><span>encodeURIComponent</span><span><span>(</span><span>v</span><span>)</span></span><span>}</span><span>`</span><span>)</span></div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>.</span><span>join</span><span>(</span><span>'&amp;'</span><span>);</span></div></div><div><div><div>29</div></div><div><span>}</span></div></div><div><div><div>30</div></div><div>
</div></div><div><div><div>31</div></div><div><span><span>xhr</span><span>.</span></span><span>open</span><span>(</span></div></div><div><div><div>32</div></div><div><span>  </span><span>'GET'</span><span>,</span></div></div><div><div><div>33</div></div><div><span>  </span><span>`</span><span>${</span><span>url</span><span>}</span><span>?</span><span>${</span><span>stringify</span><span>({</span></div></div><div><div><div>34</div></div><div><span>    </span><span>username</span><span>:</span><span> </span><span>'</span><span>林</span><span>'</span><span>,</span></div></div><div><div><div>35</div></div><div><span>    </span><span>age</span><span>:</span><span> </span><span>18</span></div></div><div><div><div>36</div></div><div><span><span>  </span></span><span>})</span><span>}</span><span>`</span><span>,</span></div></div><div><div><div>37</div></div><div><span>  </span><span>true</span></div></div><div><div><div>38</div></div><div><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>推荐使用URLSearchParams</strong>：完整示例</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>url</span><span> </span><span>=</span><span> </span><span>'https://www.imooc.com/api/http/search/suggest'</span><span>;</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>params</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>URLSearchParams</span><span>({</span></div></div><div><div><div>3</div></div><div><span>    </span><span>words</span><span>:</span><span> </span><span>'前端&amp;后端'</span><span>,</span></div></div><div><div><div>4</div></div><div><span>});</span></div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>xhr</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>XMLHttpRequest</span><span>();</span></div></div><div><div><div>6</div></div><div><span><span>xhr</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'readystatechange'</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>if</span><span><span> (</span><span>xhr</span><span>.</span></span><span>readyState</span><span> </span><span>!==</span><span> </span><span>4</span><span>) </span><span>return</span><span>;</span></div></div><div><div><div>8</div></div><div><span>    </span><span>if</span><span><span> (</span><span>xhr</span><span>.</span></span><span>readyState</span><span> </span><span>===</span><span> </span><span>4</span><span>) {</span></div></div><div><div><div>9</div></div><div><span>        </span><span>if</span><span><span> ((</span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&gt;=</span><span> </span><span>200</span><span> </span><span>&amp;&amp;</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&lt;</span><span> </span><span>300</span><span>) </span><span>||</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>===</span><span> </span><span>304</span><span>) {</span></div></div><div><div><div>10</div></div><div><span><span>            </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>xhr</span><span>.</span></span><span>responseText</span><span>); </span><span>//数据作为字符串形式</span></div></div><div><div><div>11</div></div><div><span><span>            </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>typeof</span><span><span> </span><span>xhr</span><span>.</span></span><span>responseText</span><span>); </span><span>//string</span></div></div><div><div><div>12</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span>});</span></div></div><div><div><div>15</div></div><div><span>//get通过请求头携带</span></div></div><div><div><div>16</div></div><div><span><span>xhr</span><span>.</span></span><span>open</span><span>(</span><span>'GET'</span><span>, </span><span>`</span><span>${</span><span>url</span><span>}</span><span>?</span><span>${</span><span>params</span><span>}</span><span>`</span><span>, </span><span>true</span><span>);</span></div></div><div><div><div>17</div></div><div><span><span>xhr</span><span>.</span></span><span>send</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>encodeURIComponent和URLSearchParams的区别</strong></p>

<table><thead><tr><th></th><th>encodeURIComponent</th><th>URLSearchParams</th></tr></thead><tbody><tr><td>类型</td><td>函数</td><td>类</td></tr><tr><td>作用</td><td>编码一个字符串</td><td>管理整个查询参数</td></tr><tr><td>自动拼 <code>key=value</code></td><td>❌</td><td>✅</td></tr><tr><td>自动拼 <code>&amp;</code></td><td>❌</td><td>✅</td></tr><tr><td>自动编码</td><td>✅</td><td>✅</td></tr><tr><td>获取参数</td><td>❌</td><td>✅</td></tr><tr><td>删除参数</td><td>❌</td><td>✅</td></tr><tr><td>修改参数</td><td>❌</td><td>✅</td></tr></tbody></table></section><section><h2>POST 请求<a href="#post-请求"><span>#</span></a></h2><p><strong>携带数据</strong>&amp;<strong>数据编码</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>url</span><span> </span><span>=</span><span> </span><span>'https://www.imooc.com/api/http/search/suggest?words=js'</span><span>;</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>xhr</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>XMLHttpRequest</span><span>();</span></div></div><div><div><div>3</div></div><div><span><span>xhr</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'readystatechange'</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span>    </span><span>if</span><span><span> (</span><span>xhr</span><span>.</span></span><span>readyState</span><span> </span><span>!==</span><span> </span><span>4</span><span>) </span><span>return</span><span>;</span></div></div><div><div><div>5</div></div><div><span>    </span><span>if</span><span><span> (</span><span>xhr</span><span>.</span></span><span>readyState</span><span> </span><span>===</span><span> </span><span>4</span><span>) {</span></div></div><div><div><div>6</div></div><div><span>        </span><span>if</span><span><span> ((</span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&gt;=</span><span> </span><span>200</span><span> </span><span>&amp;&amp;</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&lt;</span><span> </span><span>300</span><span>) </span><span>||</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>===</span><span> </span><span>304</span><span>) {</span></div></div><div><div><div>7</div></div><div><span><span>            </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>xhr</span><span>.</span></span><span>responseText</span><span>); </span><span>//数据作为字符串形式</span></div></div><div><div><div>8</div></div><div><span><span>            </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>typeof</span><span><span> </span><span>xhr</span><span>.</span></span><span>responseText</span><span>); </span><span>//string</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>});</span></div></div><div><div><div>12</div></div><div><span><span>xhr</span><span>.</span></span><span>open</span><span>(</span><span>'POST'</span><span><span>, </span><span>url</span><span>, </span></span><span>true</span><span>);</span></div></div><div><div><div>13</div></div><div><span>// 数据编码</span></div></div><div><div><div>14</div></div><div><span>const</span><span> </span><span>data</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>URLSearchParams</span><span>({</span></div></div><div><div><div>15</div></div><div><span>    </span><span>words</span><span>:</span><span> </span><span>'前端&amp;后端'</span><span>,</span></div></div><div><div><div>16</div></div><div><span>});</span></div></div><div><div><div>17</div></div><div><span>//常用1： 类型fromdata</span></div></div><div><div><div>18</div></div><div><span><span>xhr</span><span>.</span></span><span>send</span><span><span>(</span><span>data</span><span>);</span></span></div></div><div><div><div>19</div></div><div><span>//常用2：不能直接传对象，需要传字符串类型,json解决，这时候就不用编码了</span></div></div><div><div><div>20</div></div><div><span>// const data1 = {</span></div></div><div><div><div>21</div></div><div><span>//   username: 'alex',</span></div></div><div><div><div>22</div></div><div><span>//   age: 18</span></div></div><div><div><div>23</div></div><div><span>// };</span></div></div><div><div><div>24</div></div><div><span>// 对象 → JSON 字符串 → 发送</span></div></div><div><div><div>25</div></div><div><span>// xhr.send(JSON.stringify(data1));</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>
<section><h1>JSON<a href="#json"><span>#</span></a></h1><section><h2>初识 JSON<a href="#初识-json"><span>#</span></a></h2><ul>
<li>JavaScript Object Notation（JavaScript 对象表示法）</li>
<li>JSON 是一种“数据格式”，用来在前后端之间传输数据</li>
<li>JSON（JavaScript Object Notation）是一种轻量级的数据交换格式，用于前后端通信。它本质是字符串，常用于将 JavaScript 对象序列化为字符串（JSON.stringify），或将 JSON 字符串解析为对象（JSON.parse）。</li>
</ul><p><strong>JSON 长什么样</strong>：看起来像对象，但它是：字符串格式的数据</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>{</span></div></div><div><div><div>2</div></div><div><span>  </span><span>"name"</span><span>: </span><span>"Tom"</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>"age"</span><span>: </span><span>18</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div><span>[</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>{</span></div></div><div><div><div>7</div></div><div><span>    </span><span>"name"</span><span>: </span><span>"Tom"</span><span>,</span></div></div><div><div><div>8</div></div><div><span>    </span><span>"age"</span><span>: </span><span>18</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>{</span></div></div><div><div><div>11</div></div><div><span>    </span><span>"name"</span><span>: </span><span>"Jerry"</span><span>,</span></div></div><div><div><div>12</div></div><div><span>    </span><span>"age"</span><span>: </span><span>20</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span>]</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>JSON 的 3 种形式<a href="#json-的-3-种形式"><span>#</span></a></h2><p><strong>简单值</strong>：JSON 不仅可以是对象和数组，还可以是“单值”</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>"hello"</span></div></div><div><div><div>2</div></div><div><span>100</span></div></div><div><div><div>3</div></div><div><span>true</span></div></div><div><div><div>4</div></div><div><span>null</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>对象形式</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>{</span></div></div><div><div><div>2</div></div><div><span>  </span><span>"name"</span><span>: </span><span>"Tom"</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>"age"</span><span>: </span><span>18</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>数组形式</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>[</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>{</span></div></div><div><div><div>3</div></div><div><span>    </span><span>"name"</span><span>: </span><span>"Tom"</span><span>,</span></div></div><div><div><div>4</div></div><div><span>    </span><span>"age"</span><span>: </span><span>18</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>{</span></div></div><div><div><div>7</div></div><div><span>    </span><span>"name"</span><span>: </span><span>"Jerry"</span><span>,</span></div></div><div><div><div>8</div></div><div><span>    </span><span>"age"</span><span>: </span><span>20</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span>]</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意事项：</p><ul>
<li>JSON 不允许单引号</li>
<li>JSON 不允许没有引号</li>
<li>JSON 不允许undefined</li>
<li>不能注释</li>
</ul></section><section><h2>JSON 的常用方法<a href="#json-的常用方法"><span>#</span></a></h2><p>JSON 在前端中主要有两个常用方法：JSON.stringify 和 JSON.parse。stringify 用于将 JavaScript 对象转换为 JSON 字符串，常用于数据存储和请求发送；parse 用于将 JSON 字符串转换为 JavaScript 对象，常用于接口数据解析和本地存储读取。</p><p><strong>JSON.stringify()</strong>：JS对象 → JSON字符串</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>'Tom'</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>age</span><span>:</span><span> </span><span>18</span></div></div><div><div><div>4</div></div><div><span>};</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>const</span><span> </span><span>json</span><span> </span><span>=</span><span> </span><span>JSON</span><span>.</span><span>stringify</span><span><span>(</span><span>obj</span><span>);</span></span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>json</span><span>);</span></span><span>//{"name":"Tom","age":18}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>stringify 的进阶用法</strong>：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//第二个参数：过滤字段</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>'Tom'</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>age</span><span>:</span><span> </span><span>18</span><span>,</span></div></div><div><div><div>5</div></div><div><span>  </span><span>password</span><span>:</span><span> </span><span>'123456'</span></div></div><div><div><div>6</div></div><div><span>};</span></div></div><div><div><div>7</div></div><div><span>const</span><span> </span><span>json</span><span> </span><span>=</span><span> </span><span>JSON</span><span>.</span><span>stringify</span><span><span>(</span><span>obj</span><span>, [</span></span><span>'name'</span><span>, </span><span>'age'</span><span>]);</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>json</span><span>);</span></span><span>//{"name":"Tom","age":18}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>//格式化输出（第三个参数）</span></div></div><div><div><div>11</div></div><div><span>JSON</span><span>.</span><span>stringify</span><span><span>(</span><span>obj</span><span>, </span></span><span>null</span><span>, </span><span>2</span><span>);</span></div></div><div><div><div>12</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>json</span><span>);</span></span></div></div><div><div><div>13</div></div><div><span>//{</span></div></div><div><div><div>14</div></div><div><span>//  "name": "Tom",</span></div></div><div><div><div>15</div></div><div><span>//  "age": 18</span></div></div><div><div><div>16</div></div><div><span>//}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>JSON.parse()</strong>：JSON字符串 → JS对象</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>json</span><span> </span><span>=</span><span> </span><span>'{"name":"Tom","age":18}'</span><span>;</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> </span><span>JSON</span><span>.</span><span>parse</span><span><span>(</span><span>json</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj</span><span>.</span></span><span>name</span><span>);</span><span>//Tom</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>拓展-封装storage</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>storage</span><span> </span><span>=</span><span><span> </span><span>window</span><span>.</span></span><span>localStorage</span><span>;</span></div></div><div><div><div>2</div></div><div><span>//设置</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>set</span><span> </span><span>=</span><span><span> (</span><span>k</span><span>, </span><span>v</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>storage</span><span>.</span><span>setItem</span><span><span>(</span><span>k</span><span>, </span></span><span>JSON</span><span>.</span><span>stringify</span><span><span>(</span><span>v</span><span>));</span></span></div></div><div><div><div>5</div></div><div><span>};</span></div></div><div><div><div>6</div></div><div><span>//获取</span></div></div><div><div><div>7</div></div><div><span>const</span><span> </span><span>get</span><span> </span><span>=</span><span><span> (</span><span>k</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>8</div></div><div><span>  </span><span>return</span><span> </span><span>JSON</span><span>.</span><span>parse</span><span><span>(</span><span>storage</span><span>.</span></span><span>getItem</span><span><span>(</span><span>k</span><span>));</span></span></div></div><div><div><div>9</div></div><div><span>};</span></div></div><div><div><div>10</div></div><div><span>//删除</span></div></div><div><div><div>11</div></div><div><span>const</span><span> </span><span>remove</span><span> </span><span>=</span><span><span> (</span><span>k</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>storage</span><span>.</span><span>removeItem</span><span><span>(</span><span>k</span><span>);</span></span></div></div><div><div><div>13</div></div><div><span>};</span></div></div><div><div><div>14</div></div><div><span>//清空</span></div></div><div><div><div>15</div></div><div><span>const</span><span> </span><span>clear</span><span> </span><span>=</span><span> () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>storage</span><span>.</span><span>clear</span><span>();</span></div></div><div><div><div>17</div></div><div><span>};</span></div></div><div><div><div>18</div></div><div><span>export</span><span> { </span><span>set</span><span>, </span><span>get</span><span>, </span><span>remove</span><span>, </span><span>clear</span><span> };</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>使用：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> { </span><span>set</span><span>, </span><span>get</span><span>, </span><span>remove</span><span>, </span><span>clear</span><span> } </span><span>from</span><span> </span><span>'./storage.js'</span><span>;</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>url</span><span> </span><span>=</span><span> </span><span>'http://localhost:3000/post'</span><span>;</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>xhr</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>XMLHttpRequest</span><span>();</span></div></div><div><div><div>4</div></div><div><span><span>xhr</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'readystatechange'</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>5</div></div><div><span>  </span><span>if</span><span><span> (</span><span>xhr</span><span>.</span></span><span>readyState</span><span> </span><span>!==</span><span> </span><span>4</span><span>) </span><span>return</span><span>;</span></div></div><div><div><div>6</div></div><div><span>  </span><span>if</span><span><span> (</span><span>xhr</span><span>.</span></span><span>readyState</span><span> </span><span>===</span><span> </span><span>4</span><span>) {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>if</span><span><span> ((</span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&gt;=</span><span> </span><span>200</span><span> </span><span>&amp;&amp;</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&lt;</span><span> </span><span>300</span><span>) </span><span>||</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>===</span><span> </span><span>304</span><span>) {</span></div></div><div><div><div>8</div></div><div><span>      </span><span>//console.log(xhr.responseText); //数据作为字符串形式</span></div></div><div><div><div>9</div></div><div><span>      </span><span>//console.log(typeof xhr.responseText); //string</span></div></div><div><div><div>10</div></div><div><span>      </span><span>const</span><span> </span><span>data</span><span> </span><span>=</span><span> </span><span>JSON</span><span>.</span><span>parse</span><span><span>(</span><span>xhr</span><span>.</span></span><span>responseText</span><span>);</span><span>//转对象</span></div></div><div><div><div>11</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>data</span><span>.</span></span><span>user</span><span>);</span><span>//对象取user</span></div></div><div><div><div>12</div></div><div><span>      </span><span>set</span><span>(</span><span>'user'</span><span><span>, </span><span>data</span><span>.</span></span><span>user</span><span>);</span><span>//存对象，k值为user</span></div></div><div><div><div>13</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>get</span><span>(</span><span>'user'</span><span>));</span><span>//取值</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>16</div></div><div><span>});</span></div></div><div><div><div>17</div></div><div><span><span>xhr</span><span>.</span></span><span>open</span><span>(</span><span>'POST'</span><span><span>, </span><span>url</span><span>, </span></span><span>true</span><span>);</span></div></div><div><div><div>18</div></div><div><span>//常用1：表单提交就是这种</span></div></div><div><div><div>19</div></div><div><span>//xhr.send('username=alex&amp;age=18');</span></div></div><div><div><div>20</div></div><div><span>//常用2：不能直接传对象，需要传字符串类型,json解决</span></div></div><div><div><div>21</div></div><div><span><span>xhr</span><span>.</span></span><span>send</span><span>(</span></div></div><div><div><div>22</div></div><div><span>  </span><span>JSON</span><span>.</span><span>stringify</span><span>({</span></div></div><div><div><div>23</div></div><div><span>    </span><span>username</span><span>:</span><span> </span><span>'alex'</span><span>,</span></div></div><div><div><div>24</div></div><div><span>    </span><span>age</span><span>:</span><span> </span><span>18</span><span>,</span></div></div><div><div><div>25</div></div><div><span><span>  </span></span><span>}),</span></div></div><div><div><div>26</div></div><div><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>
<section><h1>跨域<a href="#跨域"><span>#</span></a></h1><section><h2>初识跨域<a href="#初识跨域"><span>#</span></a></h2><ul>
<li>跨域就是浏览器不允许“不同源之间互相访问数据”。</li>
<li>跨域是指浏览器基于同源策略限制不同源之间的资源访问行为。同源是指协议、域名和端口完全相同。跨域并不是请求无法发送，而是服务器返回的数据被浏览器拦截。常见解决方式有 CORS、代理和 JSONP。</li>
</ul><p><strong>什么是“同源”？</strong></p><p>浏览器有一个规则叫：同源策略，判断是否同源看三点：协议 + 域名 + 端口</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//同源（可以访问）</span></div></div><div><div><div>2</div></div><div><span>http://localhost:3000</span></div></div><div><div><div>3</div></div><div><span>http://localhost:3000</span></div></div><div><div><div>4</div></div><div><span>//不同源（跨域）</span></div></div><div><div><div>5</div></div><div><span>http://localhost:3000</span></div></div><div><div><div>6</div></div><div><span>http://localhost:8080</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>跨域本质是什么？</strong></p><p>很多人误解：跨域 = 请求发不出去，其实不是，请求其实已经发出去了，但<strong>浏览器拦截了响应</strong></p><p><strong>为什么要有跨域限制？</strong></p><p>坏网站可以读取你的银行网站数据，比如你登录了银行，同时打开恶意网站，恶意网站可以直接读取你的账户信息，所以浏览器规定不同源之间不能随便读数据</p><p><strong>跨域发生在哪里？</strong></p><p>跨域只在：浏览器生效，不跨域情况：Node.js 请求接口 → 没有跨域问题</p><p><strong>哪些操作会触发跨域？</strong></p><ul>
<li>Ajax / Fetch</li>
<li>XMLHttpRequest</li>
<li>Axios</li>
</ul><p><strong>跨域的错误长什么样？</strong></p><ul>
<li>Access to XMLHttpRequest has been blocked by CORS policy</li>
<li>No ‘Access-Control-Allow-Origin’ header</li>
</ul><p><strong>跨域的解决方案</strong></p><ul>
<li>后端设置 CORS（最常用）;Access-Control-Allow-Origin: *</li>
<li>代理（前端常用）：前端 → 本地服务器 → 后端</li>
<li>JSONP（老方案）：利用 script 标签不受跨域限制</li>
<li>iframe / postMessage：用于特殊场景</li>
</ul></section><section><h2>CORS 跨域资源共享<a href="#cors-跨域资源共享"><span>#</span></a></h2><ul>
<li>CORS 是浏览器“允许跨域访问”的一种官方解决方案。</li>
<li>CORS 不是前端的东西，是后端设置的规则</li>
<li>ie10及以上可以兼容</li>
</ul><p><strong>核心请求头</strong></p><p>请求头（浏览器自动带）</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//我来自哪个源</span></div></div><div><div><div>2</div></div><div><span>Origin: http://front.a.cn</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>响应头（后端设置）</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//允许所有域名</span></div></div><div><div><div>2</div></div><div><span>Access-Control-Allow-Origin: *</span></div></div><div><div><div>3</div></div><div><span>//只允许指定域名：</span></div></div><div><div><div>4</div></div><div><span>Access-Control-Allow-Origin: http://front.a.cn</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>JSONP<a href="#jsonp"><span>#</span></a></h2><p>JSONP 全称：JSON with Padding，利用 <code>&lt;script&gt;</code> 标签没有跨域限制的特性，实现跨域获取数据的一种老方案。</p><p>JSONP 是一种利用 script 标签没有跨域限制而实现跨域请求的技术。其原理是前端定义一个回调函数，通过 script 标签请求服务器，服务器返回一段执行该回调函数的 JavaScript 代码，从而实现数据获取。JSONP 只能发送 GET 请求，安全性较差，现在基本被 CORS 替代。</p><p><strong>手写 JSONP</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>jsonp</span><span><span>(</span><span>url</span><span>, </span><span>callback</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>const</span><span> </span><span>script</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>createElement</span><span>(</span><span>'script'</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>script</span><span>.</span><span>src</span><span> </span><span>=</span><span>`</span><span>${</span><span>url</span><span>}</span><span>?callback=</span><span>${</span><span>callback</span><span>}</span><span>`</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>document</span><span>.</span><span>body</span><span>.</span><span>appendChild</span><span><span>(</span><span>script</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>function</span><span> </span><span>handleResponse</span><span><span>(</span><span>data</span><span>) {</span></span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>data</span><span>);</span></span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>jsonp</span><span>(</span></div></div><div><div><div>12</div></div><div><span>  </span><span>'https://www.imooc.com/api/http/jsonp'</span><span>,</span></div></div><div><div><div>13</div></div><div><span>  </span><span>'handleResponse'</span></div></div><div><div><div>14</div></div><div><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>JSONP 的缺点:</p><ul>
<li>只能 GET</li>
<li>安全性差</li>
<li>错误处理麻烦</li>
<li>需要服务器配合</li>
</ul></section></section>
<section><h1>XHR 对象<a href="#xhr-对象"><span>#</span></a></h1><section><h2>XHR 的属性<a href="#xhr-的属性"><span>#</span></a></h2><p><strong>重点属性：</strong></p><p><strong>response</strong>：获取响应数据</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>response</span><span>  </span><span>//兼容问题 IE10及以上可以用</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>//返回值由：xhr.responseType决定</span></div></div><div><div><div>4</div></div><div><span><span>xhr</span><span>.</span></span><span>responseType</span><span> </span><span>=</span><span> </span><span>'json'</span><span>; </span><span>//返回json</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>//如果responseType不设置就是字符串，所以可以使用xhr.responseText</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>responseType</strong>：指定响应数据类型</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>responseType</span><span> </span><span>=</span><span> </span><span>'json'</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>可选值：</p>

<table><thead><tr><th>值</th><th>含义</th></tr></thead><tbody><tr><td>‘’</td><td>默认字符串</td></tr><tr><td>text</td><td>文本</td></tr><tr><td>json</td><td>JSON对象</td></tr><tr><td>blob</td><td>二进制文件</td></tr><tr><td>arraybuffer</td><td>二进制数据</td></tr><tr><td>document</td><td>XML/HTML文档</td></tr></tbody></table><p><strong>timeout</strong> ：请求超时时间，单位：毫秒(ms)</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//open之后，send之前设置</span></div></div><div><div><div>2</div></div><div><span><span>xhr</span><span>.</span></span><span>timeout</span><span> </span><span>=</span><span> </span><span>5000</span><span>;</span><span>//5秒后自动超时，连接取消</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>withCredentials</strong> ：是否携带 Cookie</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//默认false</span></div></div><div><div><div>2</div></div><div><span><span>xhr</span><span>.</span></span><span>withCredentials</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span><span>//跨域请求</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>//使用Ajax发送请求，默认情况下，同域时，会携带Cookie;跨域时，不会</span></div></div><div><div><div>5</div></div><div><span>//xhr.withCredentials = true;</span></div></div><div><div><div>6</div></div><div><span>//最终能否成功跨域携带Cookie，还要看服务器同不同意，服务器必须指定域名，不能Access-Control-Allow-Origin: *</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>其他属性</strong></p><p><strong>readyState</strong>：表示请求当前的状态。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>readyState</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>值</th><th>状态</th><th>含义</th></tr></thead><tbody><tr><td>0</td><td>UNSENT</td><td>XHR 已创建，还没调用 open()</td></tr><tr><td>1</td><td>OPENED</td><td>已调用 open()</td></tr><tr><td>2</td><td>HEADERS_RECEIVED</td><td>已收到响应头</td></tr><tr><td>3</td><td>LOADING</td><td>正在接收响应体</td></tr><tr><td>4</td><td>DONE</td><td>请求完成</td></tr></tbody></table><p><strong>status</strong>：HTTP 状态码</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>xhr.status</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>200</span></div></div><div><div><div>4</div></div><div><span>201</span></div></div><div><div><div>5</div></div><div><span>204</span></div></div><div><div><div>6</div></div><div><span>404</span></div></div><div><div><div>7</div></div><div><span>500</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>statusText</strong>：状态码对应的描述</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>xhr.statusText</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>200 OK</span></div></div><div><div><div>4</div></div><div><span>404 Not Found</span></div></div><div><div><div>5</div></div><div><span>500 Internal Server Error</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>responseText</strong>：获取服务器返回的文本数据</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>responseText</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>{</span></div></div><div><div><div>4</div></div><div><span>  </span><span>"name"</span><span>: </span><span>"Tom"</span><span>,</span></div></div><div><div><div>5</div></div><div><span>  </span><span>"age"</span><span>: </span><span>18</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div><span>const</span><span> </span><span>data</span><span> </span><span>=</span><span> </span><span>JSON</span><span>.</span><span>parse</span><span><span>(</span><span>xhr</span><span>.</span></span><span>responseText</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>responseURL</strong>：最终响应的 URL</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>responseURL</span></div></div><div><div><div>2</div></div><div><span>//https://api.xxx.com/user  //一般用于重定向后的最终地址</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>upload</strong> ：上传对象，用于监听文件上传进度</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>upload</span><span>.</span><span>onprogress</span><span> </span><span>=</span><span> </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>e</span><span>.</span></span><span>loaded</span><span>);</span></div></div><div><div><div>3</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>responseXML</strong>：获取 XML 数据</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>responseXML</span></div></div><div><div><div>2</div></div><div><span>//返回XMLDocument，基本不用，json取代</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性</th><th>用途</th><th>常用程度</th></tr></thead><tbody><tr><td>readyState</td><td>请求状态</td><td>⭐⭐⭐⭐⭐</td></tr><tr><td>status</td><td>HTTP状态码</td><td>⭐⭐⭐⭐⭐</td></tr><tr><td>responseText</td><td>文本响应</td><td>⭐⭐⭐⭐⭐</td></tr><tr><td>response</td><td>响应数据</td><td>⭐⭐⭐⭐</td></tr><tr><td>responseType</td><td>响应类型</td><td>⭐⭐⭐⭐</td></tr><tr><td>timeout</td><td>超时时间</td><td>⭐⭐⭐</td></tr><tr><td>withCredentials</td><td>携带Cookie</td><td>⭐⭐⭐⭐⭐</td></tr><tr><td>statusText</td><td>状态描述</td><td>⭐⭐⭐</td></tr><tr><td>upload</td><td>上传进度</td><td>⭐⭐⭐</td></tr><tr><td>responseXML</td><td>XML响应</td><td>⭐⭐</td></tr></tbody></table></section><section><h2>XHR 的方法<a href="#xhr-的方法"><span>#</span></a></h2><p><strong>重点方法：</strong></p><p><strong>abort()</strong>：取消请求，一般配合onabort事件使用</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>abort</span><span>();</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>xhr</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>XMLHttpRequest</span><span>();</span></div></div><div><div><div>4</div></div><div><span><span>xhr</span><span>.</span></span><span>open</span><span>(</span><span>'GET'</span><span>, </span><span>'/user'</span><span>);</span></div></div><div><div><div>5</div></div><div><span><span>xhr</span><span>.</span></span><span>send</span><span>();</span></div></div><div><div><div>6</div></div><div><span><span>xhr</span><span>.</span></span><span>abort</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>setRequestHeader()</strong>：设置请求头。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//必须在open()之后send()之前</span></div></div><div><div><div>2</div></div><div><span>//不是所有的头信息能设置，出于安全，比如 Origin: http://front.a.cn 伪造跨域就不能设置</span></div></div><div><div><div>3</div></div><div><span><span>xhr</span><span>.</span></span><span>setRequestHeader</span><span><span>(</span><span>name</span><span>, </span><span>value</span><span>);</span></span></div></div><div><div><div>4</div></div><div><span>//Content-Type告诉服务器，浏览器发送的数据是什么格式的</span></div></div><div><div><div>5</div></div><div><span><span>xhr</span><span>.</span></span><span>setRequestHeader</span><span>(</span></div></div><div><div><div>6</div></div><div><span>  </span><span>'Content-Type'</span><span>,</span></div></div><div><div><div>7</div></div><div><span>  </span><span>'application/json'</span></div></div><div><div><div>8</div></div><div><span>);</span></div></div><div><div><div>9</div></div><div><span><span>xhr</span><span>.</span></span><span>setRequestHeader</span><span>(</span></div></div><div><div><div>10</div></div><div><span>  </span><span>'Authorization'</span><span>,</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>token</span></div></div><div><div><div>12</div></div><div><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>其他方法：</strong></p><p><strong>open()</strong>：初始化一个请求</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>open</span><span><span>(</span><span>method</span><span>, </span><span>url</span><span>, </span><span>async</span><span>);</span></span></div></div><div><div><div>2</div></div><div><span><span>xhr</span><span>.</span></span><span>open</span><span>(</span><span>'POST'</span><span>, </span><span>'/login'</span><span>, </span><span>true</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>参数</th><th>说明</th></tr></thead><tbody><tr><td>method</td><td>请求方法（GET、POST…）</td></tr><tr><td>url</td><td>请求地址</td></tr><tr><td>async</td><td>是否异步，默认 true</td></tr></tbody></table><p><strong>send()</strong>：发送请求。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//GET 请求</span></div></div><div><div><div>2</div></div><div><span><span>xhr</span><span>.</span></span><span>send</span><span>();</span></div></div><div><div><div>3</div></div><div><span>//POST 请求</span></div></div><div><div><div>4</div></div><div><span><span>xhr</span><span>.</span></span><span>send</span><span><span>(</span><span>data</span><span>);</span></span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>xhr</span><span>.</span></span><span>send</span><span>(</span></div></div><div><div><div>7</div></div><div><span>  </span><span>JSON</span><span>.</span><span>stringify</span><span>({</span></div></div><div><div><div>8</div></div><div><span>    </span><span>username</span><span>:</span><span> </span><span>'admin'</span><span>,</span></div></div><div><div><div>9</div></div><div><span>    </span><span>password</span><span>:</span><span> </span><span>'123456'</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>11</div></div><div><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>getResponseHeader()</strong> ：获取指定响应头</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>getResponseHeader</span><span><span>(</span><span>name</span><span>);</span></span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>type</span><span> </span><span>=</span><span><span> </span><span>xhr</span><span>.</span></span><span>getResponseHeader</span><span>(</span><span>'Content-Type'</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>type</span><span>);</span></span><span>//application/json</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>getAllResponseHeaders()</strong>：获取所有响应头</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>headers</span><span> </span><span>=</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>xhr</span><span>.</span><span>getAllResponseHeaders</span><span>();</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>headers</span><span>);</span></span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>content</span><span>-</span><span><span>type</span><span>: </span><span>application</span></span><span>/</span><span>json</span></div></div><div><div><div>7</div></div><div><span>content</span><span>-</span><span><span>length</span><span>: </span></span><span>123</span></div></div><div><div><div>8</div></div><div><span><span>server</span><span>: </span><span>nginx</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>overrideMimeType()</strong> ：修改响应的 MIME 类型。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>overrideMimeType</span><span>(</span></div></div><div><div><div>2</div></div><div><span>  </span><span>'application/json'</span></div></div><div><div><div>3</div></div><div><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>XHR 最常用的方法总结</strong></p>

<table><thead><tr><th>方法</th><th>作用</th><th>常用程度</th></tr></thead><tbody><tr><td>open()</td><td>初始化请求</td><td>⭐⭐⭐⭐⭐</td></tr><tr><td>send()</td><td>发送请求</td><td>⭐⭐⭐⭐⭐</td></tr><tr><td>setRequestHeader()</td><td>设置请求头</td><td>⭐⭐⭐⭐</td></tr><tr><td>getResponseHeader()</td><td>获取一个响应头</td><td>⭐⭐⭐</td></tr><tr><td>getAllResponseHeaders()</td><td>获取全部响应头</td><td>⭐⭐⭐</td></tr><tr><td>abort()</td><td>取消请求</td><td>⭐⭐⭐⭐</td></tr><tr><td>overrideMimeType()</td><td>修改 MIME 类型</td><td>⭐⭐</td></tr></tbody></table></section><section><h2>XHR 的事件<a href="#xhr-的事件"><span>#</span></a></h2><p><strong>为什么需要事件？</strong></p><p>因为ajax是异步的，所以需要在某个时机通知我们，请求发生了什么这就是事件的作用。</p><p><strong>重点事件</strong></p><p><strong>onload</strong>：请求成功完成时触发</p><p>和 onreadystatechange 的区别：onreadystatechange状态变化触发多次，onload请求成功结束触发一次</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>onload</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>xhr</span><span>.</span></span><span>responseText</span><span>);</span></div></div><div><div><div>3</div></div><div><span>};</span></div></div><div><div><div>4</div></div><div><span>//eg  IE10</span></div></div><div><div><div>5</div></div><div><span><span>xhr</span><span>.</span></span><span>onload</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>6</div></div><div><span>  </span><span>if</span><span> (</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>xhr</span><span>.</span><span>status</span><span> </span><span>&gt;=</span><span> </span><span>200</span><span> </span><span>&amp;&amp;</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>xhr</span><span>.</span><span>status</span><span> </span><span>&lt;</span><span> </span><span>300</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>) {</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>xhr</span><span>.</span></span><span>response</span><span>);</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>onerror</strong> ：请求失败时触发</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>onerror</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'网络错误'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>};</span></div></div><div><div><div>4</div></div><div><span>//404和500不会触发 onerror  IE10</span></div></div><div><div><div>5</div></div><div><span>//只处理断网、DNS失败、服务器无法连接</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>ontimeout</strong>：请求超时时触发</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>timeout</span><span> </span><span>=</span><span> </span><span>5000</span><span>;</span></div></div><div><div><div>2</div></div><div><span>//ie8</span></div></div><div><div><div>3</div></div><div><span><span>xhr</span><span>.</span></span><span>ontimeout</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'请求超时'</span><span>);</span></div></div><div><div><div>5</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>onabort</strong> ：请求被取消时触发</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>onabort</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'请求取消'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>};</span></div></div><div><div><div>4</div></div><div><span>//xhr.abort();会触发onabort  IE10</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>其他事件</strong></p><p><strong>onreadystatechange</strong>：每次xhr.readyState发生变化时触发。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>onreadystatechange</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>xhr</span><span>.</span></span><span>readyState</span><span>);</span></div></div><div><div><div>3</div></div><div><span>};</span></div></div><div><div><div>4</div></div><div><span>//eg：</span></div></div><div><div><div>5</div></div><div><span><span>xhr</span><span>.</span></span><span>onreadystatechange</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>6</div></div><div><span>  </span><span>if</span><span> (</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>xhr</span><span>.</span><span>readyState</span><span> </span><span>===</span><span> </span><span>4</span><span> </span><span>&amp;&amp;</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>xhr</span><span>.</span><span>status</span><span> </span><span>===</span><span> </span><span>200</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>) {</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>xhr</span><span>.</span></span><span>responseText</span><span>);</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>onloadstart</strong> ：请求开始时触发</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>onloadstart</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'开始请求'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>onloadend</strong>：请求结束时触发</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>onloadend</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'请求结束'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>};</span></div></div><div><div><div>4</div></div><div><span>//无论成功失败超时取消都会触发</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>onprogress</strong>：请求过程中不断触发</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//例如下载文件：</span></div></div><div><div><div>2</div></div><div><span><span>xhr</span><span>.</span></span><span>onprogress</span><span> </span><span>=</span><span> </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>e</span><span>.</span></span><span>loaded</span><span>);</span></div></div><div><div><div>4</div></div><div><span>};</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>e</span><span>.</span><span>loaded</span><span>,</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>e</span><span>.</span><span>total</span></div></div><div><div><div>8</div></div><div><span>);</span></div></div><div><div><div>9</div></div><div><span>const</span><span> </span><span>percent</span><span> </span><span>=</span><span><span> </span><span>e</span><span>.</span></span><span>loaded</span><span> </span><span>/</span><span><span> </span><span>e</span><span>.</span></span><span>total</span><span> </span><span>*</span><span> </span><span>100</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>upload.onprogress</strong> ：上传进度监听</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xhr</span><span>.</span></span><span>upload</span><span>.</span><span>onprogress</span><span> </span><span>=</span><span> </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>const</span><span> </span><span>percent</span><span> </span><span>=</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>e</span><span>.</span><span>loaded</span><span> </span><span>/</span><span><span> </span><span>e</span><span>.</span></span><span>total</span><span> </span><span>*</span><span> </span><span>100</span><span>;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>percent</span><span>);</span></span></div></div><div><div><div>6</div></div><div><span>};</span></div></div><div><div><div>7</div></div><div><span>//文件上传进度条、图片上传、视频上传</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>常用事件总结</strong></p>

<table><thead><tr><th>事件</th><th>作用</th><th>常用程度</th></tr></thead><tbody><tr><td>onreadystatechange</td><td>状态变化</td><td>⭐⭐⭐⭐⭐</td></tr><tr><td>onload</td><td>请求成功</td><td>⭐⭐⭐⭐</td></tr><tr><td>onerror</td><td>网络错误</td><td>⭐⭐⭐⭐</td></tr><tr><td>ontimeout</td><td>超时</td><td>⭐⭐⭐</td></tr><tr><td>onabort</td><td>请求取消</td><td>⭐⭐⭐</td></tr><tr><td>onprogress</td><td>下载进度</td><td>⭐⭐⭐</td></tr><tr><td>upload.onprogress</td><td>上传进度</td><td>⭐⭐⭐⭐</td></tr><tr><td>onloadstart</td><td>请求开始</td><td>⭐⭐</td></tr><tr><td>onloadend</td><td>请求结束</td><td>⭐⭐</td></tr></tbody></table></section><section><h2>FormData<a href="#formdata"><span>#</span></a></h2><p><strong>使用Ajax提交表单</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>form</span><span> </span><span>id</span><span>=</span><span>"loginForm"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"text"</span><span> </span><span>name</span><span>=</span><span>"username"</span><span> </span><span>placeholder</span><span>=</span><span>"用户名"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"password"</span><span> </span><span>name</span><span>=</span><span>"password"</span><span> </span><span>placeholder</span><span>=</span><span>"密码"</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>&lt;</span><span>button</span><span> </span><span>type</span><span>=</span><span>"submit"</span><span>&gt;登录&lt;/</span><span>button</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>&lt;/</span><span>form</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span>const</span><span> </span><span>form</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>'loginForm'</span><span>);</span></div></div><div><div><div>8</div></div><div><span>const</span><span> </span><span>url</span><span> </span><span>=</span><span> </span><span>'https://www.imooc.com/api/http/search/suggest?words=js'</span><span>;</span></div></div><div><div><div>9</div></div><div><span>const</span><span> { </span><span>username</span><span>, </span><span>password</span><span> } </span><span>=</span><span><span> </span><span>form</span><span>;</span></span></div></div><div><div><div>10</div></div><div><span><span>form</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'submit'</span><span>, </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>11</div></div><div><span>  </span><span>// 阻止浏览器默认提交</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>e</span><span>.</span><span>preventDefault</span><span>();</span></div></div><div><div><div>13</div></div><div><span>  </span><span>//const formData = new FormData(form);</span></div></div><div><div><div>14</div></div><div><span>  </span><span>const</span><span> </span><span>xhr</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>XMLHttpRequest</span><span>();</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>xhr</span><span>.</span><span>onload</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>16</div></div><div><span>    </span><span>if</span><span> (</span></div></div><div><div><div>17</div></div><div><span><span>      </span></span><span>(</span><span>xhr</span><span>.</span><span>readyState</span><span> </span><span>===</span><span> </span><span>4</span><span> </span><span>&amp;&amp;</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>===</span><span> </span><span>200</span><span>) </span><span>||</span></div></div><div><div><div>18</div></div><div><span><span>      </span></span><span>xhr</span><span>.</span><span>status</span><span> </span><span>===</span><span> </span><span>304</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>) {</span></div></div><div><div><div>20</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>xhr</span><span>.</span></span><span>responseText</span><span>);</span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>22</div></div><div><span><span>  </span></span><span>};</span></div></div><div><div><div>23</div></div><div><span><span>  </span></span><span>xhr</span><span>.</span><span>open</span><span>(</span><span>'POST'</span><span><span>, </span><span>url</span><span>, </span></span><span>true</span><span>);</span></div></div><div><div><div>24</div></div><div><span>  </span><span>//组装数据</span></div></div><div><div><div>25</div></div><div><span>  </span><span>const</span><span> </span><span>data</span><span> </span><span>=</span><span> </span><span>`username=</span><span>${</span><span>username</span><span>.</span><span>value</span><span>}</span><span>&amp;password=</span><span>${</span><span>password</span><span>.</span><span>value</span><span>}</span><span>`</span><span>;</span></div></div><div><div><div>26</div></div><div><span>  </span><span>//设置请求头</span></div></div><div><div><div>27</div></div><div><span><span>  </span></span><span>xhr</span><span>.</span><span>setRequestHeader</span><span>(</span></div></div><div><div><div>28</div></div><div><span>    </span><span>'Content-Type'</span><span>,</span></div></div><div><div><div>29</div></div><div><span>    </span><span>'application/x-www-form-urlencoded'</span><span>,</span></div></div><div><div><div>30</div></div><div><span><span>  </span></span><span>);</span></div></div><div><div><div>31</div></div><div><span><span>  </span></span><span>xhr</span><span>.</span><span>send</span><span><span>(</span><span>data</span><span>);</span></span></div></div><div><div><div>32</div></div><div><span>});</span></div></div><div><div><div>33</div></div><div><span>&lt;/</span><span>script</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>组装数据改版：直接包装成FormData发送</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>form</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>'loginForm'</span><span>);</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>url</span><span> </span><span>=</span><span> </span><span>'https://www.imooc.com/api/http/search/suggest?words=js'</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>form</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'submit'</span><span>, </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>4</div></div><div><span>  </span><span>// 阻止浏览器默认提交</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>e</span><span>.</span><span>preventDefault</span><span>();</span></div></div><div><div><div>6</div></div><div><span>  </span><span>const</span><span> </span><span>xhr</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>XMLHttpRequest</span><span>();</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>xhr</span><span>.</span><span>onload</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>8</div></div><div><span>    </span><span>if</span><span> (</span></div></div><div><div><div>9</div></div><div><span><span>      </span></span><span>(</span><span>xhr</span><span>.</span><span>readyState</span><span> </span><span>===</span><span> </span><span>4</span><span> </span><span>&amp;&amp;</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>===</span><span> </span><span>200</span><span>) </span><span>||</span></div></div><div><div><div>10</div></div><div><span><span>      </span></span><span>xhr</span><span>.</span><span>status</span><span> </span><span>===</span><span> </span><span>304</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>) {</span></div></div><div><div><div>12</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>xhr</span><span>.</span></span><span>responseText</span><span>);</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>};</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>xhr</span><span>.</span><span>open</span><span>(</span><span>'POST'</span><span><span>, </span><span>url</span><span>, </span></span><span>true</span><span>);</span></div></div><div><div><div>16</div></div><div><span>  </span><span>//组装数据</span></div></div><div><div><div>17</div></div><div><span>  </span><span>const</span><span> </span><span>data</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>FormData</span><span><span>(</span><span>form</span><span>);</span></span></div></div><div><div><div>18</div></div><div><span>  </span><span>for</span><span> (</span><span>const</span><span> </span><span>item</span><span> </span><span>of</span><span><span> </span><span>data</span><span>) {</span></span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>item</span><span>);</span></span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span><span>  </span></span><span>xhr</span><span>.</span><span>send</span><span><span>(</span><span>data</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>FormData基本用法</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>form</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"loginForm"</span><span>);</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>formData</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>FormData</span><span><span>(</span><span>form</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span><span>xhr</span><span>.</span></span><span>send</span><span><span>(</span><span>formData</span><span>);</span></span></div></div><div><div><div>4</div></div><div><span>//添加数据：append()</span></div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>formData</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>FormData</span><span>();</span></div></div><div><div><div>6</div></div><div><span><span>formData</span><span>.</span></span><span>append</span><span>(</span><span>'username'</span><span>, </span><span>'张三'</span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>formData</span><span>.</span></span><span>append</span><span>(</span><span>'age'</span><span>, </span><span>18</span><span>);</span></div></div><div><div><div>8</div></div><div><span>//添加文件</span></div></div><div><div><div>9</div></div><div><span>const</span><span> </span><span>file</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>'file'</span><span>).</span><span>files</span><span>[</span><span>0</span><span>];</span></div></div><div><div><div>10</div></div><div><span><span>formData</span><span>.</span></span><span>append</span><span>(</span><span>'avatar'</span><span><span>, </span><span>file</span><span>);</span></span></div></div><div><div><div>11</div></div><div><span>//添加多个同名字段</span></div></div><div><div><div>12</div></div><div><span><span>formData</span><span>.</span></span><span>append</span><span>(</span><span>'hobby'</span><span>, </span><span>'篮球'</span><span>);</span></div></div><div><div><div>13</div></div><div><span><span>formData</span><span>.</span></span><span>append</span><span>(</span><span>'hobby'</span><span>, </span><span>'足球'</span><span>);</span></div></div><div><div><div>14</div></div><div><span><span>formData</span><span>.</span></span><span>append</span><span>(</span><span>'hobby'</span><span>, </span><span>'游戏'</span><span>);</span></div></div><div><div><div>15</div></div><div><span>//修改数据：set()</span></div></div><div><div><div>16</div></div><div><span><span>formData</span><span>.</span></span><span>append</span><span>(</span><span>'name'</span><span>, </span><span>'张三'</span><span>);</span></div></div><div><div><div>17</div></div><div><span><span>formData</span><span>.</span></span><span>set</span><span>(</span><span>'name'</span><span>, </span><span>'李四'</span><span>);</span><span>//name=李四</span></div></div><div><div><div>18</div></div><div><span>//获取数据</span></div></div><div><div><div>19</div></div><div><span><span>formData</span><span>.</span></span><span>get</span><span>(</span><span>'username'</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>
<section><h1>封装Ajax<a href="#封装ajax"><span>#</span></a></h1><p>ajax.js</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>DEFAULTS</span><span> </span><span>from</span><span> </span><span>'./defaults'</span><span>;</span></div></div><div><div><div>2</div></div><div><span>class</span><span> </span><span>Ajax</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>url</span><span>, </span><span>options</span><span>) {</span></span></div></div><div><div><div>4</div></div><div><span>    </span><span>this</span><span>.</span><span>url</span><span> </span><span>=</span><span><span> </span><span>url</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>this</span><span>.</span><span>options</span><span> </span><span>=</span><span><span> </span><span>Object</span><span>.</span></span><span>assign</span><span>({}, </span><span>DEFAULTS</span><span><span>, </span><span>options</span><span>);</span></span></div></div><div><div><div>6</div></div><div><span>    </span><span>//初始化</span></div></div><div><div><div>7</div></div><div><span>    </span><span>this</span><span>.</span><span>init</span><span>();</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>  </span><span>//初始化</span></div></div><div><div><div>10</div></div><div><span>  </span><span>init</span><span>() {</span></div></div><div><div><div>11</div></div><div><span>    </span><span>//实例化XMLHttpRequest</span></div></div><div><div><div>12</div></div><div><span>    </span><span>const</span><span> </span><span>xhr</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>XMLHttpRequest</span><span>();</span></div></div><div><div><div>13</div></div><div><span>    </span><span>this</span><span>.</span><span>xhr</span><span> </span><span>=</span><span><span> </span><span>xhr</span><span>;</span></span></div></div><div><div><div>14</div></div><div><span>    </span><span>this</span><span>.</span><span>bindEvent</span><span>(); </span><span>//监听事件</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>  </span><span>//监听事件</span></div></div><div><div><div>18</div></div><div><span>  </span><span>bindEvent</span><span>() {</span></div></div><div><div><div>19</div></div><div><span>    </span><span>const</span><span> </span><span>xhr</span><span> </span><span>=</span><span> </span><span>this</span><span>.</span><span>xhr</span><span>;</span></div></div><div><div><div>20</div></div><div><span>    </span><span>const</span><span> { </span><span>success</span><span>, </span><span>httpCodeError</span><span>, </span><span>error</span><span>, </span><span>abort</span><span>, </span><span>timeout</span><span> } </span><span>=</span><span> </span><span>this</span><span>.</span><span>options</span><span>;</span></div></div><div><div><div>21</div></div><div><span>    </span><span>//请求成功完成时触发</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>xhr</span><span>.</span><span>onload</span><span> </span><span>=</span><span> () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>23</div></div><div><span>      </span><span>if</span><span> (</span><span>this</span><span>.</span><span>ok</span><span>) {</span></div></div><div><div><div>24</div></div><div><span>        </span><span>success</span><span><span>(</span><span>xhr</span><span>.</span></span><span>response</span><span><span>, </span><span>xhr</span><span>);</span></span></div></div><div><div><div>25</div></div><div><span><span>      </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>26</div></div><div><span>        </span><span>httpCodeError</span><span><span>(</span><span>xhr</span><span>.</span></span><span>status</span><span><span>, </span><span>xhr</span><span>);</span></span></div></div><div><div><div>27</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>};</span></div></div><div><div><div>29</div></div><div><span>    </span><span>//请求失败时触发</span></div></div><div><div><div>30</div></div><div><span><span>    </span></span><span>xhr</span><span>.</span><span>onerror</span><span> </span><span>=</span><span> () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>31</div></div><div><span>      </span><span>error</span><span><span>(</span><span>xhr</span><span>);</span></span></div></div><div><div><div>32</div></div><div><span><span>    </span></span><span>};</span></div></div><div><div><div>33</div></div><div><span>    </span><span>//onabort请求被取消时触发</span></div></div><div><div><div>34</div></div><div><span><span>    </span></span><span>xhr</span><span>.</span><span>onabort</span><span> </span><span>=</span><span> () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>35</div></div><div><span>      </span><span>abort</span><span><span>(</span><span>xhr</span><span>);</span></span></div></div><div><div><div>36</div></div><div><span><span>    </span></span><span>};</span></div></div><div><div><div>37</div></div><div><span>    </span><span>//ontimeout请求超时时触发</span></div></div><div><div><div>38</div></div><div><span><span>    </span></span><span>xhr</span><span>.</span><span>ontimeout</span><span> </span><span>=</span><span> () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>39</div></div><div><span>      </span><span>timeout</span><span><span>(</span><span>xhr</span><span>);</span></span></div></div><div><div><div>40</div></div><div><span><span>    </span></span><span>};</span></div></div><div><div><div>41</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>42</div></div><div><span>  </span><span>//检测响应http状态码是否正常</span></div></div><div><div><div>43</div></div><div><span>  </span><span>ok</span><span>() {</span></div></div><div><div><div>44</div></div><div><span>    </span><span>const</span><span> </span><span>xhr</span><span> </span><span>=</span><span> </span><span>this</span><span>.</span><span>xhr</span><span>;</span></div></div><div><div><div>45</div></div><div><span>    </span><span>return</span><span><span> (</span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&gt;=</span><span> </span><span>200</span><span> </span><span>&amp;&amp;</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>&lt;</span><span> </span><span>300</span><span>) </span><span>||</span><span><span> </span><span>xhr</span><span>.</span></span><span>status</span><span> </span><span>===</span><span> </span><span>304</span><span>;</span></div></div><div><div><div>46</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>47</div></div><div><span>}</span></div></div><div><div><div>48</div></div><div><span>export</span><span> </span><span>default</span><span> </span><span>Ajax</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>defaults.js</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//默认参数</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>DEFAULTS</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>method</span><span>:</span><span> </span><span>'GET'</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>params</span><span>:</span><span> </span><span>null</span><span>, </span><span>//请求头</span></div></div><div><div><div>5</div></div><div><span>  </span><span>data</span><span>:</span><span> </span><span>null</span><span>, </span><span>//请求体</span></div></div><div><div><div>6</div></div><div><span>  </span><span>contentType</span><span>:</span><span> </span><span>'application/x-www-form-urlencoded'</span><span>,</span></div></div><div><div><div>7</div></div><div><span>  </span><span>response</span><span>:</span><span> </span><span>''</span><span>,</span></div></div><div><div><div>8</div></div><div><span>  </span><span>timeoutTime</span><span>:</span><span> </span><span>0</span><span>,</span></div></div><div><div><div>9</div></div><div><span>  </span><span>withCredentials</span><span>:</span><span> </span><span>false</span><span>,</span></div></div><div><div><div>10</div></div><div><span>  </span><span>//方法</span></div></div><div><div><div>11</div></div><div><span>  </span><span>success</span><span>() {},</span></div></div><div><div><div>12</div></div><div><span>  </span><span>httpCodeError</span><span>() {},</span></div></div><div><div><div>13</div></div><div><span>  </span><span>error</span><span>() {},</span></div></div><div><div><div>14</div></div><div><span>  </span><span>abort</span><span>() {},</span></div></div><div><div><div>15</div></div><div><span>  </span><span>timeout</span><span>() {},</span></div></div><div><div><div>16</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><ul>
<li>用类封装ajax，能传入url和配置</li>
<li>使用DEFAULTS.js设置默认的配置：method、params、data、contentType、response、timeoutTime、withCredentials</li>
<li>init初始化XMLHttpRequest，绑定<code>this.xhr = xhr</code>全局可用，<code>this.bindEvent()</code>绑定监听事件</li>
<li>onload的时候触发自定义的success方法，否则触发自定义的httpCodeError方法</li>
<li>onerror触发自定义的error方法</li>
<li>onabort触发自定义的abort方法</li>
<li>ontimeout触发自定义的timeout方法</li>
</ul><p>继续封装优化：</p><p>ajax.js</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> { </span><span>serialize</span><span>, </span><span>addURLData</span><span> } </span><span>from</span><span> </span><span>'./utils'</span><span>;</span></div></div><div><div><div>2</div></div><div><span>//get的时候，传参数需要处理addParam()</span></div></div><div><div><div>3</div></div><div><span><span>xhr</span><span>.</span></span><span>open</span><span>(</span><span>this</span><span>.</span><span>options</span><span>.</span><span>method</span><span>, </span><span>this</span><span>.</span><span>url</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>addParam</span><span>(), </span><span>true</span><span>);</span></div></div><div><div><div>4</div></div><div><span>//在地址上添加数据</span></div></div><div><div><div>5</div></div><div><span>  </span><span>addParam</span><span>() {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>const</span><span> { </span><span>params</span><span> } </span><span>=</span><span> </span><span>this</span><span>.</span><span>options</span><span>;</span></div></div><div><div><div>7</div></div><div><span>    </span><span>//如果为空，直接返回''，比如post请求params就是null</span></div></div><div><div><div>8</div></div><div><span>    </span><span>//要传对象</span></div></div><div><div><div>9</div></div><div><span>    </span><span>if</span><span> (</span><span>!</span><span><span>params</span><span>) {</span></span></div></div><div><div><div>10</div></div><div><span>      </span><span>return</span><span> </span><span>''</span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>    </span><span>//处理对象形式</span></div></div><div><div><div>13</div></div><div><span>    </span><span>//两种情况：一种本身没参数的，一种本身就带参数的，追加参数的</span></div></div><div><div><div>14</div></div><div><span>    </span><span>//工具类解决</span></div></div><div><div><div>15</div></div><div><span>    </span><span>return</span><span> </span><span>addURLData</span><span><span>(</span><span>thi</span><span>.</span></span><span>url</span><span>, </span><span>serialize</span><span><span>(</span><span>params</span><span>));</span></span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>utils.js</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//工具函数</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>//数据序列化成urlencoded格式的字符串</span></div></div><div><div><div>4</div></div><div><span>const</span><span> </span><span>serialize</span><span> </span><span>=</span><span><span> (</span><span>param</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>5</div></div><div><span>  </span><span>const</span><span> </span><span>results</span><span> </span><span>=</span><span> [];</span></div></div><div><div><div>6</div></div><div><span>  </span><span>for</span><span> (</span><span>const</span><span> [</span><span>key</span><span>, </span><span>value</span><span>] </span><span>of</span><span><span> </span><span>Object</span><span>.</span></span><span>entries</span><span><span>(</span><span>param</span><span>)) {</span></span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>results</span><span>.</span><span>push</span><span>(</span><span>`</span><span>${</span><span>encodeURIComponent</span><span><span>(</span><span>key</span><span>)</span></span><span>}</span><span>=</span><span>${</span><span>encodeURIComponent</span><span><span>(</span><span>value</span><span>)</span></span><span>}</span><span>`</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>  </span><span>return</span><span><span> </span><span>results</span><span>.</span></span><span>join</span><span>(</span><span>'&amp;'</span><span>);</span></div></div><div><div><div>10</div></div><div><span>};</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>//给url添加参数</span></div></div><div><div><div>13</div></div><div><span>const</span><span> </span><span>addURLData</span><span> </span><span>=</span><span><span> (</span><span>url</span><span>, </span><span>data</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>14</div></div><div><span>  </span><span>if</span><span> (</span><span>!</span><span><span>data</span><span>) </span></span><span>return</span><span> </span><span>''</span><span>;</span></div></div><div><div><div>15</div></div><div><span>  </span><span>//判断url是否已经有参数</span></div></div><div><div><div>16</div></div><div><span>  </span><span>//如果有?就用&amp;，如果没有就用?</span></div></div><div><div><div>17</div></div><div><span>  </span><span>const</span><span> </span><span>mark</span><span> </span><span>=</span><span><span> </span><span>url</span><span>.</span></span><span>includes</span><span>(</span><span>'?'</span><span>) </span><span>?</span><span> </span><span>'&amp;'</span><span> </span><span>:</span><span> </span><span>'?'</span><span>;</span></div></div><div><div><div>18</div></div><div><span>  </span><span>return</span><span> </span><span>`</span><span>${</span><span>mark</span><span>}${</span><span>data</span><span>}</span><span>`</span><span>;</span></div></div><div><div><div>19</div></div><div><span>};</span></div></div><div><div><div>20</div></div><div><span>export</span><span> { </span><span>serialize</span><span>, </span><span>addURLData</span><span> };</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><ul>
<li>open的增加，method，url，和是否异步，method直接配置取就可以，url这里需要考虑get的情况在url添加</li>
<li>创建工具函数，addURLData：给url添加参数，serialize数据序列化成urlencoded格式的字符串</li>
</ul><p>继续优化封装</p><p>ajax.js</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>HTTP_GET</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>CONTENT_TYPE_FORM_URLENCODED</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>CONTENT_TYPE_FORM_JSON</span><span>,</span></div></div><div><div><div>5</div></div><div><span>} </span><span>from</span><span> </span><span>'./constants'</span><span>;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>//发送请求</span></div></div><div><div><div>8</div></div><div><span>this</span><span>.</span><span>sendData</span><span>();</span></div></div><div><div><div>9</div></div><div><span>  </span><span>//发送</span></div></div><div><div><div>10</div></div><div><span>  </span><span>sendData</span><span>() {</span></div></div><div><div><div>11</div></div><div><span>    </span><span>const</span><span> </span><span>xhr</span><span> </span><span>=</span><span> </span><span>this</span><span>.</span><span>xhr</span><span>;</span></div></div><div><div><div>12</div></div><div><span>    </span><span>if</span><span> (</span><span>!</span><span>this</span><span>.</span><span>isSendData</span><span>()) {</span></div></div><div><div><div>13</div></div><div><span>      </span><span>return</span><span><span> </span><span>xhr</span><span>.</span></span><span>send</span><span>(</span><span>null</span><span>);</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>16</div></div><div><span>  </span><span>//是否需要使用send发送数据</span></div></div><div><div><div>17</div></div><div><span>  </span><span>isSendData</span><span>() {</span></div></div><div><div><div>18</div></div><div><span>    </span><span>const</span><span> { </span><span>data</span><span>, </span><span>method</span><span> } </span><span>=</span><span> </span><span>this</span><span>.</span><span>options</span><span>;</span></div></div><div><div><div>19</div></div><div><span>    </span><span>if</span><span> (</span><span>!</span><span><span>data</span><span>) </span></span><span>return</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>20</div></div><div><span>    </span><span>//判断，转成都是小写</span></div></div><div><div><div>21</div></div><div><span>    </span><span>if</span><span><span> (</span><span>method</span><span>.</span></span><span>toLowerCase</span><span>() </span><span>===</span><span> </span><span>HTTP_GET</span><span>.</span><span>toLowerCase</span><span>()) </span><span>return</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>22</div></div><div><span>    </span><span>return</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>23</div></div><div><span><span>  </span></span><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>constants.js</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//常量</span></div></div><div><div><div>2</div></div><div><span>export const HTTP_GET = 'GET';</span></div></div><div><div><div>3</div></div><div><span>export const CONTENT_TYPE_FORM_URLENCODED = 'application/x-www-form-urlencoded';</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>export const CONTENT_TYPE_FORM_JSON = 'application/json';</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>defaults.js</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import { HTTP_GET, CONTENT_TYPE_FORM_URLENCODED } from './constants';</span></div></div><div><div><div>2</div></div><div><span>//默认参数</span></div></div><div><div><div>3</div></div><div><span>const DEFAULTS = {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>method: HTTP_GET,</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>params: null, //请求头</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>data: null, //请求体</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>contentType: CONTENT_TYPE_FORM_URLENCODED,</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>response: '',</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>timeoutTime: 0,</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>withCredentials: false,</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>//方法</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>success() {},</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>httpCodeError() {},</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>error() {},</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>abort() {},</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>timeout() {},</span></div></div><div><div><div>17</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><ul>
<li>最后需要把数据发送出去，那就需要判断是否需要发送，get请求不需要发送，直接null</li>
<li>sendData就是发送，isSendData就是判断要不要发送</li>
<li>增加常量，统一管理常量信息</li>
</ul><p>继续完善优化</p><p>ajax.js</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import { serialize, addURLData, serializeJSON } from './utils';</span></div></div><div><div><div>2</div></div><div><span>//发送</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>sendData() {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>const xhr = this.xhr;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>if (!this.isSendData()) {</span></div></div><div><div><div>6</div></div><div><span><span>      </span></span><span>return xhr.send(null);</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>//需要传入就直接传入发送了，但是这里需要判断数据的格式</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>//xhr.send()</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>let resultData = null;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>//判断是不是FormData</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>if (!this.isFormData()) {</span></div></div><div><div><div>13</div></div><div><span><span>      </span></span><span>resultData = data;</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>} else if (this.isFormURLEncodedData()) {</span></div></div><div><div><div>15</div></div><div><span><span>      </span></span><span>//发送application/x-www-form-urlencoded格式数据</span></div></div><div><div><div>16</div></div><div><span><span>      </span></span><span>this.setContentType(CONTENT_TYPE_FORM_URLENCODED);</span></div></div><div><div><div>17</div></div><div><span><span>      </span></span><span>resultData = serialize(data);</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>} else if (this.isJSONData()) {</span></div></div><div><div><div>19</div></div><div><span><span>      </span></span><span>//发送JSON格式数据</span></div></div><div><div><div>20</div></div><div><span><span>      </span></span><span>this.setContentType(CONTENT_TYPE_FORM_JSON);</span></div></div><div><div><div>21</div></div><div><span><span>      </span></span><span>resultData = serializeJSON(data);</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>} else {</span></div></div><div><div><div>23</div></div><div><span><span>      </span></span><span>this.setContentType();</span></div></div><div><div><div>24</div></div><div><span><span>      </span></span><span>resultData = data;</span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>26</div></div><div><span><span>    </span></span><span>xhr.send(resultData);</span></div></div><div><div><div>27</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>//判断是不是FormData</span></div></div><div><div><div>30</div></div><div><span><span>  </span></span><span>isFormData() {</span></div></div><div><div><div>31</div></div><div><span><span>    </span></span><span>return this.options.data instanceof FormData;</span></div></div><div><div><div>32</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>33</div></div><div><span><span>  </span></span><span>//application/x-www-form-urlencoded格式数据</span></div></div><div><div><div>34</div></div><div><span><span>  </span></span><span>isFormURLEncodedData() {</span></div></div><div><div><div>35</div></div><div><span><span>    </span></span><span>return this.options.responseType</span></div></div><div><div><div>36</div></div><div><span><span>      </span></span><span>.toLowerCase()</span></div></div><div><div><div>37</div></div><div><span><span>      </span></span><span>.includes(CONTENT_TYPE_FORM_URLENCODED);</span></div></div><div><div><div>38</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>39</div></div><div><span><span>  </span></span><span>//json</span></div></div><div><div><div>40</div></div><div><span><span>  </span></span><span>isJSONData() {</span></div></div><div><div><div>41</div></div><div><span><span>    </span></span><span>return this.options.responseType</span></div></div><div><div><div>42</div></div><div><span><span>      </span></span><span>.toLowerCase()</span></div></div><div><div><div>43</div></div><div><span><span>      </span></span><span>.includes(CONTENT_TYPE_FORM_JSON);</span></div></div><div><div><div>44</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>45</div></div><div><span><span>  </span></span><span>//setContentType</span></div></div><div><div><div>46</div></div><div><span><span>  </span></span><span>setContentType(contentType = this.options.contentType) {</span></div></div><div><div><div>47</div></div><div><span><span>    </span></span><span>if (!contentType) return;</span></div></div><div><div><div>48</div></div><div><span><span>    </span></span><span>this.xhr.setRequestHeader('Content-Type', contentType);</span></div></div><div><div><div>49</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>50</div></div><div><span><span>  </span></span><span>//获取</span></div></div><div><div><div>51</div></div><div><span><span>  </span></span><span>getXHR() {</span></div></div><div><div><div>52</div></div><div><span><span>    </span></span><span>return this.xhr;</span></div></div><div><div><div>53</div></div><div><span><span>  </span></span><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>utils.js</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//数据序列化成json</span></div></div><div><div><div>2</div></div><div><span>const serializeJSON = (param) =&gt; {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>return JSON.stringify(param);</span></div></div><div><div><div>4</div></div><div><span>};</span></div></div><div><div><div>5</div></div><div><span>export { serialize, addURLData, serializeJSON };</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li>判断传的是fromdata、application/x-www-form-urlencoded还是json还是其他格式</li>
<li>setContentType设置请求头发送的数据格式</li>
</ul><p>最终封装和修复bug</p><p>源码地址：<a href="https://github.com/youzi177/AjaxPackaging" target="_blank">https://github.com/youzi177/AjaxPackaging</a></p><p>测试API：<a href="https://github.com/youzi177/AjaxApi" target="_blank">https://github.com/youzi177/AjaxApi</a></p></section>
<section><h1>Ajax应用<a href="#ajax应用"><span>#</span></a></h1><section><h2>搜索提示<a href="#搜索提示"><span>#</span></a></h2></section><section><h2>二级菜单<a href="#二级菜单"><span>#</span></a></h2></section><section><h2>多个Ajax请求的并发执行<a href="#多个ajax请求的并发执行"><span>#</span></a></h2></section></section>
<section><h1>Axios与Fetch<a href="#axios与fetch"><span>#</span></a></h1><section><h2>axios<a href="#axios"><span>#</span></a></h2><p>基本使用 ：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>url</span><span> </span><span>=</span><span> </span><span>'http://192.168.2.132:3000/post'</span><span>;</span></div></div><div><div><div>2</div></div><div><span>      </span><span>axios</span><span><span>(</span><span>url</span><span>, {</span></span></div></div><div><div><div>3</div></div><div><span>        </span><span>method</span><span>:</span><span> </span><span>'post'</span><span>,</span></div></div><div><div><div>4</div></div><div><span>        </span><span>Headers</span><span>:</span><span> { </span><span>'content-type'</span><span>:</span><span> </span><span>'application/json'</span><span> },</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>        </span><span>//传对象就是application/json</span></div></div><div><div><div>7</div></div><div><span>        </span><span>data</span><span>:</span><span> {</span></div></div><div><div><div>8</div></div><div><span>          </span><span>username</span><span>:</span><span> </span><span>'alex'</span><span>,</span></div></div><div><div><div>9</div></div><div><span>          </span><span>age</span><span>:</span><span> </span><span>18</span><span>,</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>},</span></div></div><div><div><div>11</div></div><div><span>        </span><span>timeout</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>12</div></div><div><span>        </span><span>withCredentials</span><span>:</span><span> </span><span>false</span><span>,</span></div></div><div><div><div>13</div></div><div><span><span>      </span></span><span>})</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>.</span><span>then</span><span><span>((</span><span>result</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>15</div></div><div><span><span>          </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>result</span><span>.</span></span><span>data</span><span>);</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>})</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>.</span><span>catch</span><span><span>((</span><span>err</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>18</div></div><div><span><span>          </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>err</span><span>);</span></span></div></div><div><div><div>19</div></div><div><span><span>        </span></span><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h2>Fetch<a href="#fetch"><span>#</span></a></h2><p>Fetch是Ajax于Promise 的(XMLHttpRequest)的一种替代方案，它是基于Promise</p><p><code>fetch</code> 是基于 Promise 的网络请求 API，现在基本已经替代了大部分 <code>XMLHttpRequest</code> 的使用场景。</p><p><strong>和 XHR 对比</strong></p>

<table><thead><tr><th>功能</th><th>XHR</th><th>Fetch</th></tr></thead><tbody><tr><td>Promise</td><td>❌</td><td>✅</td></tr><tr><td>async/await</td><td>❌</td><td>✅</td></tr><tr><td>自动 reject 404</td><td>❌</td><td>❌</td></tr><tr><td>自动 reject 网络错误</td><td>❌</td><td>✅</td></tr><tr><td>abort</td><td><code>xhr.abort()</code></td><td><code>AbortController</code></td></tr><tr><td>timeout</td><td><code>xhr.timeout</code></td><td>❌ 自己实现</td></tr><tr><td>上传进度</td><td>✅</td><td>❌</td></tr><tr><td>下载进度</td><td>✅</td><td>✅（Stream）</td></tr><tr><td>设置 responseType</td><td>✅</td><td>不需要，调用 <code>json()</code>、<code>text()</code> 等即可</td></tr></tbody></table><p>基本使用</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>async</span><span> </span><span>function</span><span> </span><span>login</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>try</span><span> {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>const</span><span> </span><span>response</span><span> </span><span>=</span><span> </span><span>await</span><span> </span><span>fetch</span><span>(</span></div></div><div><div><div>4</div></div><div><span>      </span><span>'http://localhost:3000/login'</span><span>,</span></div></div><div><div><div>5</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>6</div></div><div><span>        </span><span>method</span><span>:</span><span> </span><span>'POST'</span><span>,</span></div></div><div><div><div>7</div></div><div><span>        </span><span>headers</span><span>:</span><span> {</span></div></div><div><div><div>8</div></div><div><span>          </span><span>'Content-Type'</span><span>:</span><span> </span><span>'application/json'</span><span>,</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>},</span></div></div><div><div><div>10</div></div><div><span>        </span><span>body</span><span>:</span><span> </span><span>JSON</span><span>.</span><span>stringify</span><span>({</span></div></div><div><div><div>11</div></div><div><span>          </span><span>username</span><span>:</span><span> </span><span>'admin'</span><span>,</span></div></div><div><div><div>12</div></div><div><span>          </span><span>password</span><span>:</span><span> </span><span>'123456'</span><span>,</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>}),</span></div></div><div><div><div>14</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>);</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>    </span><span>if</span><span> (</span><span>!</span><span><span>response</span><span>.</span></span><span>ok</span><span>) {</span></div></div><div><div><div>18</div></div><div><span>      </span><span>throw</span><span> </span><span>new</span><span> </span><span>Error</span><span>(</span><span>`HTTP Error: </span><span>${</span><span>response</span><span>.</span><span>status</span><span>}</span><span>`</span><span>);</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>    </span><span>const</span><span> </span><span>data</span><span> </span><span>=</span><span> </span><span>await</span><span><span> </span><span>response</span><span>.</span></span><span>json</span><span>();</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'成功：'</span><span><span>, </span><span>data</span><span>);</span></span></div></div><div><div><div>24</div></div><div><span><span>  </span></span><span>} </span><span>catch</span><span><span> (</span><span>error</span><span>) {</span></span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'失败：'</span><span><span>, </span><span>error</span><span>.</span></span><span>message</span><span>);</span></div></div><div><div><div>26</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>27</div></div><div><span>}</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>login</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102204-qian-duan-ben-di-cun-chu/</id>
      <title type="text">前端本地存储</title>
      <published>2026-10-22T00:46:59.000Z</published>
      <updated>2026-10-22T00:46:59.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102204-qian-duan-ben-di-cun-chu/"/>
      <summary type="text">本文主要学习前端本地存储Cookie和localStorage</summary>
      <content type="html"><![CDATA[<section><h2>初识 Cookie<a href="#初识-cookie"><span>#</span></a></h2><ul>
<li>浏览器存储在本地的一小段字符串数据，用来保存用户状态。所以敏感信息不要放在Cookie</li>
<li>一般会自动随着浏览器每次请求发送到服务器上（修改网站语言）</li>
</ul><p><strong>Cookie有什么用</strong></p><ul>
<li>Cookie跟踪统计用户访问该网站的习惯，比如什么时间访问，访问了哪些页面，在每个网页的停留时间等利用（Cookie + JS + 后端日志 + 大数据系统）</li>
</ul><p><strong>在浏览器操作Cookie</strong></p><ul>
<li>谷歌浏览器-F12控制台-Application-Cookie-网站 输入KV值</li>
<li><code>document.cookie</code> 能输出刚才的Cookie</li>
</ul></section>
<section><h2>Cookie 的基本用法<a href="#cookie-的基本用法"><span>#</span></a></h2><p><strong>写入Cookie</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//写入</span></div></div><div><div><div>2</div></div><div><span><span>     </span></span><span>document</span><span>.</span><span>cookie</span><span> </span><span>=</span><span> </span><span>'username = youzi'</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>     </span></span><span>document</span><span>.</span><span>cookie</span><span> </span><span>=</span><span> </span><span>'age = 18'</span><span>;</span></div></div><div><div><div>4</div></div><div><span>     </span><span>// 不能一起写入</span></div></div><div><div><div>5</div></div><div><span>     </span><span>//document.cookie = 'username = youzi;age = 18';</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>读取Cookie</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>document</span><span>.</span></span><span>cookie</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>Cookie 的属性<a href="#cookie-的属性"><span>#</span></a></h2><ul>
<li>
<p>Cookie 的属性（Attributes）决定了，这个 Cookie 能存多久、在哪些请求中发送、谁可以访问、是否安全等。</p>
</li>
<li>
<p>Cookie 的名称或值如果包含非英文字母，则写入时需要使用encodeURIComponent0编码，读取时使用decodeURIComponent(解码），一般名称使用英文字母，不要用中文，值可以用中文，但是要编码</p>
</li>
<li>
<p>如果没有设置失效(到期)时间，这样的Cookie称为会话Cookie，它存在内存中，当会话结束，也就是浏览器关闭时，Cookie消失</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//属性可以一起写；expires指定 Cookie 的绝对过期时间</span></div></div><div><div><div>2</div></div><div><span><span>document</span><span>.</span></span><span>cookie</span><span> </span><span>=</span><span> </span><span>`username = youzi;expires =</span><span>${</span><span>new</span><span> </span><span>Date</span><span>(</span><span>'</span><span>2026-6-27 13:41:00</span><span>'</span><span>)</span><span>}</span><span>`</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>Max-Age（存活时间）：指定 Cookie 还能存活多少秒。</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>document</span><span>.</span></span><span>cookie</span><span> </span><span>=</span><span> </span><span>'age=18;max-age=5'</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>如果max-age的值是0或负数，则Cookie会被删除</p>
</li>
<li>
<p>Domain（域名）：哪些域名可以使用这个 Cookie。默认值就是当前网站</p>
</li>
<li>
<p>HttpOnly：JavaScript 无法访问这个 Cookie。防止XSS 攻击</p>
</li>
<li>
<p>SameSite：防止 CSRF 攻击。只有同站请求才发送 Cookie。</p>
</li>
<li>
<p>只有name，value，Domain，path都一样的情况下才算一个Cookie ，才会覆盖</p>
</li>
</ul>

<table><thead><tr><th>属性</th><th>作用</th></tr></thead><tbody><tr><td>Expires</td><td>绝对过期时间</td></tr><tr><td>Max-Age</td><td>存活秒数</td></tr><tr><td>Path</td><td>生效路径（同一个域名下）</td></tr><tr><td>Domain</td><td>生效域名（不同域名的情况）</td></tr><tr><td>Secure</td><td>仅 HTTPS 发送</td></tr><tr><td>HttpOnly</td><td>JS 不可访问</td></tr><tr><td>SameSite</td><td>防止 CSRF</td></tr><tr><td>Partitioned</td><td>第三方 Cookie 分区</td></tr></tbody></table></section>
<section><h2>Cookie 的封装<a href="#cookie-的封装"><span>#</span></a></h2><p><strong>为什么封装？</strong></p><ol>
<li>
<p>语法难用</p>
<p>实际开发中，我们不会直接到处写：</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>document</span><span>.</span></span><span>cookie</span><span> </span><span>=</span><span> </span><span>'age=18;max-age=3600'</span><span>;</span></div></div><div><div><div>2</div></div><div><span><span>document</span><span>.</span></span><span>cookie</span><span> </span><span>=</span><span> </span><span>'name=Tom'</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>document</span><span>.</span></span><span>cookie</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>因为 <code>document.cookie</code> 的 API 非常难用：读取需要自己解析字符串；删除需要设置过期时间；修改和设置逻辑重复。</p>
</li>
<li>
<p>document.cookie打印的全部，不能根据k值获取</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>document</span><span>.</span></span><span>cookie</span><span> </span><span>=</span><span> </span><span>'name=Tom'</span><span>;</span></div></div><div><div><div>2</div></div><div><span><span>document</span><span>.</span></span><span>cookie</span><span> </span><span>=</span><span> </span><span>'age=18'</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>document</span><span>.</span></span><span>cookie</span><span> </span><span>=</span><span> </span><span>'gender=male'</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>document</span><span>.</span></span><span>cookie</span><span>);</span><span>//name=Tom; age=18; gender=male</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ol><p><strong>封装：</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>cookie</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>set</span><span><span>(</span><span>name</span><span>, </span><span>value</span><span>, </span><span>maxAge</span><span>, </span><span>path</span><span> </span></span><span>=</span><span> </span><span>'/'</span><span>) {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>document</span><span>.</span><span>cookie</span><span> </span><span>=</span></div></div><div><div><div>4</div></div><div><span>      </span><span>`</span><span>${</span><span>encodeURIComponent</span><span><span>(</span><span>name</span><span>)</span></span><span>}</span><span>=</span><span>${</span><span>encodeURIComponent</span><span><span>(</span><span>value</span><span>)</span></span><span>}</span><span>;max-age=</span><span>${</span><span>maxAge</span><span>}</span><span>;path=</span><span>${</span><span>path</span><span>}</span><span>`</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>  </span><span>get</span><span><span>(</span><span>name</span><span>) {</span></span></div></div><div><div><div>8</div></div><div><span>    </span><span>const</span><span> </span><span>cookies</span><span> </span><span>=</span></div></div><div><div><div>9</div></div><div><span><span>      </span></span><span>document</span><span>.</span><span>cookie</span><span>.</span><span>split</span><span>(</span><span>'; '</span><span>);</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>    </span><span>for</span><span> (</span><span>let</span><span><span> </span><span>item</span><span> </span></span><span>of</span><span><span> </span><span>cookies</span><span>) {</span></span></div></div><div><div><div>12</div></div><div><span>      </span><span>const</span><span> [</span><span>key</span><span>, </span><span>value</span><span>] </span><span>=</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>item</span><span>.</span><span>split</span><span>(</span><span>'='</span><span>);</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>      </span><span>if</span><span> (</span></div></div><div><div><div>16</div></div><div><span>        </span><span>decodeURIComponent</span><span><span>(</span><span>key</span><span>) </span></span><span>===</span><span><span> </span><span>name</span></span></div></div><div><div><div>17</div></div><div><span><span>      </span></span><span>) {</span></div></div><div><div><div>18</div></div><div><span>        </span><span>return</span><span> </span><span>decodeURIComponent</span><span><span>(</span><span>value</span><span>);</span></span></div></div><div><div><div>19</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>20</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>    </span><span>return</span><span> </span><span>null</span><span>;</span></div></div><div><div><div>23</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span>  </span><span>remove</span><span><span>(</span><span>name</span><span>, </span><span>path</span><span> </span></span><span>=</span><span> </span><span>'/'</span><span>) {</span></div></div><div><div><div>26</div></div><div><span><span>    </span></span><span>document</span><span>.</span><span>cookie</span><span> </span><span>=</span></div></div><div><div><div>27</div></div><div><span>      </span><span>`</span><span>${</span><span>encodeURIComponent</span><span><span>(</span><span>name</span><span>)</span></span><span>}</span><span>=;max-age=0;path=</span><span>${</span><span>path</span><span>}</span><span>`</span><span>;</span></div></div><div><div><div>28</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>29</div></div><div><span>};</span></div></div><div><div><div>30</div></div><div>
</div></div><div><div><div>31</div></div><div><span><span>cookie</span><span>.</span></span><span>set</span><span>(</span><span>'name'</span><span>, </span><span>'Tom'</span><span>, </span><span>3600</span><span>);</span></div></div><div><div><div>32</div></div><div><span><span>cookie</span><span>.</span></span><span>get</span><span>(</span><span>'name'</span><span>);</span></div></div><div><div><div>33</div></div><div><span><span>cookie</span><span>.</span></span><span>remove</span><span>(</span><span>'name'</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>实际开发中可以使用这个包：<a href="https://github.com/js-cookie/js-cookie" target="_blank">js-cookie</a></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>Cookies</span><span>.</span></span><span>set</span><span>(</span><span>'token'</span><span>, </span><span>'abc'</span><span>);</span></div></div><div><div><div>2</div></div><div><span><span>Cookies</span><span>.</span></span><span>get</span><span>(</span><span>'token'</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>Cookies</span><span>.</span></span><span>remove</span><span>(</span><span>'token'</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>Cookie 的注意事项<a href="#cookie-的注意事项"><span>#</span></a></h2><ol>
<li>大小限制约 4KB</li>
<li>数量有限</li>
<li>自动随请求发送</li>
<li>不要存敏感信息</li>
<li>HttpOnly 无法被 JS 读取</li>
<li>删除时 Path/Domain 要一致</li>
<li>只能存字符串</li>
<li>特殊字符要编码</li>
<li>跨域默认不发送 Cookie</li>
<li>会过期，不适合存重要数据</li>
</ol></section>
<section><h2>初识 localStorage<a href="#初识-localstorage"><span>#</span></a></h2><ul>
<li><code>localStorage</code> 是浏览器提供的一种持久化本地存储，它允许前端把数据保存在浏览器本地，即使：刷新页面、关闭浏览器、重新打开浏览器数据依然存在。</li>
</ul><p><strong>为什么会有 localStorage？</strong></p><ul>
<li>以前只有 Cookie，但是 Cookie 有很多缺点：容量小（4KB），自动发送给服务器增加请求体积，所以 HTML5 推出了Web Storage，包括localStorage和sessionStorage</li>
</ul><p><strong>localStorage 的特点</strong></p><ul>
<li>永久保存（除非主动删除）</li>
<li>不会自动发送给服务器</li>
<li>容量大5MB ~ 10MB</li>
<li>同源限制：协议、域名和端口全部相同才能访问</li>
</ul><p><strong>localStorage 的 API</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//保存数据</span></div></div><div><div><div>2</div></div><div><span><span>localStorage</span><span>.</span></span><span>setItem</span><span>(</span><span>'name'</span><span>, </span><span>'Tom'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>//获取数据</span></div></div><div><div><div>4</div></div><div><span><span>localStorage</span><span>.</span></span><span>getItem</span><span>(</span><span>'name'</span><span>);</span><span>//Tom</span></div></div><div><div><div>5</div></div><div><span><span>localStorage</span><span>.</span></span><span>getItem</span><span>(</span><span>'gender'</span><span>);</span><span>//null</span></div></div><div><div><div>6</div></div><div><span>//删除某一项</span></div></div><div><div><div>7</div></div><div><span><span>localStorage</span><span>.</span></span><span>removeItem</span><span>(</span><span>'name'</span><span>);</span></div></div><div><div><div>8</div></div><div><span>//清空全部</span></div></div><div><div><div>9</div></div><div><span><span>localStorage</span><span>.</span></span><span>clear</span><span>();</span></div></div><div><div><div>10</div></div><div><span>//获取数量</span></div></div><div><div><div>11</div></div><div><span><span>localStorage</span><span>.</span></span><span>length</span><span>;</span></div></div><div><div><div>12</div></div><div><span>//获取第几个 key</span></div></div><div><div><div>13</div></div><div><span><span>localStorage</span><span>.</span></span><span>key</span><span>(</span><span>0</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>localStorage 只能存字符串</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>localStorage</span><span>.</span></span><span>setItem</span><span>(</span><span>'age'</span><span>, </span><span>18</span><span>);</span></div></div><div><div><div>2</div></div><div><span><span>localStorage</span><span>.</span></span><span>getItem</span><span>(</span><span>'age'</span><span>);</span><span>//"18" 是字符串</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>存对象怎么办？</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//错误</span></div></div><div><div><div>2</div></div><div><span><span>localStorage</span><span>.</span></span><span>setItem</span><span>(</span><span>'user'</span><span>, {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>'Tom'</span></div></div><div><div><div>4</div></div><div><span>});</span></div></div><div><div><div>5</div></div><div><span>//正确</span></div></div><div><div><div>6</div></div><div><span>const</span><span> </span><span>user</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>7</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>'Tom'</span><span>,</span></div></div><div><div><div>8</div></div><div><span>  </span><span>age</span><span>:</span><span> </span><span>18</span></div></div><div><div><div>9</div></div><div><span>};</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>localStorage</span><span>.</span></span><span>setItem</span><span>(</span></div></div><div><div><div>12</div></div><div><span>  </span><span>'user'</span><span>,</span></div></div><div><div><div>13</div></div><div><span>  </span><span>JSON</span><span>.</span><span>stringify</span><span><span>(</span><span>user</span><span>)</span></span></div></div><div><div><div>14</div></div><div><span>);</span></div></div><div><div><div>15</div></div><div><span>//读取</span></div></div><div><div><div>16</div></div><div><span>const</span><span> </span><span>user</span><span> </span><span>=</span><span> </span><span>JSON</span><span>.</span><span>parse</span><span>(</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>localStorage</span><span>.</span><span>getItem</span><span>(</span><span>'user'</span><span>)</span></div></div><div><div><div>18</div></div><div><span>);</span></div></div><div><div><div>19</div></div><div><span>//结果</span></div></div><div><div><div>20</div></div><div><span>{</span></div></div><div><div><div>21</div></div><div><span><span>  </span></span><span>name</span><span>: </span><span>'Tom'</span><span>,</span></div></div><div><div><div>22</div></div><div><span><span>  </span></span><span>age</span><span>: </span><span>18</span></div></div><div><div><div>23</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>实际开发中的使用场景</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//保存 Token</span></div></div><div><div><div>2</div></div><div><span><span>localStorage</span><span>.</span></span><span>setItem</span><span>(</span></div></div><div><div><div>3</div></div><div><span>  </span><span>'token'</span><span>,</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>res</span><span>.</span><span>data</span><span>.</span><span>token</span></div></div><div><div><div>5</div></div><div><span>);</span></div></div><div><div><div>6</div></div><div><span>//保存主题</span></div></div><div><div><div>7</div></div><div><span><span>localStorage</span><span>.</span></span><span>setItem</span><span>(</span></div></div><div><div><div>8</div></div><div><span>  </span><span>'theme'</span><span>,</span></div></div><div><div><div>9</div></div><div><span>  </span><span>'dark'</span></div></div><div><div><div>10</div></div><div><span>);</span></div></div><div><div><div>11</div></div><div><span>//保存用户信息</span></div></div><div><div><div>12</div></div><div><span><span>localStorage</span><span>.</span></span><span>setItem</span><span>(</span></div></div><div><div><div>13</div></div><div><span>  </span><span>'userInfo'</span><span>,</span></div></div><div><div><div>14</div></div><div><span>  </span><span>JSON</span><span>.</span><span>stringify</span><span><span>(</span><span>user</span><span>)</span></span></div></div><div><div><div>15</div></div><div><span>);</span></div></div><div><div><div>16</div></div><div><span>//保存搜索历史</span></div></div><div><div><div>17</div></div><div><span><span>localStorage</span><span>.</span></span><span>setItem</span><span>(</span></div></div><div><div><div>18</div></div><div><span>  </span><span>'history'</span><span>,</span></div></div><div><div><div>19</div></div><div><span>  </span><span>JSON</span><span>.</span><span>stringify</span><span><span>(</span><span>list</span><span>)</span></span></div></div><div><div><div>20</div></div><div><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>为什么 Token 喜欢放 localStorage？</strong></p><ul>
<li>不会自动发送、容量大、操作简单</li>
</ul><p><strong>localStorage 的缺点</strong></p><ul>
<li>容易被 XSS 攻击，不要把高敏感数据放 localStorage。</li>
<li>不会自动过期，需要自己管理过期时间。</li>
<li>只能存字符串</li>
</ul></section>
<section><h2>localStorage 的注意事项<a href="#localstorage-的注意事项"><span>#</span></a></h2><ul>
<li>
<p>只能存字符串</p>
</li>
<li>
<p>关闭浏览器不会消失</p>
</li>
<li>
<p>没有过期时间，如果要设置过期：</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//存</span></div></div><div><div><div>2</div></div><div><span><span>localStorage</span><span>.</span></span><span>setItem</span><span>(</span></div></div><div><div><div>3</div></div><div><span>  </span><span>'token'</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>JSON</span><span>.</span><span>stringify</span><span>({</span></div></div><div><div><div>5</div></div><div><span>    </span><span>value</span><span>:</span><span> </span><span>'abc'</span><span>,</span></div></div><div><div><div>6</div></div><div><span>    </span><span>expire</span><span>:</span><span><span> </span><span>Date</span><span>.</span></span><span>now</span><span>() </span><span>+</span><span> </span><span>3600</span><span> </span><span>*</span><span> </span><span>1000</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>8</div></div><div><span>);</span></div></div><div><div><div>9</div></div><div><span>//取</span></div></div><div><div><div>10</div></div><div><span>const</span><span> </span><span>data</span><span> </span><span>=</span><span> </span><span>JSON</span><span>.</span><span>parse</span><span>(</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>localStorage</span><span>.</span><span>getItem</span><span>(</span><span>'token'</span><span>)</span></div></div><div><div><div>12</div></div><div><span>);</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>if</span><span><span> (</span><span>Date</span><span>.</span></span><span>now</span><span>() </span><span>&gt;</span><span><span> </span><span>data</span><span>.</span></span><span>expire</span><span>) {</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>localStorage</span><span>.</span><span>removeItem</span><span>(</span><span>'token'</span><span>);</span></div></div><div><div><div>16</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
</li>
<li>
<p>容易被 XSS 攻击</p>
</li>
<li>
<p>不会自动发送给服务器</p>
</li>
<li>
<p>同源限制</p>
</li>
<li>
<p>容量有限制，5MB~10MB</p>
</li>
<li>
<p>同步 API，会阻塞 JS 主线程。</p>
</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102203-qian-duan-shu-ju-jiao-hu-yu-http-xie-yi/</id>
      <title type="text">前端数据交互与HTTP协议</title>
      <published>2026-10-22T00:44:23.000Z</published>
      <updated>2026-10-22T00:44:23.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102203-qian-duan-shu-ju-jiao-hu-yu-http-xie-yi/"/>
      <summary type="text">本文主要学习前端数据交互与HTTP协议</summary>
      <content type="html"><![CDATA[<section><h1>初识前后端通信<a href="#初识前后端通信"><span>#</span></a></h1><p><strong>是什么？</strong></p><ul>
<li>前端和后端数据交互的过程</li>
<li>可以把整个过程理解成：前端（浏览器） ←→ HTTP协议 ←→ 后端（服务器） ←→ 数据库</li>
</ul></section>
<section><h1>前后端通信的过程与概念解释<a href="#前后端通信的过程与概念解释"><span>#</span></a></h1><p><strong>前后端通讯过程</strong></p><p><img src="https://img.youzi177.cn/2026062602.webp" alt="" /></p><p><strong>概念解释</strong></p><p>前端：用户能够直接看到和操作的部分。</p><p>后端：处理业务逻辑和数据的部分。</p><p>客户端：发起请求的一方。</p><p>服务器端：提供服务并响应请求的一方。</p></section>
<section><h1>前后端的通信方式<a href="#前后端的通信方式"><span>#</span></a></h1>

<table><thead><tr><th>通信方式</th><th>是否实时</th><th>是否刷新页面</th><th>使用场景</th></tr></thead><tbody><tr><td>Form 表单</td><td>❌</td><td>✅</td><td>传统网站</td></tr><tr><td>Ajax（一种思想）</td><td>❌</td><td>❌</td><td>普通接口</td></tr><tr><td>Fetch</td><td>❌</td><td>❌</td><td>现代项目</td></tr><tr><td>Axios</td><td>❌</td><td>❌</td><td>企业开发</td></tr><tr><td>Polling</td><td>伪实时</td><td>❌</td><td>简单通知</td></tr><tr><td>Long Polling</td><td>准实时</td><td>❌</td><td>消息系统</td></tr><tr><td>SSE</td><td>单向实时</td><td>❌</td><td>AI输出、通知</td></tr><tr><td>WebSocket</td><td>双向实时</td><td>❌</td><td>聊天、游戏</td></tr></tbody></table></section>
<section><h1>初识 HTTP<a href="#初识-http"><span>#</span></a></h1><p><strong>什么是 HTTP？</strong></p><ul>
<li>HTTP 全称：HyperText Transfer Protocol（超文本传输协议）</li>
<li>简单来说：HTTP 是浏览器（客户端）和服务器（服务端）之间通信的规则。</li>
</ul><p><strong>为什么需要 HTTP？</strong></p><ul>
<li>浏览器和服务器是两台不同的计算机，它们需要一套规则：怎么发消息？消息格式是什么？怎么返回数据？返回成功还是失败？这套规则就是 HTTP。</li>
</ul><p><strong>HTTP 的工作过程</strong></p><ul>
<li>打开百度网站，浏览器发送请求</li>
<li>服务器收到请求，返回响应</li>
<li>浏览器解析 HTML，显示页面。</li>
</ul><p><strong>HTTP 是请求-响应模型</strong></p><ul>
<li>特点：一次请求-一次响应-连接结束</li>
</ul><p><strong>HTTP 中两个最重要的概念</strong></p><ul>
<li>请求（Request）：浏览器发给服务器。</li>
<li>响应（Response）：服务器返回给浏览器。</li>
</ul><p><strong>HTTP 请求包含什么？</strong></p><ul>
<li>请求行：<code>GET /user HTTP/1.1</code>，请求方法GET ；请求路径/user；协议版本：HTTP/1.1</li>
<li>请求头（Headers）：告诉服务器更多信息。</li>
<li>请求体（Body）：通常POST、PUT会有请求体。</li>
</ul><p><strong>HTTP 响应包含什么？</strong></p><ul>
<li>
<p>状态行：<code>HTTP/1.1 200 OK</code>；协议版本，状态码，状态描述</p>
</li>
<li>
<p>响应头：</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Content-Type: application/json</span></div></div><div><div><div>2</div></div><div><span>Content-Length: 100</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>响应体：</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>{</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>"name":"Tom"</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>HTTP 常见请求方法</strong></p><ul>
<li>GET：获取数据</li>
<li>POST：提交数据</li>
<li>PUT：修改数据。</li>
<li>DELETE：删除数据。</li>
</ul></section>
<section><h1>HTTP 报文<a href="#http-报文"><span>#</span></a></h1><p>可以理解成：浏览器和服务器之间传递的一封“信”。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>浏览器  --------HTTP报文--------&gt;  服务器</span></div></div><div><div><div>2</div></div><div><span>浏览器  &lt;-------HTTP报文---------  服务器</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>用一张图理解</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>【请求报文】</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>请求行</span></div></div><div><div><div>4</div></div><div><span>请求头</span></div></div><div><div><div>5</div></div><div><span>空行</span></div></div><div><div><div>6</div></div><div><span>请求体</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>【响应报文】</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>状态行</span></div></div><div><div><div>12</div></div><div><span>响应头</span></div></div><div><div><div>13</div></div><div><span>空行</span></div></div><div><div><div>14</div></div><div><span>响应体</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>HTTP 方法<a href="#http-方法"><span>#</span></a></h1><ul>
<li>发送请求时采用的方法，和响应无关</li>
<li>虽然有各自语义，但是并不是强制的</li>
</ul><p><strong>常用方法和语义：</strong></p>

<table><thead><tr><th>方法</th><th>作用</th><th>CRUD</th></tr></thead><tbody><tr><td>GET</td><td>查询数据</td><td>Read</td></tr><tr><td>POST</td><td>新增数据</td><td>Create</td></tr><tr><td>PUT</td><td>修改数据</td><td>Update</td></tr><tr><td>DELETE</td><td>删除数据</td><td>Delete</td></tr></tbody></table><p><strong>RESTful 接口设计</strong></p><p>RESTful 是一种接口设计风格，它把数据看作资源，使用 URL 表示资源，使用 HTTP 方法表示对资源的操作。</p><p>比如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//注册用户：一个接口，通过HTTP 方法表示操作</span></div></div><div><div><div>2</div></div><div><span>//get</span></div></div><div><div><div>3</div></div><div><span>https://api.youzi177.cn/api/user?id=1  //获取用户信息</span></div></div><div><div><div>4</div></div><div><span>//post</span></div></div><div><div><div>5</div></div><div><span>https://api.youzi177.cn/api/user  //注册用户</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>GET 和 POST 方法的对比<a href="#get-和-post-方法的对比"><span>#</span></a></h1><ul>
<li>get没有请求体，有请求头，用请求头发送数据</li>
<li>post有请求体，用请求体请求数据</li>
</ul><p><strong>区别：</strong></p>

<table><thead><tr><th>方法</th><th>作用</th></tr></thead><tbody><tr><td>GET</td><td>获取资源（查询）</td></tr><tr><td>POST</td><td>提交数据（新增、登录、上传等）</td></tr></tbody></table><p>数据发送方式不同：</p><ul>
<li>GET：参数通常放在 URL 后面</li>
<li>POST：参数放在请求体（Body）中</li>
</ul><p><strong>注意事项：</strong></p><ul>
<li>安全性：很多人认为GET 不安全，POST 安全，这是错误的，实际情况是，在HTTP下GET 和 POST 都是明文传输，都可以被抓包，真正的安全来自HTTPS，而不是 GET 或 POST，为什么大家觉得 GET 不安全？因为GET 参数出现在 URL 中，容易被浏览器记录，被历史记录保存，被日志记录，所以敏感数据不要用 GET。</li>
<li>数据长度限制：GET的，URL 有长度限制，IE：约 2083 个字符，现代浏览器虽然支持更长，但依然不建议传大量数据。POST理论上没有固定限制，真正限制在服务器配置、Nginx 配置、Tomcat 配置</li>
<li>是否缓存：GET浏览器会缓存，可能直接从缓存读取，POST默认不会缓存。</li>
<li>是否可以收藏：GET可以收藏，因为参数在url中，POST不能直接收藏。因为请求体不会保存到地址栏。</li>
<li>幂等性：什么是幂等？执行一次和执行多次，结果一样。GET获取用户信息，执行多次，不会改变数据，所以GET 是幂等的。POST创建三条订单，所以POST不是幂等</li>
<li>GET 不能传大数据：这是错的，GET 的数据放在 URL 中，受 URL 长度限制，不适合传大量数据。</li>
<li>POST 一定有请求体：这是错的，HTTP 规范并没有强制要求POST 必须有 Body，只是实际开发中通常会有</li>
<li>GET 一定没有请求体，这也是错的，规范没有禁止 GET 带 Body，但大部分浏览器和服务器都不支持或忽略 GET Body，实际开发中GET 基本不使用 Body。</li>
</ul></section>
<section><h1>HTTP 状态码<a href="#http-状态码"><span>#</span></a></h1>

<table><thead><tr><th>状态码</th><th>意义</th></tr></thead><tbody><tr><td>200</td><td>成功</td></tr><tr><td>201</td><td>创建成功</td></tr><tr><td>301</td><td>永久重定向【谨慎使用】</td></tr><tr><td>302</td><td>临时重定向</td></tr><tr><td>401</td><td>未登录。</td></tr><tr><td>403</td><td>没有权限。</td></tr><tr><td>404</td><td>资源不存在。</td></tr><tr><td>500</td><td>服务器内部错误。</td></tr></tbody></table></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102202babel-yu-webpack/</id>
      <title type="text">Babel与webpack</title>
      <published>2026-10-21T23:31:15.000Z</published>
      <updated>2026-10-21T23:31:15.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102202babel-yu-webpack/"/>
      <summary type="text">本文主要学习Babel与webpack</summary>
      <content type="html"><![CDATA[<section><h2>Babel 是什么<a href="#babel-是什么"><span>#</span></a></h2><p>Babel 是一个 JavaScript 编译器（转译器），负责把新的 JavaScript 代码转换成旧环境也能运行的代码。</p><p><strong>为什么需要 Babel？</strong></p><p>现代浏览器支持，但老浏览器（比如 IE）不支持箭头函数。Babel 可以把它转换成：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>fn</span><span> </span><span>=</span><span><span> (</span><span>a</span><span>, </span><span>b</span><span>) </span></span><span>=&gt;</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>//转换</span></div></div><div><div><div>4</div></div><div><span>var</span><span> </span><span>fn</span><span> </span><span>=</span><span> </span><span>function</span><span><span> (</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>5</div></div><div><span>  </span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>6</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>Babel 能干什么？</strong></p><p>转换 ES6+ 语法：箭头函数、类、模板字符串、解构赋值，转换模块语法，转换实验性语法，编译 JSX以前 Node 不支持 ESM 时，经常这么干。<strong>Babel 不是打包工具，是负责代码转换</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> { </span><span>add</span><span> } </span><span>from</span><span> </span><span>'./math.js'</span><span>;</span></div></div><div><div><div>2</div></div><div><span>//转换成</span></div></div><div><div><div>3</div></div><div><span>const</span><span> { </span><span>add</span><span> } </span><span>=</span><span> </span><span>require</span><span>(</span><span>'./math'</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>Babel 的使用方式<a href="#babel-的使用方式"><span>#</span></a></h2><p>Babel 的使用方式其实就三步：安装 Babel-配置 Babel-执行编译</p><p>初始化项目</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>npm init -y</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>安装 Babel</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>npm install -D @babel/core @babel/cli @babel/preset-env</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>创建源码：</p><div><figure><figcaption><span>src/index.js</span></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>fn</span><span> </span><span>=</span><span><span> (</span><span>a</span><span>, </span><span>b</span><span>) </span></span><span>=&gt;</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>fn</span><span>(</span><span>1</span><span>, </span><span>2</span><span>));</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>配置 Babel：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//babel.config.json</span></div></div><div><div><div>2</div></div><div><span>{</span></div></div><div><div><div>3</div></div><div><span>  </span><span>"presets"</span><span>: [</span><span>"@babel/preset-env"</span><span>]</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div><span>//或者</span></div></div><div><div><div>6</div></div><div><span>//.babelrc</span></div></div><div><div><div>7</div></div><div><span>{</span></div></div><div><div><div>8</div></div><div><span>  </span><span>"presets"</span><span>: [</span><span>"@babel/preset-env"</span><span>]</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>执行编译</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>npx</span><span> </span><span>babel</span><span> </span><span>src</span><span> </span></span><span>-</span><span><span>d</span><span> </span><span>dist</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>生成：dist/index.js</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>"use strict"</span><span>;</span></div></div><div><div><div>2</div></div><div><span>var</span><span> </span><span>fn</span><span> </span><span>=</span><span> </span><span>function</span><span> </span><span>fn</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>  </span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>};</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>fn</span><span>(</span><span>1</span><span>, </span><span>2</span><span>));</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>package.json 配置脚本</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>{</span></div></div><div><div><div>2</div></div><div><span>  </span><span>"scripts"</span><span>: {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>"build"</span><span>:</span><span> </span><span>"babel src -d dist"</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>指定目标环境：如果这里不设置，Babel（<code>@babel/preset-env</code>）默认会根据**目标环境（targets）**决定是否转换，现代环境下就不转换了</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>{</span></div></div><div><div><div>2</div></div><div><span>  </span><span>"presets"</span><span>: [</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>[</span></div></div><div><div><div>4</div></div><div><span>      </span><span>"@babel/preset-env"</span><span>,</span></div></div><div><div><div>5</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>6</div></div><div><span>        </span><span>"targets"</span><span>:</span><span> {</span></div></div><div><div><div>7</div></div><div><span>          </span><span>"chrome"</span><span>:</span><span> </span><span>"80"</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>]</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>]</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div><span>//只兼容 Chrome80+</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>配合 browserslist，Babel 会自动根据目标浏览器决定转换哪些语法。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//package.json</span></div></div><div><div><div>2</div></div><div><span>{</span></div></div><div><div><div>3</div></div><div><span>  </span><span>"browserslist"</span><span>: [</span></div></div><div><div><div>4</div></div><div><span>    </span><span>"&gt;1%"</span><span>,</span></div></div><div><div><div>5</div></div><div><span>    </span><span>"last 2 versions"</span><span>,</span></div></div><div><div><div>6</div></div><div><span>    </span><span>"not dead"</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>]</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>使用 Babel 前的准备工作<a href="#使用-babel-前的准备工作"><span>#</span></a></h2><ul>
<li>安装nodejs和npm ；推荐使用nvm</li>
<li>初始化项目(Babel 的使用方式已经有讲解)</li>
<li>安装bable需要的包(Babel 的使用方式已经有讲解)</li>
</ul></section>
<section><h2>使用 Babel 编译 ES6 代码<a href="#使用-babel-编译-es6-代码"><span>#</span></a></h2><ul>
<li>Babel 的使用方式已经有讲解</li>
</ul></section>
<section><h2>Webpack是什么<a href="#webpack是什么"><span>#</span></a></h2><ul>
<li>Webpack 是一个静态模块打包工具（Static Module Bundler）。</li>
<li>webpack是<strong>静态模块</strong>打包器，当webpack处理应用程序时，会将所有这些模块打包成一个或多个文件</li>
<li>模块：webpack可以处理js/css/图片、图标字体等单位文件</li>
<li>静态：开发过程中存在于本地的js/css/图片/图标字体等文件，就是静态的</li>
<li>动态内容webpack没办法处理</li>
</ul></section>
<section><h2>Webpack 初体验<a href="#webpack-初体验"><span>#</span></a></h2><p><strong>初始化项目</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>mkdir webpack-demo</span></div></div><div><div><div>2</div></div><div><span>cd webpack-demo</span></div></div><div><div><div>3</div></div><div><span>npm init -y</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>安装webpack需要的包</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>npm i webpack webpack-cli -D</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>创建示例代码：</strong></p><p>src/math.js</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>function</span><span> </span><span>add</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>src/index.js</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> { </span><span>add</span><span> } </span><span>from</span><span> </span><span>'./math'</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>add</span><span>(</span><span>1</span><span>, </span><span>2</span><span>));</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>配置webpack</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>path</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'path'</span><span>);</span></div></div><div><div><div>2</div></div><div><span>module</span><span>.</span><span>exports</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>mode</span><span>:</span><span> </span><span>'development'</span><span>, </span><span>//  development开发模式 production生产模式</span></div></div><div><div><div>4</div></div><div><span>  </span><span>entry</span><span>:</span><span> </span><span>'./src/index.js'</span><span>,</span></div></div><div><div><div>5</div></div><div><span>  </span><span>output</span><span>:</span><span> {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>filename</span><span>:</span><span> </span><span>'bundle.js'</span><span>,</span></div></div><div><div><div>7</div></div><div><span>    </span><span>path</span><span>:</span><span><span> </span><span>path</span><span>.</span></span><span>resolve</span><span><span>(</span><span>__dirname</span><span>, </span></span><span>'dist'</span><span>),</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>9</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>development（开发模式）：不压缩、可读性强、调试友好、构建快</p><p>production（生产模式）：代码压缩、Tree Shaking、性能优化、文件更小</p><p><strong>打包测试</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>npx webpack</span></div></div><div><div><div>2</div></div><div><span>node dist/bundle.js</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>entry和output<a href="#entry和output"><span>#</span></a></h2><ul>
<li>webpacke的4核心概念：entry、output、loader、plugins</li>
<li>entry输入：就是程序入口</li>
<li>output输出：打包之后路径</li>
</ul></section>
<section><h2>loader<a href="#loader"><span>#</span></a></h2><p>Loader 的作用：让 Webpack 能“读懂”非 JS 文件</p><p>试试babel-loader，ES6 → ES5</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>npm i -D babel-loader</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>path</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'path'</span><span>);</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>module</span><span>.</span><span>exports</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>4</div></div><div><span>  </span><span>mode</span><span>:</span><span> </span><span>'development'</span><span>,</span></div></div><div><div><div>5</div></div><div><span>  </span><span>entry</span><span>:</span><span> </span><span>'./src/index.js'</span><span>,</span></div></div><div><div><div>6</div></div><div><span>  </span><span>output</span><span>:</span><span> {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>filename</span><span>:</span><span> </span><span>'bundle.js'</span><span>,</span></div></div><div><div><div>8</div></div><div><span>    </span><span>path</span><span>:</span><span><span> </span><span>path</span><span>.</span></span><span>resolve</span><span><span>(</span><span>__dirname</span><span>, </span></span><span>'dist'</span><span>),</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>10</div></div><div><span>  </span><span>module</span><span>:</span><span> {</span></div></div><div><div><div>11</div></div><div><span>    </span><span>rules</span><span>:</span><span> [</span></div></div><div><div><div>12</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>13</div></div><div><span>        </span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>(js</span><span>|</span><span>jsx)</span></span><span>$</span><span>/</span><span>,</span></div></div><div><div><div>14</div></div><div><span>        </span><span>use</span><span>:</span><span> [</span><span>'babel-loader'</span><span>],</span></div></div><div><div><div>15</div></div><div><span>        </span><span>exclude</span><span>:</span><span><span> [</span><span>path</span><span>.</span></span><span>join</span><span><span>(</span><span>__dirname</span><span>, </span></span><span>'./node_modules'</span><span>)], </span><span>//排除node_modules</span></div></div><div><div><div>16</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>],</span></div></div><div><div><div>18</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>19</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>Loader 可以链式执行，执行顺序是 <strong>从右到左</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>use: ['style-loader', 'css-loader', 'postcss-loader']</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>plugins<a href="#plugins"><span>#</span></a></h2><p>Plugin 用来“增强 Webpack 的能力”，而不是转换单个文件。</p><p>做什么：监听 Webpack 整个生命周期，做“全局事情”，比如打包前清空 dist、自动生成 HTML、压缩 JS、提取 CSS、打包分析、注入环境变量</p><p>区别：</p>

<table><thead><tr><th>对比</th><th>Loader</th><th>Plugin</th></tr></thead><tbody><tr><td>作用</td><td>转换文件</td><td>扩展功能</td></tr><tr><td>作用范围</td><td>单个模块</td><td>整个构建流程</td></tr><tr><td>时机</td><td>加载阶段</td><td>编译生命周期</td></tr><tr><td>写法</td><td><code>rules</code></td><td><code>plugins</code></td></tr></tbody></table><p>举例： 清理 dist，插件clean-webpack-plugin ，每次打包前清空 dist目录</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>npm install --save-dev clean-webpack-plugin</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> { </span><span>CleanWebpackPlugin</span><span> } </span><span>=</span><span> </span><span>require</span><span>(</span><span>'clean-webpack-plugin'</span><span>);</span></div></div><div><div><div>2</div></div><div><span><span>plugins</span><span>: [</span></span><span>new</span><span> </span><span>CleanWebpackPlugin</span><span>()]</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>从 <strong>Webpack 5</strong> 开始，官方已经内置了类似功能，可以直接使用</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>module</span><span>.</span><span>exports</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>output</span><span>:</span><span> {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>clean</span><span>:</span><span> </span><span>true</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>举例： 插件HtmlWebpackPlugin，该插件将为你生成一个 HTML5 文件， 在 body 中使用 <code>script</code> 标签引入你所有 webpack 生成的 bundle</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>npm install --save-dev html-webpack-plugin</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>HtmlWebpackPlugin</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'html-webpack-plugin'</span><span>);</span></div></div><div><div><div>2</div></div><div><span><span>plugins</span><span>: [ </span></span><span>new</span><span> </span><span>HtmlWebpackPlugin</span><span>()],</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>HtmlWebpackPlugin进阶使用：多个js入口文件，多个html，a.html引入a.js，b.html引入b.js；并且配置压缩minify</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>path</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'path'</span><span>);</span></div></div><div><div><div>2</div></div><div><span>const</span><span> { </span><span>CleanWebpackPlugin</span><span> } </span><span>=</span><span> </span><span>require</span><span>(</span><span>'clean-webpack-plugin'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>HtmlWebpackPlugin</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'html-webpack-plugin'</span><span>);</span></div></div><div><div><div>4</div></div><div><span>module</span><span>.</span><span>exports</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>5</div></div><div><span>  </span><span>mode</span><span>:</span><span> </span><span>'development'</span><span>,</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>  </span><span>entry</span><span>:</span><span> {</span></div></div><div><div><div>8</div></div><div><span>    </span><span>index</span><span>:</span><span> </span><span>'./src/index.js'</span><span>,</span></div></div><div><div><div>9</div></div><div><span>    </span><span>search</span><span>:</span><span> </span><span>'./src/search.js'</span><span>,</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>  </span><span>output</span><span>:</span><span> {</span></div></div><div><div><div>13</div></div><div><span>    </span><span>filename</span><span>:</span><span> </span><span>'[name].js'</span><span>,</span></div></div><div><div><div>14</div></div><div><span>    </span><span>path</span><span>:</span><span><span> </span><span>path</span><span>.</span></span><span>resolve</span><span><span>(</span><span>__dirname</span><span>, </span></span><span>'dist'</span><span>),</span></div></div><div><div><div>15</div></div><div><span>    </span><span>clean</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>17</div></div><div><span>  </span><span>module</span><span>:</span><span> {</span></div></div><div><div><div>18</div></div><div><span>    </span><span>rules</span><span>:</span><span> [</span></div></div><div><div><div>19</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>20</div></div><div><span>        </span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>(js</span><span>|</span><span>jsx)</span></span><span>$</span><span>/</span><span>,</span></div></div><div><div><div>21</div></div><div><span>        </span><span>use</span><span>:</span><span> [</span><span>'babel-loader'</span><span>],</span></div></div><div><div><div>22</div></div><div><span>        </span><span>exclude</span><span>:</span><span><span> [</span><span>path</span><span>.</span></span><span>join</span><span><span>(</span><span>__dirname</span><span>, </span></span><span>'./node_modules'</span><span>)], </span><span>//排除node_modules</span></div></div><div><div><div>23</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>24</div></div><div><span><span>    </span></span><span>],</span></div></div><div><div><div>25</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>26</div></div><div><span>  </span><span>plugins</span><span>:</span><span> [</span></div></div><div><div><div>27</div></div><div><span>    </span><span>new</span><span> </span><span>HtmlWebpackPlugin</span><span>({</span></div></div><div><div><div>28</div></div><div><span>      </span><span>// template: 'index.html',不写模板，自动创建，demo样式可以这样</span></div></div><div><div><div>29</div></div><div><span>      </span><span>filename</span><span>:</span><span> </span><span>'index.html'</span><span>, </span><span>//重命名</span></div></div><div><div><div>30</div></div><div><span>      </span><span>chunks</span><span>:</span><span> [</span><span>'index'</span><span>], </span><span>//指定引入</span></div></div><div><div><div>31</div></div><div><span>      </span><span>minify</span><span>:</span><span> {</span></div></div><div><div><div>32</div></div><div><span>        </span><span>collapseWhitespace</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>33</div></div><div><span>        </span><span>keepClosingSlash</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>34</div></div><div><span>        </span><span>removeComments</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>35</div></div><div><span>        </span><span>removeRedundantAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>36</div></div><div><span>        </span><span>removeScriptTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>37</div></div><div><span>        </span><span>removeStyleLinkTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>38</div></div><div><span>        </span><span>useShortDoctype</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>39</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>40</div></div><div><span><span>    </span></span><span>}),</span></div></div><div><div><div>41</div></div><div><span>    </span><span>new</span><span> </span><span>HtmlWebpackPlugin</span><span>({</span></div></div><div><div><div>42</div></div><div><span>      </span><span>// template: 'search.html',</span></div></div><div><div><div>43</div></div><div><span>      </span><span>filename</span><span>:</span><span> </span><span>'search.html'</span><span>, </span><span>//重命名</span></div></div><div><div><div>44</div></div><div><span>      </span><span>chunks</span><span>:</span><span> [</span><span>'search'</span><span>], </span><span>//指定引入</span></div></div><div><div><div>45</div></div><div><span>      </span><span>minify</span><span>:</span><span> {</span></div></div><div><div><div>46</div></div><div><span>        </span><span>collapseWhitespace</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>47</div></div><div><span>        </span><span>keepClosingSlash</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>48</div></div><div><span>        </span><span>removeComments</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>49</div></div><div><span>        </span><span>removeRedundantAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>50</div></div><div><span>        </span><span>removeScriptTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>51</div></div><div><span>        </span><span>removeStyleLinkTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>52</div></div><div><span>        </span><span>useShortDoctype</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>53</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>54</div></div><div><span><span>    </span></span><span>}),</span></div></div><div><div><div>55</div></div><div><span><span>  </span></span><span>],</span></div></div><div><div><div>56</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>处理CSS文件<a href="#处理css文件"><span>#</span></a></h2><p>webpack不认识除js以外的文件，所以这里需要loader</p><p>安装：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>npm install -D style-loader css-loader</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>配置 Webpack</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>path</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'path'</span><span>);</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>module</span><span>.</span><span>exports</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>4</div></div><div><span>  </span><span>mode</span><span>:</span><span> </span><span>'development'</span><span>,</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>  </span><span>entry</span><span>:</span><span> </span><span>'./src/index.js'</span><span>,</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>  </span><span>output</span><span>:</span><span> {</span></div></div><div><div><div>9</div></div><div><span>    </span><span>filename</span><span>:</span><span> </span><span>'bundle.js'</span><span>,</span></div></div><div><div><div>10</div></div><div><span>    </span><span>path</span><span>:</span><span><span> </span><span>path</span><span>.</span></span><span>resolve</span><span><span>(</span><span>__dirname</span><span>, </span></span><span>'dist'</span><span>)</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>  </span><span>module</span><span>:</span><span> {</span></div></div><div><div><div>14</div></div><div><span>    </span><span>rules</span><span>:</span><span> [</span></div></div><div><div><div>15</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>16</div></div><div><span>        </span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>css</span></span><span>$</span><span>/</span><span>,</span></div></div><div><div><div>17</div></div><div><span>        </span><span>use</span><span>:</span><span> [</span><span>'style-loader'</span><span>, </span><span>'css-loader'</span><span>] </span><span>//⚠️loader 执行顺序是从右到左</span></div></div><div><div><div>18</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>]</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>21</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>Webpack 实际做了这些事：</p><p>1：css-loader 阶段：把style.css转换成 JS 模块，类似：<code>export default "body { background: pink; }";</code></p><p>2：style-loader 阶段：把 CSS 插入 DOM，类似：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const style = document.createElement('style');</span></div></div><div><div><div>2</div></div><div><span>style.innerHTML = "body { background: pink; }";</span></div></div><div><div><div>3</div></div><div><span>document.head.appendChild(style);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>进阶处理CSS，使用link方式引入</p><p>安装插件：mini-css-extract-plugin</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>npm install -D mini-css-extract-plugin</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>使用：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>MiniCssExtractPlugin</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'mini-css-extract-plugin'</span><span>)</span></div></div><div><div><div>2</div></div><div><span>{</span></div></div><div><div><div>3</div></div><div><span><span>        </span></span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>css</span></span><span>$</span><span>/</span><span>,</span></div></div><div><div><div>4</div></div><div><span><span>        </span></span><span>use</span><span>: [</span><span>MiniCssExtractPlugin</span><span>.</span><span>loader</span><span>, </span><span>'css-loader'</span><span>], </span><span>//换MiniCssExtractPlugin.loader</span></div></div><div><div><div>5</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>6</div></div><div><span>new</span><span> </span><span>MiniCssExtractPlugin</span><span>({</span></div></div><div><div><div>7</div></div><div><span>      </span><span>filename</span><span>:</span><span> </span><span>'css/[name].css'</span><span>,</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>}),</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>完整：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>path</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'path'</span><span>);</span></div></div><div><div><div>2</div></div><div><span>const</span><span> { </span><span>CleanWebpackPlugin</span><span> } </span><span>=</span><span> </span><span>require</span><span>(</span><span>'clean-webpack-plugin'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>HtmlWebpackPlugin</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'html-webpack-plugin'</span><span>);</span></div></div><div><div><div>4</div></div><div><span>const</span><span> </span><span>MiniCssExtractPlugin</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'mini-css-extract-plugin'</span><span>);</span></div></div><div><div><div>5</div></div><div><span>module</span><span>.</span><span>exports</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>6</div></div><div><span>  </span><span>mode</span><span>:</span><span> </span><span>'production'</span><span>,</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>  </span><span>entry</span><span>:</span><span> {</span></div></div><div><div><div>9</div></div><div><span>    </span><span>index</span><span>:</span><span> </span><span>'./src/index.js'</span><span>,</span></div></div><div><div><div>10</div></div><div><span>    </span><span>search</span><span>:</span><span> </span><span>'./src/search.js'</span><span>,</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>  </span><span>output</span><span>:</span><span> {</span></div></div><div><div><div>14</div></div><div><span>    </span><span>filename</span><span>:</span><span> </span><span>'[name].js'</span><span>,</span></div></div><div><div><div>15</div></div><div><span>    </span><span>path</span><span>:</span><span><span> </span><span>path</span><span>.</span></span><span>resolve</span><span><span>(</span><span>__dirname</span><span>, </span></span><span>'dist'</span><span>),</span></div></div><div><div><div>16</div></div><div><span>    </span><span>clean</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>18</div></div><div><span>  </span><span>module</span><span>:</span><span> {</span></div></div><div><div><div>19</div></div><div><span>    </span><span>rules</span><span>:</span><span> [</span></div></div><div><div><div>20</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>21</div></div><div><span>        </span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>(js</span><span>|</span><span>jsx)</span></span><span>$</span><span>/</span><span>,</span></div></div><div><div><div>22</div></div><div><span>        </span><span>use</span><span>:</span><span> [</span><span>'babel-loader'</span><span>],</span></div></div><div><div><div>23</div></div><div><span>        </span><span>exclude</span><span>:</span><span><span> [</span><span>path</span><span>.</span></span><span>join</span><span><span>(</span><span>__dirname</span><span>, </span></span><span>'./node_modules'</span><span>)], </span><span>//排除node_modules</span></div></div><div><div><div>24</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>25</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>26</div></div><div><span>        </span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>css</span></span><span>$</span><span>/</span><span>,</span></div></div><div><div><div>27</div></div><div><span>        </span><span>use</span><span>:</span><span><span> [</span><span>MiniCssExtractPlugin</span><span>.</span></span><span>loader</span><span>, </span><span>'css-loader'</span><span>], </span><span>//换MiniCssExtractPlugin.loader</span></div></div><div><div><div>28</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>29</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>30</div></div><div><span>        </span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>(png</span><span>|</span><span>jpg</span><span>|</span><span>jpeg</span><span>|</span><span>gif)</span></span><span>$</span><span>/</span><span>i</span><span>,</span></div></div><div><div><div>31</div></div><div><span>        </span><span>type</span><span>:</span><span> </span><span>'asset/resource'</span><span>,</span></div></div><div><div><div>32</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>33</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>34</div></div><div><span>        </span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>(png</span><span>|</span><span>jpg</span><span>|</span><span>jpeg)</span></span><span>$</span><span>/</span><span>i</span><span>,</span></div></div><div><div><div>35</div></div><div><span>        </span><span>use</span><span>:</span><span> [</span></div></div><div><div><div>36</div></div><div><span><span>          </span></span><span>{</span></div></div><div><div><div>37</div></div><div><span>            </span><span>loader</span><span>:</span><span> </span><span>'image-webpack-loader'</span><span>,</span></div></div><div><div><div>38</div></div><div><span>            </span><span>options</span><span>:</span><span> {</span></div></div><div><div><div>39</div></div><div><span>              </span><span>mozjpeg</span><span>:</span><span> {</span></div></div><div><div><div>40</div></div><div><span>                </span><span>quality</span><span>:</span><span> </span><span>70</span><span>,</span></div></div><div><div><div>41</div></div><div><span><span>              </span></span><span>},</span></div></div><div><div><div>42</div></div><div><span><span>            </span></span><span>},</span></div></div><div><div><div>43</div></div><div><span><span>          </span></span><span>},</span></div></div><div><div><div>44</div></div><div><span><span>        </span></span><span>],</span></div></div><div><div><div>45</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>46</div></div><div><span><span>    </span></span><span>],</span></div></div><div><div><div>47</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>48</div></div><div><span>  </span><span>plugins</span><span>:</span><span> [</span></div></div><div><div><div>49</div></div><div><span>    </span><span>new</span><span> </span><span>HtmlWebpackPlugin</span><span>({</span></div></div><div><div><div>50</div></div><div><span>      </span><span>// template: 'index.html',不写模板，自动创建，demo样式可以这样</span></div></div><div><div><div>51</div></div><div><span>      </span><span>filename</span><span>:</span><span> </span><span>'index.html'</span><span>, </span><span>//重命名</span></div></div><div><div><div>52</div></div><div><span>      </span><span>chunks</span><span>:</span><span> [</span><span>'index'</span><span>], </span><span>//指定引入</span></div></div><div><div><div>53</div></div><div><span>      </span><span>minify</span><span>:</span><span> {</span></div></div><div><div><div>54</div></div><div><span>        </span><span>collapseWhitespace</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>55</div></div><div><span>        </span><span>keepClosingSlash</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>56</div></div><div><span>        </span><span>removeComments</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>57</div></div><div><span>        </span><span>removeRedundantAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>58</div></div><div><span>        </span><span>removeScriptTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>59</div></div><div><span>        </span><span>removeStyleLinkTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>60</div></div><div><span>        </span><span>useShortDoctype</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>61</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>62</div></div><div><span><span>    </span></span><span>}),</span></div></div><div><div><div>63</div></div><div><span>    </span><span>new</span><span> </span><span>HtmlWebpackPlugin</span><span>({</span></div></div><div><div><div>64</div></div><div><span>      </span><span>// template: 'search.html',</span></div></div><div><div><div>65</div></div><div><span>      </span><span>filename</span><span>:</span><span> </span><span>'search.html'</span><span>, </span><span>//重命名</span></div></div><div><div><div>66</div></div><div><span>      </span><span>chunks</span><span>:</span><span> [</span><span>'search'</span><span>], </span><span>//指定引入</span></div></div><div><div><div>67</div></div><div><span>      </span><span>minify</span><span>:</span><span> {</span></div></div><div><div><div>68</div></div><div><span>        </span><span>collapseWhitespace</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>69</div></div><div><span>        </span><span>keepClosingSlash</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>70</div></div><div><span>        </span><span>removeComments</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>71</div></div><div><span>        </span><span>removeRedundantAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>72</div></div><div><span>        </span><span>removeScriptTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>73</div></div><div><span>        </span><span>removeStyleLinkTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>74</div></div><div><span>        </span><span>useShortDoctype</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>75</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>76</div></div><div><span><span>    </span></span><span>}),</span></div></div><div><div><div>77</div></div><div><span>    </span><span>new</span><span> </span><span>MiniCssExtractPlugin</span><span>({</span></div></div><div><div><div>78</div></div><div><span>      </span><span>filename</span><span>:</span><span> </span><span>'css/[name].css'</span><span>,</span></div></div><div><div><div>79</div></div><div><span><span>    </span></span><span>}),</span></div></div><div><div><div>80</div></div><div><span><span>  </span></span><span>],</span></div></div><div><div><div>81</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>使用file-loader处理CSS中的图片<a href="#使用file-loader处理css中的图片"><span>#</span></a></h2><ul>
<li>
<p>webpack不会处理远程的图片，所以，如果图片是在外部服务器的，webpack不会处理，可以正常执行</p>
</li>
<li>
<p>注意：在webpack4之前，处理本地css图片是需要这个包的，但是webpack5新增了Asset Modules，并且默认开启，所以在webpack5即便什么都不做，也不会出错，file-loader在webpack5不推荐使用</p>
</li>
<li>
<p>file-loader使用 ⚠2026年6月25日，webpack5下这插件不能使用，有问题，推荐新写法</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>npm install -D file-loader</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>path</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'path'</span><span>);</span></div></div><div><div><div>2</div></div><div><span>const</span><span> { </span><span>CleanWebpackPlugin</span><span> } </span><span>=</span><span> </span><span>require</span><span>(</span><span>'clean-webpack-plugin'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>HtmlWebpackPlugin</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'html-webpack-plugin'</span><span>);</span></div></div><div><div><div>4</div></div><div><span>const</span><span> </span><span>MiniCssExtractPlugin</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'mini-css-extract-plugin'</span><span>);</span></div></div><div><div><div>5</div></div><div><span>module</span><span>.</span><span>exports</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>6</div></div><div><span>  </span><span>mode</span><span>:</span><span> </span><span>'production'</span><span>,</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>  </span><span>entry</span><span>:</span><span> {</span></div></div><div><div><div>9</div></div><div><span>    </span><span>index</span><span>:</span><span> </span><span>'./src/index.js'</span><span>,</span></div></div><div><div><div>10</div></div><div><span>    </span><span>search</span><span>:</span><span> </span><span>'./src/search.js'</span><span>,</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>  </span><span>output</span><span>:</span><span> {</span></div></div><div><div><div>14</div></div><div><span>    </span><span>filename</span><span>:</span><span> </span><span>'[name].js'</span><span>,</span></div></div><div><div><div>15</div></div><div><span>    </span><span>path</span><span>:</span><span><span> </span><span>path</span><span>.</span></span><span>resolve</span><span><span>(</span><span>__dirname</span><span>, </span></span><span>'dist'</span><span>),</span></div></div><div><div><div>16</div></div><div><span>    </span><span>clean</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>18</div></div><div><span>  </span><span>module</span><span>:</span><span> {</span></div></div><div><div><div>19</div></div><div><span>    </span><span>rules</span><span>:</span><span> [</span></div></div><div><div><div>20</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>21</div></div><div><span>        </span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>(js</span><span>|</span><span>jsx)</span></span><span>$</span><span>/</span><span>,</span></div></div><div><div><div>22</div></div><div><span>        </span><span>use</span><span>:</span><span> [</span><span>'babel-loader'</span><span>],</span></div></div><div><div><div>23</div></div><div><span>        </span><span>exclude</span><span>:</span><span><span> [</span><span>path</span><span>.</span></span><span>join</span><span><span>(</span><span>__dirname</span><span>, </span></span><span>'./node_modules'</span><span>)], </span><span>//排除node_modules</span></div></div><div><div><div>24</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>25</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>26</div></div><div><span>        </span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>css</span></span><span>$</span><span>/</span><span>,</span></div></div><div><div><div>27</div></div><div><span>        </span><span>use</span><span>:</span><span><span> [</span><span>MiniCssExtractPlugin</span><span>.</span></span><span>loader</span><span>, </span><span>'css-loader'</span><span>], </span><span>//换MiniCssExtractPlugin.loader</span></div></div><div><div><div>28</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>29</div></div><div><span>      </span><span>// webpack5新特性</span></div></div><div><div><div>30</div></div><div><span>      </span><span>// {</span></div></div><div><div><div>31</div></div><div><span>      </span><span>//   test: /\.(png|jpg|jpeg|gif)$/i,</span></div></div><div><div><div>32</div></div><div><span>      </span><span>//   type: 'asset/resource',</span></div></div><div><div><div>33</div></div><div><span>      </span><span>// },</span></div></div><div><div><div>34</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>35</div></div><div><span>        </span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>(png</span><span>|</span><span>jpg</span><span>|</span><span>jpeg</span><span>|</span><span>gif)</span></span><span>$</span><span>/</span><span>i</span><span>,</span></div></div><div><div><div>36</div></div><div><span>        </span><span>use</span><span>:</span><span> [</span></div></div><div><div><div>37</div></div><div><span><span>          </span></span><span>{</span></div></div><div><div><div>38</div></div><div><span>            </span><span>loader</span><span>:</span><span> </span><span>'file-loader'</span><span>,</span></div></div><div><div><div>39</div></div><div><span>            </span><span>options</span><span>:</span><span> {</span></div></div><div><div><div>40</div></div><div><span>              </span><span>name</span><span>:</span><span> </span><span>'[name].[hash].[ext]'</span><span>,</span></div></div><div><div><div>41</div></div><div><span>              </span><span>outputPath</span><span>:</span><span> </span><span>'images'</span><span>,</span></div></div><div><div><div>42</div></div><div><span><span>            </span></span><span>},</span></div></div><div><div><div>43</div></div><div><span><span>          </span></span><span>},</span></div></div><div><div><div>44</div></div><div><span><span>        </span></span><span>],</span></div></div><div><div><div>45</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>46</div></div><div>
</div></div><div><div><div>47</div></div><div><span><span>    </span></span><span>],</span></div></div><div><div><div>48</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>49</div></div><div><span>  </span><span>plugins</span><span>:</span><span> [</span></div></div><div><div><div>50</div></div><div><span>    </span><span>new</span><span> </span><span>HtmlWebpackPlugin</span><span>({</span></div></div><div><div><div>51</div></div><div><span>      </span><span>// template: 'index.html',不写模板，自动创建，demo样式可以这样</span></div></div><div><div><div>52</div></div><div><span>      </span><span>filename</span><span>:</span><span> </span><span>'index.html'</span><span>, </span><span>//重命名</span></div></div><div><div><div>53</div></div><div><span>      </span><span>chunks</span><span>:</span><span> [</span><span>'index'</span><span>], </span><span>//指定引入</span></div></div><div><div><div>54</div></div><div><span>      </span><span>minify</span><span>:</span><span> {</span></div></div><div><div><div>55</div></div><div><span>        </span><span>collapseWhitespace</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>56</div></div><div><span>        </span><span>keepClosingSlash</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>57</div></div><div><span>        </span><span>removeComments</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>58</div></div><div><span>        </span><span>removeRedundantAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>59</div></div><div><span>        </span><span>removeScriptTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>60</div></div><div><span>        </span><span>removeStyleLinkTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>61</div></div><div><span>        </span><span>useShortDoctype</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>62</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>63</div></div><div><span><span>    </span></span><span>}),</span></div></div><div><div><div>64</div></div><div><span>    </span><span>new</span><span> </span><span>HtmlWebpackPlugin</span><span>({</span></div></div><div><div><div>65</div></div><div><span>      </span><span>// template: 'search.html',</span></div></div><div><div><div>66</div></div><div><span>      </span><span>filename</span><span>:</span><span> </span><span>'search.html'</span><span>, </span><span>//重命名</span></div></div><div><div><div>67</div></div><div><span>      </span><span>chunks</span><span>:</span><span> [</span><span>'search'</span><span>], </span><span>//指定引入</span></div></div><div><div><div>68</div></div><div><span>      </span><span>minify</span><span>:</span><span> {</span></div></div><div><div><div>69</div></div><div><span>        </span><span>collapseWhitespace</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>70</div></div><div><span>        </span><span>keepClosingSlash</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>71</div></div><div><span>        </span><span>removeComments</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>72</div></div><div><span>        </span><span>removeRedundantAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>73</div></div><div><span>        </span><span>removeScriptTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>74</div></div><div><span>        </span><span>removeStyleLinkTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>75</div></div><div><span>        </span><span>useShortDoctype</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>76</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>77</div></div><div><span><span>    </span></span><span>}),</span></div></div><div><div><div>78</div></div><div><span>    </span><span>new</span><span> </span><span>MiniCssExtractPlugin</span><span>({</span></div></div><div><div><div>79</div></div><div><span>      </span><span>filename</span><span>:</span><span> </span><span>'css/[name].css'</span><span>,</span></div></div><div><div><div>80</div></div><div><span><span>    </span></span><span>}),</span></div></div><div><div><div>81</div></div><div><span><span>  </span></span><span>],</span></div></div><div><div><div>82</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
<p>webpack新写法：asset/resource</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>path</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'path'</span><span>);</span></div></div><div><div><div>2</div></div><div><span>const</span><span> { </span><span>CleanWebpackPlugin</span><span> } </span><span>=</span><span> </span><span>require</span><span>(</span><span>'clean-webpack-plugin'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>HtmlWebpackPlugin</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'html-webpack-plugin'</span><span>);</span></div></div><div><div><div>4</div></div><div><span>const</span><span> </span><span>MiniCssExtractPlugin</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'mini-css-extract-plugin'</span><span>);</span></div></div><div><div><div>5</div></div><div><span>module</span><span>.</span><span>exports</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>6</div></div><div><span>  </span><span>mode</span><span>:</span><span> </span><span>'production'</span><span>,</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>  </span><span>entry</span><span>:</span><span> {</span></div></div><div><div><div>9</div></div><div><span>    </span><span>index</span><span>:</span><span> </span><span>'./src/index.js'</span><span>,</span></div></div><div><div><div>10</div></div><div><span>    </span><span>search</span><span>:</span><span> </span><span>'./src/search.js'</span><span>,</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>  </span><span>output</span><span>:</span><span> {</span></div></div><div><div><div>14</div></div><div><span>    </span><span>filename</span><span>:</span><span> </span><span>'[name].js'</span><span>,</span></div></div><div><div><div>15</div></div><div><span>    </span><span>path</span><span>:</span><span><span> </span><span>path</span><span>.</span></span><span>resolve</span><span><span>(</span><span>__dirname</span><span>, </span></span><span>'dist'</span><span>),</span></div></div><div><div><div>16</div></div><div><span>    </span><span>clean</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>18</div></div><div><span>  </span><span>module</span><span>:</span><span> {</span></div></div><div><div><div>19</div></div><div><span>    </span><span>rules</span><span>:</span><span> [</span></div></div><div><div><div>20</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>21</div></div><div><span>        </span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>(js</span><span>|</span><span>jsx)</span></span><span>$</span><span>/</span><span>,</span></div></div><div><div><div>22</div></div><div><span>        </span><span>use</span><span>:</span><span> [</span><span>'babel-loader'</span><span>],</span></div></div><div><div><div>23</div></div><div><span>        </span><span>exclude</span><span>:</span><span><span> [</span><span>path</span><span>.</span></span><span>join</span><span><span>(</span><span>__dirname</span><span>, </span></span><span>'./node_modules'</span><span>)], </span><span>//排除node_modules</span></div></div><div><div><div>24</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>25</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>26</div></div><div><span>        </span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>css</span></span><span>$</span><span>/</span><span>,</span></div></div><div><div><div>27</div></div><div><span>        </span><span>use</span><span>:</span><span><span> [</span><span>MiniCssExtractPlugin</span><span>.</span></span><span>loader</span><span>, </span><span>'css-loader'</span><span>], </span><span>//换MiniCssExtractPlugin.loader</span></div></div><div><div><div>28</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>29</div></div><div><span>      </span><span>// webpack5新特性</span></div></div><div><div><div>30</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>31</div></div><div><span>        </span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>(png</span><span>|</span><span>jpg</span><span>|</span><span>jpeg</span><span>|</span><span>gif)</span></span><span>$</span><span>/</span><span>i</span><span>,</span></div></div><div><div><div>32</div></div><div><span>        </span><span>type</span><span>:</span><span> </span><span>'asset/resource'</span><span>,</span></div></div><div><div><div>33</div></div><div><span>        </span><span>generator</span><span>:</span><span> {</span></div></div><div><div><div>34</div></div><div><span>          </span><span>filename</span><span>:</span><span> </span><span>'img/[name].[contenthash][ext]'</span><span>, </span><span>//img文件夹下创建图片</span></div></div><div><div><div>35</div></div><div><span><span>        </span></span><span>},</span></div></div><div><div><div>36</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>37</div></div><div><span><span>    </span></span><span>],</span></div></div><div><div><div>38</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>39</div></div><div><span>  </span><span>plugins</span><span>:</span><span> [</span></div></div><div><div><div>40</div></div><div><span>    </span><span>new</span><span> </span><span>HtmlWebpackPlugin</span><span>({</span></div></div><div><div><div>41</div></div><div><span>      </span><span>// template: 'index.html',不写模板，自动创建，demo样式可以这样</span></div></div><div><div><div>42</div></div><div><span>      </span><span>filename</span><span>:</span><span> </span><span>'index.html'</span><span>, </span><span>//重命名</span></div></div><div><div><div>43</div></div><div><span>      </span><span>chunks</span><span>:</span><span> [</span><span>'index'</span><span>], </span><span>//指定引入</span></div></div><div><div><div>44</div></div><div><span>      </span><span>minify</span><span>:</span><span> {</span></div></div><div><div><div>45</div></div><div><span>        </span><span>collapseWhitespace</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>46</div></div><div><span>        </span><span>keepClosingSlash</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>47</div></div><div><span>        </span><span>removeComments</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>48</div></div><div><span>        </span><span>removeRedundantAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>49</div></div><div><span>        </span><span>removeScriptTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>50</div></div><div><span>        </span><span>removeStyleLinkTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>51</div></div><div><span>        </span><span>useShortDoctype</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>52</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>53</div></div><div><span><span>    </span></span><span>}),</span></div></div><div><div><div>54</div></div><div><span>    </span><span>new</span><span> </span><span>HtmlWebpackPlugin</span><span>({</span></div></div><div><div><div>55</div></div><div><span>      </span><span>// template: 'search.html',</span></div></div><div><div><div>56</div></div><div><span>      </span><span>filename</span><span>:</span><span> </span><span>'search.html'</span><span>, </span><span>//重命名</span></div></div><div><div><div>57</div></div><div><span>      </span><span>chunks</span><span>:</span><span> [</span><span>'search'</span><span>], </span><span>//指定引入</span></div></div><div><div><div>58</div></div><div><span>      </span><span>minify</span><span>:</span><span> {</span></div></div><div><div><div>59</div></div><div><span>        </span><span>collapseWhitespace</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>60</div></div><div><span>        </span><span>keepClosingSlash</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>61</div></div><div><span>        </span><span>removeComments</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>62</div></div><div><span>        </span><span>removeRedundantAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>63</div></div><div><span>        </span><span>removeScriptTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>64</div></div><div><span>        </span><span>removeStyleLinkTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>65</div></div><div><span>        </span><span>useShortDoctype</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>66</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>67</div></div><div><span><span>    </span></span><span>}),</span></div></div><div><div><div>68</div></div><div><span>    </span><span>new</span><span> </span><span>MiniCssExtractPlugin</span><span>({</span></div></div><div><div><div>69</div></div><div><span>      </span><span>filename</span><span>:</span><span> </span><span>'css/[name].css'</span><span>,</span></div></div><div><div><div>70</div></div><div><span><span>    </span></span><span>}),</span></div></div><div><div><div>71</div></div><div><span><span>  </span></span><span>],</span></div></div><div><div><div>72</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
</li>
</ul></section>
<section><h2>使用html-withimg-loader处理HTML中的图片<a href="#使用html-withimg-loader处理html中的图片"><span>#</span></a></h2><p>处理html的图片</p><p>安装</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>npm install -D html-withimg-loader</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>使用</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>path</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'path'</span><span>);</span></div></div><div><div><div>2</div></div><div><span>const</span><span> { </span><span>CleanWebpackPlugin</span><span> } </span><span>=</span><span> </span><span>require</span><span>(</span><span>'clean-webpack-plugin'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>HtmlWebpackPlugin</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'html-webpack-plugin'</span><span>);</span></div></div><div><div><div>4</div></div><div><span>const</span><span> </span><span>MiniCssExtractPlugin</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'mini-css-extract-plugin'</span><span>);</span></div></div><div><div><div>5</div></div><div><span>module</span><span>.</span><span>exports</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>6</div></div><div><span>  </span><span>mode</span><span>:</span><span> </span><span>'production'</span><span>,</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>  </span><span>entry</span><span>:</span><span> {</span></div></div><div><div><div>9</div></div><div><span>    </span><span>index</span><span>:</span><span> </span><span>'./src/index.js'</span><span>,</span></div></div><div><div><div>10</div></div><div><span>    </span><span>search</span><span>:</span><span> </span><span>'./src/search.js'</span><span>,</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>  </span><span>output</span><span>:</span><span> {</span></div></div><div><div><div>14</div></div><div><span>    </span><span>filename</span><span>:</span><span> </span><span>'[name].js'</span><span>,</span></div></div><div><div><div>15</div></div><div><span>    </span><span>path</span><span>:</span><span><span> </span><span>path</span><span>.</span></span><span>resolve</span><span><span>(</span><span>__dirname</span><span>, </span></span><span>'dist'</span><span>),</span></div></div><div><div><div>16</div></div><div><span>    </span><span>clean</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>18</div></div><div><span>  </span><span>module</span><span>:</span><span> {</span></div></div><div><div><div>19</div></div><div><span>    </span><span>rules</span><span>:</span><span> [</span></div></div><div><div><div>20</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>21</div></div><div><span>        </span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>(js</span><span>|</span><span>jsx)</span></span><span>$</span><span>/</span><span>,</span></div></div><div><div><div>22</div></div><div><span>        </span><span>use</span><span>:</span><span> [</span><span>'babel-loader'</span><span>],</span></div></div><div><div><div>23</div></div><div><span>        </span><span>exclude</span><span>:</span><span><span> [</span><span>path</span><span>.</span></span><span>join</span><span><span>(</span><span>__dirname</span><span>, </span></span><span>'./node_modules'</span><span>)], </span><span>//排除node_modules</span></div></div><div><div><div>24</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>25</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>26</div></div><div><span>        </span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>css</span></span><span>$</span><span>/</span><span>,</span></div></div><div><div><div>27</div></div><div><span>        </span><span>use</span><span>:</span><span><span> [</span><span>MiniCssExtractPlugin</span><span>.</span></span><span>loader</span><span>, </span><span>'css-loader'</span><span>], </span><span>//换MiniCssExtractPlugin.loader</span></div></div><div><div><div>28</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>29</div></div><div><span>      </span><span>// webpack5新特性</span></div></div><div><div><div>30</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>31</div></div><div><span>        </span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>(png</span><span>|</span><span>jpg</span><span>|</span><span>jpeg</span><span>|</span><span>gif)</span></span><span>$</span><span>/</span><span>i</span><span>,</span></div></div><div><div><div>32</div></div><div><span>        </span><span>type</span><span>:</span><span> </span><span>'asset/resource'</span><span>,</span></div></div><div><div><div>33</div></div><div><span>        </span><span>generator</span><span>:</span><span> {</span></div></div><div><div><div>34</div></div><div><span>          </span><span>filename</span><span>:</span><span> </span><span>'img/[name].[contenthash][ext]'</span><span>, </span><span>//img文件夹下创建图片</span></div></div><div><div><div>35</div></div><div><span><span>        </span></span><span>},</span></div></div><div><div><div>36</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>37</div></div><div><span>      </span><span>// 处理html的图片，没有这个loader会报错</span></div></div><div><div><div>38</div></div><div><span><span>      </span></span><span>{</span></div></div><div><div><div>39</div></div><div><span>        </span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>html</span></span><span>$</span><span>/</span><span>,</span></div></div><div><div><div>40</div></div><div><span>        </span><span>use</span><span>:</span><span> [</span><span>'html-withimg-loader'</span><span>],</span></div></div><div><div><div>41</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>42</div></div><div><span>      </span><span>//webpack5 推荐使用html-loader</span></div></div><div><div><div>43</div></div><div><span>      </span><span>// {</span></div></div><div><div><div>44</div></div><div><span>      </span><span>//   test: /\.html$/,</span></div></div><div><div><div>45</div></div><div><span>      </span><span>//   loader: 'html-loader',</span></div></div><div><div><div>46</div></div><div><span>      </span><span>// },</span></div></div><div><div><div>47</div></div><div><span><span>    </span></span><span>],</span></div></div><div><div><div>48</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>49</div></div><div><span>  </span><span>plugins</span><span>:</span><span> [</span></div></div><div><div><div>50</div></div><div><span>    </span><span>new</span><span> </span><span>HtmlWebpackPlugin</span><span>({</span></div></div><div><div><div>51</div></div><div><span>      </span><span>template</span><span>:</span><span> </span><span>'./src/index.html'</span><span>, </span><span>//不写模板，自动创建，demo样式可以这样</span></div></div><div><div><div>52</div></div><div><span>      </span><span>filename</span><span>:</span><span> </span><span>'index.html'</span><span>, </span><span>//重命名</span></div></div><div><div><div>53</div></div><div><span>      </span><span>chunks</span><span>:</span><span> [</span><span>'index'</span><span>], </span><span>//指定引入</span></div></div><div><div><div>54</div></div><div><span>      </span><span>minify</span><span>:</span><span> {</span></div></div><div><div><div>55</div></div><div><span>        </span><span>collapseWhitespace</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>56</div></div><div><span>        </span><span>keepClosingSlash</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>57</div></div><div><span>        </span><span>removeComments</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>58</div></div><div><span>        </span><span>removeRedundantAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>59</div></div><div><span>        </span><span>removeScriptTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>60</div></div><div><span>        </span><span>removeStyleLinkTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>61</div></div><div><span>        </span><span>useShortDoctype</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>62</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>63</div></div><div><span><span>    </span></span><span>}),</span></div></div><div><div><div>64</div></div><div><span>    </span><span>new</span><span> </span><span>HtmlWebpackPlugin</span><span>({</span></div></div><div><div><div>65</div></div><div><span>      </span><span>// template: 'search.html',</span></div></div><div><div><div>66</div></div><div><span>      </span><span>filename</span><span>:</span><span> </span><span>'search.html'</span><span>, </span><span>//重命名</span></div></div><div><div><div>67</div></div><div><span>      </span><span>chunks</span><span>:</span><span> [</span><span>'search'</span><span>], </span><span>//指定引入</span></div></div><div><div><div>68</div></div><div><span>      </span><span>minify</span><span>:</span><span> {</span></div></div><div><div><div>69</div></div><div><span>        </span><span>collapseWhitespace</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>70</div></div><div><span>        </span><span>keepClosingSlash</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>71</div></div><div><span>        </span><span>removeComments</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>72</div></div><div><span>        </span><span>removeRedundantAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>73</div></div><div><span>        </span><span>removeScriptTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>74</div></div><div><span>        </span><span>removeStyleLinkTypeAttributes</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>75</div></div><div><span>        </span><span>useShortDoctype</span><span>:</span><span> </span><span>true</span><span>,</span></div></div><div><div><div>76</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>77</div></div><div><span><span>    </span></span><span>}),</span></div></div><div><div><div>78</div></div><div><span>    </span><span>new</span><span> </span><span>MiniCssExtractPlugin</span><span>({</span></div></div><div><div><div>79</div></div><div><span>      </span><span>filename</span><span>:</span><span> </span><span>'css/[name].css'</span><span>,</span></div></div><div><div><div>80</div></div><div><span><span>    </span></span><span>}),</span></div></div><div><div><div>81</div></div><div><span><span>  </span></span><span>],</span></div></div><div><div><div>82</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>webpack5推荐html-loader</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>npm install -D html-loader</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>     </span><span>//webpack5 推荐使用html-loader</span></div></div><div><div><div>2</div></div><div><span>{</span></div></div><div><div><div>3</div></div><div><span><span>      </span></span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>html</span></span><span>$</span><span>/</span><span>,</span></div></div><div><div><div>4</div></div><div><span><span>     </span></span><span>loader</span><span>: </span><span>'html-loader'</span><span>,</span></div></div><div><div><div>5</div></div><div><span><span> </span></span><span>},</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>使用file-loader处理JS中的图片<a href="#使用file-loader处理js中的图片"><span>#</span></a></h2><p>JS 中的图片不是“被处理”，而是“被 import 之后交给 loader 处理”</p><p>webpack5也不推荐使用，也无需使用，因为asset/resource已经处理了，使用file-loader也会出问题，不要用</p><p>安装：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>npm install -D file-loader</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>使用</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>{</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>(png</span><span>|</span><span>jpg</span><span>|</span><span>jpeg</span><span>|</span><span>gif)</span></span><span>$</span><span>/</span><span>i</span><span>,</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>use</span><span>: [</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>{</span></div></div><div><div><div>5</div></div><div><span>      </span><span>loader</span><span>:</span><span> </span><span>'file-loader'</span><span>,</span></div></div><div><div><div>6</div></div><div><span>      </span><span>options</span><span>:</span><span> {</span></div></div><div><div><div>7</div></div><div><span>        </span><span>name</span><span>:</span><span> </span><span>'[name].[hash].[ext]'</span><span>,</span></div></div><div><div><div>8</div></div><div><span>        </span><span>outputPath</span><span>:</span><span> </span><span>'images'</span><span>,</span></div></div><div><div><div>9</div></div><div><span><span>      </span></span><span>},</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>},</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>],</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>使用url-loader处理图片<a href="#使用url-loader处理图片"><span>#</span></a></h2><p><code>url-loader</code> 是 Webpack 4 时代非常经典的图片 loader，但现在已经<strong>基本被 Webpack5 的 Asset Modules 取代了</strong>。</p><p>webpack5替代方案</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>{</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>test</span><span>:</span><span><span> /</span><span>\.</span><span>(png</span><span>|</span><span>jpg</span><span>|</span><span>jpeg</span><span>|</span><span>gif)</span></span><span>$</span><span>/</span><span>i</span><span>,</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>type</span><span>: </span><span>'asset'</span><span>,</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>parser</span><span>: {</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>dataUrlCondition</span><span>: {</span></div></div><div><div><div>6</div></div><div><span><span>      </span></span><span>maxSize</span><span>: </span><span>10</span><span> </span><span>*</span><span> </span><span>1024</span><span> </span><span>// 10kb以下转base64</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>使用webpack-dev-server搭建开发环境<a href="#使用webpack-dev-server搭建开发环境"><span>#</span></a></h2><ul>
<li>
<p>让 webpack 在内存里打包 + 自动刷新浏览器 + 支持热更新</p>
</li>
<li>
<p>如果不用它，现在是这样开发：</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>写代码 → npx webpack → 打包到 dist → 手动刷新浏览器</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>用了 dev-server：</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>写代码 → 自动编译 → 浏览器自动更新（不用刷新）</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>安装</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>npm install -D webpack-dev-server</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>使用</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>devServer</span><span>: {</span></span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>static</span><span>: {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>directory</span><span>: </span><span>path</span><span>.</span><span>join</span><span><span>(</span><span>__dirname</span><span>, </span></span><span>'dist'</span><span>),</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>port</span><span>: </span><span>8080</span><span>,</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>open</span><span>: </span><span>true</span><span>,</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>hot</span><span>: </span><span>true</span><span>,</span></div></div><div><div><div>8</div></div><div><span>},</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102201es6-mo-kuai-module/</id>
      <title type="text">ES6模块Module</title>
      <published>2026-10-21T23:30:35.000Z</published>
      <updated>2026-10-21T23:30:35.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102201es6-mo-kuai-module/"/>
      <summary type="text">本文主要学习ES6模块Module</summary>
      <content type="html"><![CDATA[<section><h1>Module 是什么<a href="#module-是什么"><span>#</span></a></h1><p>模块就是把代码拆分成多个文件，每个文件负责一部分功能，然后通过导入和导出实现复用。</p><p>一个一个的局部作用域的代码块</p><p><strong>什么是模块系统</strong></p><p>模块系统需要解决的主要问题：</p><p>模块化的问题</p><p>消除全局变量</p><p>管理加载顺序</p></section>
<section><h1>Module 的基本用法<a href="#module-的基本用法"><span>#</span></a></h1><p><strong>导出</strong>：分别导出</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>const</span><span> </span><span>name</span><span> </span><span>=</span><span> </span><span>'张三'</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>export</span><span> </span><span>function</span><span> </span><span>sayHello</span><span>() {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'hello'</span><span>);</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>导入</strong>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> { </span><span>name</span><span>, </span><span>sayHello</span><span> } </span><span>from</span><span> </span><span>'./user.js'</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>name</span><span>);</span></span></div></div><div><div><div>4</div></div><div><span>sayHello</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>默认导出</strong></p><div><figure><figcaption><span>math.js</span></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>default</span><span> </span><span>function</span><span> </span><span>add</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span> </span><span>a</span><span> </span><span>+</span><span> </span><span>b</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>导入时可以随便起名字</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>sum</span><span> </span><span>from</span><span> </span><span>'./math.js'</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>sum</span><span>(</span><span>1</span><span>, </span><span>2</span><span>));</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>区别：</strong></p>

<table><thead><tr><th>类型</th><th>导出</th><th>导入</th></tr></thead><tbody><tr><td>named export</td><td><code>{ add }</code></td><td><code>{ add }</code></td></tr><tr><td>default export</td><td><code>export default</code></td><td>随便命名</td></tr></tbody></table><p><strong>混合导出</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>const</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>export</span><span> </span><span>default</span><span> </span><span>function</span><span> </span><span>test</span><span>() {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'default'</span><span>);</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>导入：</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>test</span><span>, { </span><span>a</span><span> } </span><span>from</span><span> </span><span>'./file.js'</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>导出方式总结</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//直接导出</span></div></div><div><div><div>2</div></div><div><span>export</span><span> </span><span>const</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>3</div></div><div><span>//先写再导出</span></div></div><div><div><div>4</div></div><div><span>const</span><span> </span><span>b</span><span> </span><span>=</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>5</div></div><div><span>export</span><span> { </span><span>b</span><span> };</span></div></div><div><div><div>6</div></div><div><span>//重命名导出</span></div></div><div><div><div>7</div></div><div><span>const</span><span> </span><span>c</span><span> </span><span>=</span><span> </span><span>3</span><span>;</span></div></div><div><div><div>8</div></div><div><span>export</span><span><span> { </span><span>c</span><span> </span><span>as</span><span> </span></span><span>count</span><span> };</span></div></div><div><div><div>9</div></div><div><span>import</span><span> { </span><span>count</span><span> } </span><span>from</span><span> </span><span>'./file.js'</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>全部导入</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>*</span><span><span> </span><span>as</span><span> </span></span><span>utils</span><span> </span><span>from</span><span> </span><span>'./utils.js'</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>utils</span><span>.</span></span><span>a</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>utils</span><span>.</span></span><span>fn</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>export default 和对应的 import<a href="#export-default-和对应的-import"><span>#</span></a></h1><p>一个模块可以有多个普通导出（named export），但只能有一个默认导出（default export）。</p><p>默认导出：</p><div><figure><figcaption><span>math.js</span></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>default</span><span> </span><span>function</span><span> </span><span>add</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span> </span><span>a</span><span> </span><span>+</span><span> </span><span>b</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>//导入</span></div></div><div><div><div>5</div></div><div><span>// app.js</span></div></div><div><div><div>6</div></div><div><span>import</span><span> </span><span>add</span><span> </span><span>from</span><span> </span><span>'./math.js'</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>add</span><span>(</span><span>1</span><span>, </span><span>2</span><span>));</span><span>//3</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>为什么导入时没有 <code>{}</code>？ 因为导出的是这个模块的默认值，导入时直接拿，名字可以随便起</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//import 任意名字 from '模块';</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>add</span><span> </span><span>from</span><span> </span><span>'./math.js'</span><span>;</span></div></div><div><div><div>3</div></div><div><span>import</span><span> </span><span>fn</span><span> </span><span>from</span><span> </span><span>'./math.js'</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>默认导出对象：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>default</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>add</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>sub</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>mul</span></div></div><div><div><div>5</div></div><div><span>};</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>import</span><span> </span><span>math</span><span> </span><span>from</span><span> </span><span>'./math.js'</span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>math</span><span>.</span></span><span>add</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>默认导出类：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>default</span><span> </span><span>class</span><span> </span><span>User</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>login</span><span>() {}</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>import</span><span> </span><span>User</span><span> </span><span>from</span><span> </span><span>'./User.js'</span><span>;</span></div></div><div><div><div>6</div></div><div><span>const</span><span> </span><span>u</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>User</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>默认导出匿名函数：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>default</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'hello'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>import</span><span> </span><span>fn</span><span> </span><span>from</span><span> </span><span>'./a.js'</span><span>;</span></div></div><div><div><div>5</div></div><div><span>fn</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>默认导出匿名类</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>default</span><span> </span><span>class</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>login</span><span>() {}</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>import</span><span> </span><span>User</span><span> </span><span>from</span><span> </span><span>'./User.js'</span><span>;</span></div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>u</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>User</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>export 和对应的 import<a href="#export-和对应的-import"><span>#</span></a></h1><p>一个模块可以有多个普通导出，普通 <code>export</code> 是“按名字导出”，导入时必须按名字取。</p><p><strong>普通导出：</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//导出</span></div></div><div><div><div>2</div></div><div><span>export</span><span> </span><span>function</span><span> </span><span>add</span><span>() {}</span></div></div><div><div><div>3</div></div><div><span>export</span><span> </span><span>function</span><span> </span><span>sub</span><span>() {}</span></div></div><div><div><div>4</div></div><div><span>//导入 名字必须对应。</span></div></div><div><div><div>5</div></div><div><span>import</span><span> { </span><span>add</span><span>, </span><span>sub</span><span> } </span><span>from</span><span> </span><span>'./math.js'</span><span>;</span></div></div><div><div><div>6</div></div><div><span>import</span><span> { </span><span>fn</span><span> } </span><span>from</span><span> </span><span>'./math.js'</span><span>;</span><span>//错误</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>function</span><span> </span><span>add</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>9</div></div><div><span>  </span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div><span>function</span><span> </span><span>sub</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>12</div></div><div><span>  </span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>-</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>13</div></div><div><span>}</span></div></div><div><div><div>14</div></div><div><span>function</span><span> </span><span>mul</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>15</div></div><div><span>  </span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>*</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>16</div></div><div><span>}</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>export</span><span> {</span></div></div><div><div><div>19</div></div><div><span>  </span><span>add</span><span>,</span></div></div><div><div><div>20</div></div><div><span>  </span><span>sub</span><span>,</span></div></div><div><div><div>21</div></div><div><span>  </span><span>mul</span></div></div><div><div><div>22</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>为什么要加 <code>{}</code>？因为导出了多个名字，导入时必须明确</p><p>导出后再统一 export</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>b</span><span> </span><span>=</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>3</div></div><div><span>export</span><span> { </span><span>a</span><span>, </span><span>b</span><span> };</span></div></div><div><div><div>4</div></div><div><span>//等价于</span></div></div><div><div><div>5</div></div><div><span>export</span><span> </span><span>const</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>6</div></div><div><span>export</span><span> </span><span>const</span><span> </span><span>b</span><span> </span><span>=</span><span> </span><span>2</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>导出时起别名</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const a = 1;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>export {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>a as count</span></div></div><div><div><div>5</div></div><div><span>};</span></div></div><div><div><div>6</div></div><div><span>//导入肯定就需要别名</span></div></div><div><div><div>7</div></div><div><span>import { count } from './a.js';</span></div></div><div><div><div>8</div></div><div><span>console.log(count);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li>
<p>导入时起别名</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import { count as c } from './a.js';</span></div></div><div><div><div>2</div></div><div><span>console.log(c);</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p><strong>一次导入导出多个</strong></p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>export const a = 1;</span></div></div><div><div><div>2</div></div><div><span>export const b = 2;</span></div></div><div><div><div>3</div></div><div><span>export const c = 3;</span></div></div><div><div><div>4</div></div><div><span>//导入</span></div></div><div><div><div>5</div></div><div><span>import { a, b, c } from './a.js';</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>全部导入：</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import * as utils from './a.js';</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>导入导出复合写法</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//复合写法无法在当前模板中使用</span></div></div><div><div><div>2</div></div><div><span>export { age } from './module.js';//类似中转站</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h1>Module 的注意事项<a href="#module-的注意事项"><span>#</span></a></h1><p><code>import</code> 必须写在顶层</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//错误</span></div></div><div><div><div>2</div></div><div><span>if</span><span> (</span><span>true</span><span>) {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>import</span><span> { </span><span>a</span><span> } </span><span>from</span><span> </span><span>'./a.js'</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div><span>function</span><span> </span><span>fn</span><span>() {</span></div></div><div><div><div>6</div></div><div><span>  </span><span>import</span><span> { </span><span>a</span><span> } </span><span>from</span><span> </span><span>'./a.js'</span><span>;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div><span>//正确</span></div></div><div><div><div>9</div></div><div><span>import</span><span> { </span><span>a</span><span> } </span><span>from</span><span> </span><span>'./a.js'</span><span>;</span></div></div><div><div><div>10</div></div><div><span>//如果需要条件加载：</span></div></div><div><div><div>11</div></div><div><span>if</span><span> (</span><span>true</span><span>) {</span></div></div><div><div><div>12</div></div><div><span>  </span><span>const</span><span> </span><span>module</span><span> </span><span>=</span><span> </span><span>await</span><span> </span><span>import</span><span>(</span><span>'./a.js'</span><span>);</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>import</code> 导入的是只读绑定：</p><div><figure><figcaption><span>a.js</span></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>let</span><span><span> </span><span>count</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>2</div></div><div><span>//b.js</span></div></div><div><div><div>3</div></div><div><span>import</span><span> { </span><span>count</span><span> } </span><span>from</span><span> </span><span>'./a.js'</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>count</span><span> </span></span><span>=</span><span> </span><span>2</span><span>; </span><span>// ❌import 得到的是只读引用。不能修改</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>导出的变量是动态绑定：</p><div><figure><figcaption><span>a.js</span></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>let</span><span><span> </span><span>count</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>count</span><span> </span><span>=</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}, </span><span>1000</span><span>);</span></div></div><div><div><div>6</div></div><div><span>//b.js</span></div></div><div><div><div>7</div></div><div><span>import</span><span> { </span><span>count</span><span> } </span><span>from</span><span> </span><span>'./a.js'</span><span>;</span></div></div><div><div><div>8</div></div><div><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>count</span><span>);</span></span><span>//2</span></div></div><div><div><div>10</div></div><div><span>}, </span><span>2000</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>一个模块只能有一个 <code>default</code></p><p>默认导出导入时名字随便起</p><p>普通导出必须按名字导入</p><p>导入的名字不能重复声明</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> { </span><span>a</span><span> } </span><span>from</span><span> </span><span>'./a.js'</span><span>;</span></div></div><div><div><div>2</div></div><div><span>let</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>2</span><span>;</span><span>//error Identifier 'a' has already been declared</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>//解决，起一个别名</span></div></div><div><div><div>5</div></div><div><span>import</span><span><span> { </span><span>a</span><span> </span><span>as</span><span> </span></span><span>importedA</span><span> } </span><span>from</span><span> </span><span>'./a.js'</span><span>;</span></div></div><div><div><div>6</div></div><div><span>let</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>2</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>模块默认是严格模式</p><p>模块有自己的作用域，模块之间，变量默认不共享</p><div><figure><figcaption><span>a.js</span></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>2</div></div><div><span>//b.js</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>);</span></span><span>//a is not defined</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>模块只执行一次</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> </span><span>'./a.js'</span><span>;</span></div></div><div><div><div>2</div></div><div><span>import</span><span> </span><span>'./a.js'</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'执行'</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>浏览器必须加 <code>type="module"</code></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>script</span><span> </span><span>type</span><span>=</span><span>"module"</span><span> </span><span>src</span><span>=</span><span>"./app.js"</span><span>&gt;&lt;/</span><span>script</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>Node ESM 必须开启，或者，文件拓展名字.mjs，注意node12之前存在兼容问题</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>{</span></div></div><div><div><div>2</div></div><div><span>  </span><span>"type"</span><span>: </span><span>"module"</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>Node ESM 必须写扩展名</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> { </span><span>add</span><span> } </span><span>from</span><span> </span><span>'./math'</span><span>;</span><span>//错误</span></div></div><div><div><div>2</div></div><div><span>import</span><span> { </span><span>add</span><span> } </span><span>from</span><span> </span><span>'./math.js'</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>import</code> 有提升：<code>import</code> 的“提升”指的是模块初始化阶段提前建立绑定，不是代码文本位置上的变量提升。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>);</span></span></div></div><div><div><div>2</div></div><div><span>import</span><span> { </span><span>a</span><span> } </span><span>from</span><span> </span><span>'./a.js'</span><span>;</span></div></div><div><div><div>3</div></div><div><span>//看起来：先使用后导入；实际上：import 在模块初始化阶段就完成了。</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>循环引用要小心：如a导入b文件，b文件导入a文件</p><div><figure><figcaption><span>a.js</span></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> { </span><span>b</span><span> } </span><span>from</span><span> </span><span>'./b.js'</span><span>;</span></div></div><div><div><div>2</div></div><div><span>export</span><span> </span><span>const</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>3</div></div><div><span>//b.js</span></div></div><div><div><div>4</div></div><div><span>import</span><span> { </span><span>a</span><span> } </span><span>from</span><span> </span><span>'./a.js'</span><span>;</span></div></div><div><div><div>5</div></div><div><span>export</span><span> </span><span>const</span><span> </span><span>b</span><span> </span><span>=</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>6</div></div><div><span>//Cannot access before initialization</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>Module的应用<a href="#module的应用"><span>#</span></a></h1><p>最常见的应用场景</p>

<table><thead><tr><th>场景</th><th>使用方式</th></tr></thead><tbody><tr><td>工具函数</td><td>export</td></tr><tr><td>常量</td><td>export</td></tr><tr><td>API</td><td>export</td></tr><tr><td>配置</td><td>export default</td></tr><tr><td>类</td><td>export default</td></tr><tr><td>组件</td><td>export default</td></tr><tr><td>数据库</td><td>export</td></tr><tr><td>路由</td><td>export</td></tr></tbody></table><p>API 请求模块：</p><div><figure><figcaption><span>api/request.js</span></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>function</span><span> </span><span>request</span><span><span>(</span><span>url</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span> </span><span>fetch</span><span><span>(</span><span>url</span><span>).</span></span><span>then</span><span><span>(</span><span>res</span><span> </span></span><span>=&gt;</span><span><span> </span><span>res</span><span>.</span></span><span>json</span><span>());</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>//api/user.js</span></div></div><div><div><div>5</div></div><div><span>import</span><span> { </span><span>request</span><span> } </span><span>from</span><span> </span><span>'./request.js'</span><span>;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>export</span><span> </span><span>function</span><span> </span><span>getUser</span><span>() {</span></div></div><div><div><div>8</div></div><div><span>  </span><span>return</span><span> </span><span>request</span><span>(</span><span>'/user'</span><span>);</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>配置文件模块：</p><div><figure><figcaption><span>config.js</span></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>default</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>baseURL</span><span>:</span><span> </span><span>'http://localhost:3000'</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>timeout</span><span>:</span><span> </span><span>5000</span></div></div><div><div><div>4</div></div><div><span>};</span></div></div><div><div><div>5</div></div><div><span>//app.js</span></div></div><div><div><div>6</div></div><div><span>import</span><span> </span><span>config</span><span> </span><span>from</span><span> </span><span>'./config.js'</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>config</span><span>.</span></span><span>baseURL</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>拓展-ES Module 和 CommonJS 的区别<a href="#拓展-es-module-和-commonjs-的区别"><span>#</span></a></h1><ul>
<li>ES Module（ESM）是 JavaScript 官方标准模块规范；CommonJS（CJS）是 Node.js 最早使用的模块规范。</li>
</ul><section><h2>语法区别<a href="#语法区别"><span>#</span></a></h2><p>CommonJS：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>module</span><span>.</span><span>exports</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>add</span><span>,</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>sub</span></div></div><div><div><div>4</div></div><div><span>};</span></div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>math</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'./math'</span><span>);</span></div></div><div><div><div>6</div></div><div><span>const</span><span> { </span><span>add</span><span> } </span><span>=</span><span> </span><span>require</span><span>(</span><span>'./math'</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>ES Module：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>function</span><span> </span><span>add</span><span>() {}</span></div></div><div><div><div>2</div></div><div><span>export</span><span> </span><span>function</span><span> </span><span>sub</span><span>() {}</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>import</span><span> { </span><span>add</span><span>, </span><span>sub</span><span> } </span><span>from</span><span> </span><span>'./math.js'</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>加载时机不同<a href="#加载时机不同"><span>#</span></a></h2><p>CommonJS：运行时加载</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>math</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'./math'</span><span>);</span><span>//代码运行到这里才去加载模块</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>//合法</span></div></div><div><div><div>4</div></div><div><span>if</span><span> (</span><span>true</span><span>) {</span></div></div><div><div><div>5</div></div><div><span>  </span><span>const</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'./a'</span><span>);</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>ES Module：编译时加载（静态加载）</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> { </span><span>add</span><span> } </span><span>from</span><span> </span><span>'./math.js'</span><span>;</span><span>//代码执行之前就已经确定依赖关系</span></div></div><div><div><div>2</div></div><div><span>//报错</span></div></div><div><div><div>3</div></div><div><span>if</span><span> (</span><span>true</span><span>) {</span></div></div><div><div><div>4</div></div><div><span>  </span><span>import</span><span> { </span><span>a</span><span> } </span><span>from</span><span> </span><span>'./a.js'</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>//动态导入</span></div></div><div><div><div>7</div></div><div><span>const</span><span> </span><span>module</span><span> </span><span>=</span><span> </span><span>await</span><span> </span><span>import</span><span>(</span><span>'./a.js'</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>值拷贝 VS 引用绑定<a href="#值拷贝-vs-引用绑定"><span>#</span></a></h2><p>CommonJS：值拷贝</p><div><figure><figcaption><span>a.js</span></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>count</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>2</div></div><div><span>module</span><span>.</span><span>exports</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>count</span></div></div><div><div><div>4</div></div><div><span>};</span></div></div><div><div><div>5</div></div><div><span><span>count</span><span> </span></span><span>=</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>6</div></div><div><span>//b.js</span></div></div><div><div><div>7</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> </span><span>require</span><span>(</span><span>'./a'</span><span>);</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj</span><span>.</span></span><span>count</span><span>);</span><span>//1 导出时已经复制了一份值。</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>ES Module：动态绑定</p><div><figure><figcaption><span>a.js</span></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>let</span><span><span> </span><span>count</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>count</span><span> </span><span>=</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}, </span><span>1000</span><span>);</span></div></div><div><div><div>6</div></div><div><span>//b.js</span></div></div><div><div><div>7</div></div><div><span>import</span><span> { </span><span>count</span><span> } </span><span>from</span><span> </span><span>'./a.js'</span><span>;</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>count</span><span>);</span></span><span>//2  import 得到的是引用绑定，不是值拷贝。</span></div></div><div><div><div>11</div></div><div><span>}, </span><span>2000</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>this 指向不同<a href="#this-指向不同"><span>#</span></a></h2><p>CommonJS</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>this</span><span>);</span><span>//module.exports</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>ES Module</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>this</span><span>);</span><span>//undefined  ES Module 默认严格模式。</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>总结:</p>

<table><thead><tr><th>区别</th><th>CommonJS</th><th>ES Module</th></tr></thead><tbody><tr><td>提出者</td><td>Node.js</td><td>ECMAScript 官方</td></tr><tr><td>导出</td><td>module.exports</td><td>export</td></tr><tr><td>导入</td><td>require</td><td>import</td></tr><tr><td>加载时机</td><td>运行时</td><td>编译时</td></tr><tr><td>值传递</td><td>值拷贝</td><td>动态绑定</td></tr><tr><td>this</td><td>module.exports</td><td>undefined</td></tr><tr><td>顶层 await</td><td>❌</td><td>✅</td></tr><tr><td>Tree Shaking</td><td>❌</td><td>✅</td></tr><tr><td>浏览器支持</td><td>❌</td><td>✅</td></tr><tr><td>静态分析</td><td>❌</td><td>✅</td></tr><tr><td>文件名</td><td>.js .cjs</td><td>.mjs</td></tr></tbody></table></section></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/20261021012es6-lei-class/</id>
      <title type="text">ES6类Class</title>
      <published>2026-10-21T12:57:51.000Z</published>
      <updated>2026-10-21T12:57:51.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/20261021012es6-lei-class/"/>
      <summary type="text">本文主要学习ES6类Class</summary>
      <content type="html"><![CDATA[<section><h2>Class 是什么<a href="#class-是什么"><span>#</span></a></h2><p>JavaScript 的 <code>Class</code>（类）本质上是：对“构造函数 + 原型链”的语法糖封装，更接近“面向对象语言”的写法（比如 Java / C++）来写 JS，但底层机制还是原型（prototype）。</p><p>基本用法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Person</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>name</span><span>, </span><span>age</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>    </span><span>this</span><span>.</span><span>age</span><span> </span><span>=</span><span><span> </span><span>age</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>  </span><span>sayHello</span><span>() {</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>`我叫</span><span>${</span><span>this</span><span>.</span><span>name</span><span>}</span><span>`</span><span>);</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div><span>//使用</span></div></div><div><div><div>12</div></div><div><span>const</span><span> </span><span>p1</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Person</span><span>(</span><span>'张三'</span><span>, </span><span>18</span><span>);</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span><span>p1</span><span>.</span></span><span>sayHello</span><span>();</span><span>//this指向p1</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>class与构造函数：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//旧写法</span></div></div><div><div><div>2</div></div><div><span>function</span><span> </span><span>Person</span><span><span>(</span><span>name</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>  </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>Person</span><span>.</span><span>prototype</span><span>.</span><span>say</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>name</span><span>);</span></div></div><div><div><div>8</div></div><div><span>};</span></div></div><div><div><div>9</div></div><div><span>//新写法</span></div></div><div><div><div>10</div></div><div><span>class</span><span> </span><span>Person</span><span> {</span></div></div><div><div><div>11</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>name</span><span>) {</span></span></div></div><div><div><div>12</div></div><div><span>    </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>  </span><span>say</span><span>() {</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>name</span><span>);</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>constructor 是什么</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//new 的时候自动执行</span></div></div><div><div><div>2</div></div><div><span>//用来初始化对象</span></div></div><div><div><div>3</div></div><div><span>//默认的构造函数，可不写，但是每个类都会有</span></div></div><div><div><div>4</div></div><div><span>class</span><span> </span><span>A</span><span> {</span></div></div><div><div><div>5</div></div><div><span>  </span><span>constructor</span><span>() {</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'我会在 new 的时候执行'</span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div><div><div><div>9</div></div><div><span>new</span><span> </span><span>A</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>不建议把方法放到constructor中</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Person</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>name</span><span>, </span><span>age</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>    </span><span>this</span><span>.</span><span>age</span><span> </span><span>=</span><span><span> </span><span>age</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>////一般构造方法定义属性，方法不在构造函数中定义</span></div></div><div><div><div>6</div></div><div><span>    </span><span>this</span><span>.</span><span>speak</span><span> </span><span>=</span><span> () </span><span>=&gt;</span><span> {};</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>8</div></div><div><span>  </span><span>sayHello</span><span>() {</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>`我叫</span><span>${</span><span>this</span><span>.</span><span>name</span><span>}</span><span>`</span><span>);</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div><span>const</span><span> </span><span>p1</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Person</span><span>();</span></div></div><div><div><div>13</div></div><div><span>const</span><span> </span><span>p2</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Person</span><span>();</span></div></div><div><div><div>14</div></div><div><span>//不建议把方法放在constructor，因为每new一个对象实例就会占用内存</span></div></div><div><div><div>15</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>p1</span><span>.</span></span><span>speak</span><span> </span><span>===</span><span><span> </span><span>p2</span><span>.</span></span><span>speak</span><span>); </span><span>//false</span></div></div><div><div><div>16</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>p1</span><span>.</span></span><span>sayHello</span><span> </span><span>===</span><span><span> </span><span>p2</span><span>.</span></span><span>sayHello</span><span>); </span><span>//true</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>Class 的两种定义形式<a href="#class-的两种定义形式"><span>#</span></a></h2><p>类声明和类表达式区别</p>

<table><thead><tr><th>特性</th><th>类声明</th><th>类表达式</th></tr></thead><tbody><tr><td>语法</td><td><code>class Person {}</code></td><td><code>const Person = class {}</code></td></tr><tr><td>是否有名字</td><td>必须有</td><td>可匿名、可命名</td></tr><tr><td>变量提升</td><td>❌ 无</td><td>❌ 无</td></tr><tr><td>是否可以赋值给变量</td><td>默认就是标识符</td><td>通常赋值给变量</td></tr><tr><td>使用场景</td><td>普通定义类</td><td>动态创建类、工厂模式</td></tr></tbody></table><p><strong>类声明</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Person</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>name</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>  </span><span>sayHello</span><span>() {</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>`Hello, </span><span>${</span><span>this</span><span>.</span><span>name</span><span>}</span><span>`</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>const</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Person</span><span>(</span><span>'张三'</span><span>);</span></div></div><div><div><div>12</div></div><div><span><span>p</span><span>.</span></span><span>sayHello</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>类表达式</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>Person</span><span> </span><span>=</span><span> </span><span>class</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>name</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>};</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>const</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Person</span><span>(</span><span>'张三'</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>两个注意点：</p><p>不存在声明提升</p><p>一样可以跟函数一样立即执行，但是需要new</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//不存在声明提升</span></div></div><div><div><div>2</div></div><div><span>//ReferenceError: Cannot access 'Person' before initialization</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Person</span><span>(</span><span>'张三'</span><span>);</span></div></div><div><div><div>4</div></div><div><span>const</span><span> </span><span>Person</span><span> </span><span>=</span><span> </span><span>class</span><span> {</span></div></div><div><div><div>5</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>name</span><span>) {</span></span></div></div><div><div><div>6</div></div><div><span>    </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>8</div></div><div><span>};</span></div></div><div><div><div>9</div></div><div><span>//一样可以跟函数一样立即执行，但是需要new</span></div></div><div><div><div>10</div></div><div><span>new</span><span> (</span><span>class</span><span> {</span></div></div><div><div><div>11</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>name</span><span>) {</span></span></div></div><div><div><div>12</div></div><div><span>    </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span>}(</span><span>'张三'</span><span>))</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>实例属性、静态方法和静态属性<a href="#实例属性静态方法和静态属性"><span>#</span></a></h2><p>实例的东西属于对象，静态的东西属于类</p><p>实例属性：实例属性是每个对象自己拥有的属性。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Person</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>name</span><span> </span><span>=</span><span> </span><span>'alex'</span><span>; </span><span>//实例属性，默认值</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>age</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>//实例属性，默认值</span></div></div><div><div><div>4</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>name</span><span>, </span><span>age</span><span>) {</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>6</div></div><div><span>    </span><span>this</span><span>.</span><span>age</span><span> </span><span>=</span><span><span> </span><span>age</span><span>;</span></span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>const</span><span> </span><span>p1</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Person</span><span>(</span><span>'张三'</span><span>, </span><span>18</span><span>);</span></div></div><div><div><div>11</div></div><div><span>const</span><span> </span><span>p2</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Person</span><span>(</span><span>'李四'</span><span>, </span><span>20</span><span>);</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>p1</span><span>.</span></span><span>name</span><span>);</span></div></div><div><div><div>14</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>p2</span><span>.</span></span><span>name</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>实例方法：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//注意，实例方法只能实例调用，不能类调用，如Person.sayHello()就错误了</span></div></div><div><div><div>2</div></div><div><span>class</span><span> </span><span>Person</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>name</span><span> </span><span>=</span><span> </span><span>'alex'</span><span>; </span><span>//实例属性，默认值</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>age</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>//实例属性，默认值</span></div></div><div><div><div>5</div></div><div><span>  </span><span>sayHello</span><span>() {</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>`helle </span><span>${</span><span>this</span><span>.</span><span>name</span><span>}</span><span>`</span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>} </span><span>//实例方法</span></div></div><div><div><div>8</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>name</span><span>, </span><span>age</span><span>) {</span></span></div></div><div><div><div>9</div></div><div><span>    </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>10</div></div><div><span>    </span><span>this</span><span>.</span><span>age</span><span> </span><span>=</span><span><span> </span><span>age</span><span>;</span></span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>const</span><span> </span><span>p1</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Person</span><span>(</span><span>'张三'</span><span>, </span><span>18</span><span>);</span></div></div><div><div><div>15</div></div><div><span>const</span><span> </span><span>p2</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Person</span><span>(</span><span>'李四'</span><span>, </span><span>20</span><span>);</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>p1</span><span>.</span></span><span>name</span><span>);</span></div></div><div><div><div>18</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>p2</span><span>.</span></span><span>name</span><span>);</span></div></div><div><div><div>19</div></div><div><span><span>p1</span><span>.</span></span><span>sayHello</span><span>();</span></div></div><div><div><div>20</div></div><div><span><span>p2</span><span>.</span></span><span>sayHello</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>静态方法：使用 <code>static</code> 定义</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//静态方法不能实例调用</span></div></div><div><div><div>2</div></div><div><span>class</span><span> </span><span>Person</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>name</span><span> </span><span>=</span><span> </span><span>'alex'</span><span>; </span><span>//实例属性，默认值</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>age</span><span> </span><span>=</span><span> </span><span>0</span><span>; </span><span>//实例属性，默认值</span></div></div><div><div><div>5</div></div><div><span>  </span><span>static</span><span> </span><span>sayHello</span><span>() {</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>`helle </span><span>${</span><span>this</span><span>.</span><span>name</span><span>}</span><span>`</span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>} </span><span>//实例方法</span></div></div><div><div><div>8</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>name</span><span>, </span><span>age</span><span>) {</span></span></div></div><div><div><div>9</div></div><div><span>    </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>10</div></div><div><span>    </span><span>this</span><span>.</span><span>age</span><span> </span><span>=</span><span><span> </span><span>age</span><span>;</span></span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>const</span><span> </span><span>p1</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Person</span><span>(</span><span>'张三'</span><span>, </span><span>18</span><span>);</span></div></div><div><div><div>15</div></div><div><span>const</span><span> </span><span>p2</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Person</span><span>(</span><span>'李四'</span><span>, </span><span>20</span><span>);</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>p1</span><span>.</span></span><span>name</span><span>);</span></div></div><div><div><div>18</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>p2</span><span>.</span></span><span>name</span><span>);</span></div></div><div><div><div>19</div></div><div><span><span>Person</span><span>.</span></span><span>sayHello</span><span>(); </span><span>//helle Person 类名字，静态就是静</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>静态属性：ES2022 支持直接写</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Person</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>static</span><span><span> </span><span>country</span><span> </span></span><span>=</span><span> </span><span>'中国'</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>Person</span><span>.</span></span><span>country</span><span>);</span><span>//中国</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>私有属性和方法<a href="#私有属性和方法"><span>#</span></a></h2><p>JavaScript 的<strong>私有属性和私有方法（Private Fields &amp; Methods）</strong>，是 ES2022 正式支持的语法，用 <code>#</code> 开头表示。只能在类的内部访问，类的外部无法访问和修改。类似于 Java 里的 <code>private</code>。</p><p>为什么需要私有属性：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//假设有一个银行账户类：</span></div></div><div><div><div>2</div></div><div><span>class</span><span> </span><span>Account</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>balance</span><span>) {</span></span></div></div><div><div><div>4</div></div><div><span>    </span><span>this</span><span>.</span><span>balance</span><span> </span><span>=</span><span><span> </span><span>balance</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>const</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Account</span><span>(</span><span>1000</span><span>);</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span><span>a</span><span>.</span></span><span>balance</span><span> </span><span>=</span><span> </span><span>100000000</span><span>;</span></div></div><div><div><div>11</div></div><div><span>//外部可以随意修改：1000 → 100000000这显然不安全。</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>私有属性（#）</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Account</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>#balance</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>balance</span><span>) {</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>this</span><span>.</span><span>#balance</span><span> </span><span>=</span><span><span> </span><span>balance</span><span>;</span></span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>  </span><span>getBalance</span><span>() {</span></div></div><div><div><div>9</div></div><div><span>    </span><span>return</span><span> </span><span>this</span><span>.</span><span>#balance</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>const</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Account</span><span>(</span><span>1000</span><span>);</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>.</span></span><span>getBalance</span><span>());</span><span>//1000</span></div></div><div><div><div>16</div></div><div><span>//外部访问</span></div></div><div><div><div>17</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>.</span></span><span>#balance</span><span>);</span><span>//直接报错</span></div></div><div><div><div>18</div></div><div><span>//外部修改</span></div></div><div><div><div>19</div></div><div><span><span>a</span><span>.</span></span><span>#balance</span><span> </span><span>=</span><span> </span><span>9999</span><span>;</span><span>//也是语法错误。</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>私有方法（#）</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Person</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>#</span><span>sayHello</span><span>() {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'hello'</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>  </span><span>greet</span><span>() {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>this</span><span>.</span><span>#sayHello</span><span>();</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>const</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Person</span><span>();</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>p</span><span>.</span></span><span>greet</span><span>();</span><span>//hello</span></div></div><div><div><div>14</div></div><div><span>//外部调用</span></div></div><div><div><div>15</div></div><div><span><span>p</span><span>.</span></span><span>#sayHello</span><span>();</span><span>//直接报错</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>私有静态属性</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Person</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>static</span><span><span> </span><span>#count</span><span> </span></span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>  </span><span>constructor</span><span>() {</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>Person</span><span>.</span><span>#count</span><span>++</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>  </span><span>static</span><span> </span><span>getCount</span><span>() {</span></div></div><div><div><div>9</div></div><div><span>    </span><span>return</span><span><span> </span><span>Person</span><span>.</span></span><span>#count</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>new</span><span> </span><span>Person</span><span>();</span></div></div><div><div><div>14</div></div><div><span>new</span><span> </span><span>Person</span><span>();</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>Person</span><span>.</span></span><span>getCount</span><span>());</span><span>//2</span></div></div><div><div><div>17</div></div><div><span>//外部调用</span></div></div><div><div><div>18</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>Person</span><span>.</span></span><span>#count</span><span>);</span><span>//报错</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>私有静态方法</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Person</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>static</span><span> #</span><span>hello</span><span>() {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'hello'</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>  </span><span>static</span><span> </span><span>say</span><span>() {</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>Person</span><span>.</span><span>#hello</span><span>();</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>Person</span><span>.</span></span><span>say</span><span>();</span><span>//hello</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意点：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//必须声明私有变量</span></div></div><div><div><div>2</div></div><div><span>//错误示范</span></div></div><div><div><div>3</div></div><div><span>class</span><span> </span><span>Person</span><span> {</span></div></div><div><div><div>4</div></div><div><span>  </span><span>constructor</span><span>() {</span></div></div><div><div><div>5</div></div><div><span>    </span><span>this</span><span>.</span><span>#name</span><span> </span><span>=</span><span> </span><span>'张三'</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div><span>//正确</span></div></div><div><div><div>9</div></div><div><span>class</span><span> </span><span>Person</span><span> {</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>#name</span><span>;</span><span>//声明私有</span></div></div><div><div><div>11</div></div><div><span>  </span><span>constructor</span><span>() {</span></div></div><div><div><div>12</div></div><div><span>    </span><span>this</span><span>.</span><span>#name</span><span> </span><span>=</span><span> </span><span>'张三'</span><span>;</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div><div><div><div>15</div></div><div><span>//只能在类内部访问</span></div></div><div><div><div>16</div></div><div><span>class</span><span> </span><span>Person</span><span> {</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>#name</span><span> </span><span>=</span><span> </span><span>'张三'</span><span>;</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>  </span><span>show</span><span>() {</span></div></div><div><div><div>20</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>#name</span><span>);</span></div></div><div><div><div>21</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>22</div></div><div><span>}</span></div></div><div><div><div>23</div></div><div><span>//子类不能直接访问父类私有属性</span></div></div><div><div><div>24</div></div><div><span>class</span><span> </span><span>A</span><span> {</span></div></div><div><div><div>25</div></div><div><span><span>  </span></span><span>#x</span><span> </span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>26</div></div><div><span>}</span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span>class</span><span> </span><span>B</span><span> </span><span>extends</span><span> </span><span>A</span><span> {</span></div></div><div><div><div>29</div></div><div><span>  </span><span>test</span><span>() {</span></div></div><div><div><div>30</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>#x</span><span>);</span></div></div><div><div><div>31</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>32</div></div><div><span>}</span></div></div><div><div><div>33</div></div><div><span>//获取设置私有数据的方法</span></div></div><div><div><div>34</div></div><div><span>class</span><span> </span><span>Person</span><span> {</span></div></div><div><div><div>35</div></div><div><span><span>  </span></span><span>#name</span><span>;</span></div></div><div><div><div>36</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>name</span><span>) {</span></span></div></div><div><div><div>37</div></div><div><span>    </span><span>this</span><span>.</span><span>#name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>38</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>39</div></div><div><span>  </span><span>getName</span><span>() {</span></div></div><div><div><div>40</div></div><div><span>    </span><span>return</span><span> </span><span>this</span><span>.</span><span>#name</span><span>;</span></div></div><div><div><div>41</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>42</div></div><div><span>  </span><span>setName</span><span><span>(</span><span>name</span><span>) {</span></span></div></div><div><div><div>43</div></div><div><span>    </span><span>this</span><span>.</span><span>#name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>44</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>45</div></div><div><span>}</span></div></div><div><div><div>46</div></div><div>
</div></div><div><div><div>47</div></div><div><span>//输出什么？undefined</span></div></div><div><div><div>48</div></div><div><span>//为什么？p.name和p.#name不是一个东西，实例上没有name所以是undefined如果是p.#name就报错</span></div></div><div><div><div>49</div></div><div><span>class</span><span> </span><span>Person</span><span> {</span></div></div><div><div><div>50</div></div><div><span><span>  </span></span><span>#name</span><span> </span><span>=</span><span> </span><span>'张三'</span><span>;</span></div></div><div><div><div>51</div></div><div><span>}</span></div></div><div><div><div>52</div></div><div>
</div></div><div><div><div>53</div></div><div><span>const</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Person</span><span>();</span></div></div><div><div><div>54</div></div><div>
</div></div><div><div><div>55</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>p</span><span>.</span></span><span>name</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>至于之前的“古法”模拟私有变量，这里不展开讲解</p></section>
<section><h2>extends<a href="#extends"><span>#</span></a></h2><p><code>extends</code> 是 JavaScript 中实现<strong>类继承</strong>的关键字。子类继承父类的属性和方法。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>父类</span><span> {}</span></div></div><div><div><div>2</div></div><div><span>class</span><span> </span><span>子类</span><span> </span><span>extends</span><span> </span><span>父类</span><span> {}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>eat</span><span>() {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'吃东西'</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>class</span><span> </span><span>Dog</span><span> </span><span>extends</span><span> </span><span>Animal</span><span> {}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>const</span><span> </span><span>dog</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Dog</span><span>();</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>dog</span><span>.</span></span><span>eat</span><span>();</span><span>//吃东西</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>继承构造函数</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>name</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>class</span><span> </span><span>Dog</span><span> </span><span>extends</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>7</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>name</span><span>) {</span></span></div></div><div><div><div>8</div></div><div><span>    </span><span>super</span><span><span>(</span><span>name</span><span>);</span></span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div><span>const</span><span> </span><span>dog</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Dog</span><span>(</span><span>'旺财'</span><span>);</span></div></div><div><div><div>12</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>dog</span><span>.</span></span><span>name</span><span>);</span><span>//旺财</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>方法重写</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>speak</span><span>() {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'动物叫'</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>class</span><span> </span><span>Dog</span><span> </span><span>extends</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>7</div></div><div><span>  </span><span>speak</span><span>() {</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'汪汪'</span><span>);</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div><span>new</span><span> </span><span>Dog</span><span>().</span><span>speak</span><span>();</span><span>//汪汪</span></div></div><div><div><div>12</div></div><div><span>//如果想保留父类逻辑</span></div></div><div><div><div>13</div></div><div><span>class</span><span> </span><span>Dog</span><span> </span><span>extends</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>14</div></div><div><span>  </span><span>speak</span><span>() {</span></div></div><div><div><div>15</div></div><div><span>    </span><span>super</span><span>.</span><span>speak</span><span>();</span><span>//保留父类逻辑</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'汪汪'</span><span>);</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>注意点：super前面不能有this操作</p></section>
<section><h2>super<a href="#super"><span>#</span></a></h2><p>一句话记忆：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>constructor</span><span>：</span></span></div></div><div><div><div>2</div></div><div><span>super</span><span>() </span><span>=</span><span><span> </span><span>调父类构造函数</span></span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>实例方法</span><span>：</span></span></div></div><div><div><div>5</div></div><div><span>super</span><span> </span><span>=</span><span> </span><span>父类</span><span>.</span><span>prototype</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>静态方法</span><span>：</span></span></div></div><div><div><div>8</div></div><div><span>super</span><span> </span><span>=</span><span><span> </span><span>父类</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>super 有两种用法：在 constructor 中和在普通方法中</p><p>在 constructor 中：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>name</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>class</span><span> </span><span>Dog</span><span> </span><span>extends</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>8</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>name</span><span>, </span><span>age</span><span>) {</span></span></div></div><div><div><div>9</div></div><div><span>    </span><span>super</span><span><span>(</span><span>name</span><span>);</span></span></div></div><div><div><div>10</div></div><div><span>    </span><span>this</span><span>.</span><span>age</span><span> </span><span>=</span><span><span> </span><span>age</span><span>;</span></span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>const</span><span> </span><span>d</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Dog</span><span>(</span><span>'旺财'</span><span>, </span><span>2</span><span>);</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>d</span><span>);</span></span></div></div><div><div><div>17</div></div><div><span>//输出</span></div></div><div><div><div>18</div></div><div><span><span>Dog</span><span> {</span></span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>name</span><span>: </span><span>'旺财'</span><span>,</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>age</span><span>: </span><span>2</span></div></div><div><div><div>21</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>为什么必须先写 super？：在子类中：this不是一开始就存在的。必须：super()执行后，JS 才创建出 <code>this</code>。可以理解成</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Dog</span><span> </span><span>extends</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>name</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>super</span><span><span>(</span><span>name</span><span>);</span></span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>//概念上类似：</span></div></div><div><div><div>7</div></div><div><span>function</span><span> </span><span>Dog</span><span><span>(</span><span>name</span><span>) {</span></span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>Animal</span><span>.</span><span>call</span><span>(</span><span>this</span><span><span>, </span><span>name</span><span>);</span></span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>只是概念上类似，底层不是直接 <code>call</code>。</p><p>普通方法中的 super</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>eat</span><span>() {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'动物吃东西'</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>class</span><span> </span><span>Dog</span><span> </span><span>extends</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>8</div></div><div><span>  </span><span>eat</span><span>() {</span></div></div><div><div><div>9</div></div><div><span>    </span><span>super</span><span>.</span><span>eat</span><span>();</span><span>//相当于：Animal.prototype.eat.call(this)</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'吃骨头'</span><span>);</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>new</span><span> </span><span>Dog</span><span>().</span><span>eat</span><span>();</span></div></div><div><div><div>15</div></div><div><span>//动物吃东西</span></div></div><div><div><div>16</div></div><div><span>//吃骨头</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>super 不是父类实例</strong></p><p>很多人以为：super等于：new Animal()；其实不是</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>eat</span><span>() {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>class</span><span> </span><span>Dog</span><span> </span><span>extends</span><span> </span><span>Animal</span><span> {}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>new</span><span> </span><span>Dog</span><span>().</span><span>eat</span><span>();</span><span>//Dog {}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>说明：this还是Dog 的实例，所以：super.eat()其实是：Animal.prototype.eat.call(this)</p><p><strong>super 访问父类属性</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>name</span><span> </span><span>=</span><span> </span><span>'动物'</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>class</span><span> </span><span>Dog</span><span> </span><span>extends</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>6</div></div><div><span>  </span><span>show</span><span>() {</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>super</span><span>.</span><span>name</span><span>);</span><span>//undefined</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>很多人会懵。因为：super指向Animal.prototype，而name是实例属性this.name不在：Animal.prototype上</p><p>例子：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>eat</span><span>() {}</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>Animal</span><span>.</span><span>prototype</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>5</div></div><div><span>  </span><span>eat</span><span>() {}</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div><span>super</span><span>.</span><span>eat</span><span>//能找到</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>//但是：name是实例属性，不在原型上 super.name就是undefined</span></div></div><div><div><div>10</div></div><div><span>class</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>name</span><span> </span><span>=</span><span> </span><span>'动物'</span><span>;</span></div></div><div><div><div>12</div></div><div><span>  </span><span>constructor</span><span>() {</span></div></div><div><div><div>13</div></div><div><span>  </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span> </span><span>'动物'</span><span>;</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>super 调用静态方法</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>static</span><span> </span><span>hello</span><span>() {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'hello'</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>class</span><span> </span><span>Dog</span><span> </span><span>extends</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>8</div></div><div><span>  </span><span>static</span><span> </span><span>hi</span><span>() {</span></div></div><div><div><div>9</div></div><div><span>    </span><span>super</span><span>.</span><span>hello</span><span>();</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>Dog</span><span>.</span></span><span>hi</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这里：super指向Animal，而不是Animal.prototype</p><p><strong>super 的this指向总结</strong></p><ul>
<li>在实例方法中，super指向：父类.prototype</li>
<li>在静态方法中，super指向：父类本身</li>
<li>在 constructor 中，作用是调用父类构造函数，创建 this</li>
</ul></section>
<section><h2>Class的应用<a href="#class的应用"><span>#</span></a></h2><p><strong>一、创建对象模板（最基本的应用）</strong></p><p>例如：用户。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>User</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>name</span><span>, </span><span>age</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>    </span><span>this</span><span>.</span><span>age</span><span> </span><span>=</span><span><span> </span><span>age</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>  </span><span>login</span><span>() {</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>`</span><span>${</span><span>this</span><span>.</span><span>name</span><span>}</span><span> 登录了`</span><span>);</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>const</span><span> </span><span>u1</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>User</span><span>(</span><span>'张三'</span><span>, </span><span>18</span><span>);</span></div></div><div><div><div>13</div></div><div><span>const</span><span> </span><span>u2</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>User</span><span>(</span><span>'李四'</span><span>, </span><span>20</span><span>);</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span><span>u1</span><span>.</span></span><span>login</span><span>();</span></div></div><div><div><div>16</div></div><div><span><span>u2</span><span>.</span></span><span>login</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>这里：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>User</span></div></div><div><div><div>2</div></div><div><span>↓</span></div></div><div><div><div>3</div></div><div><span>创建多个用户对象</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>二、封装业务对象</strong></p><p>例如：购物车。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Cart</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>constructor</span><span>() {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>this</span><span>.</span><span>goods</span><span> </span><span>=</span><span> [];</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>  </span><span>add</span><span><span>(</span><span>item</span><span>) {</span></span></div></div><div><div><div>7</div></div><div><span>    </span><span>this</span><span>.</span><span>goods</span><span>.</span><span>push</span><span><span>(</span><span>item</span><span>);</span></span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>  </span><span>remove</span><span><span>(</span><span>id</span><span>) {</span></span></div></div><div><div><div>11</div></div><div><span>    </span><span>this</span><span>.</span><span>goods</span><span> </span><span>=</span><span> </span><span>this</span><span>.</span><span>goods</span><span>.</span><span>filter</span><span>(</span></div></div><div><div><div>12</div></div><div><span><span>      </span></span><span>item</span><span> </span><span>=&gt;</span><span><span> </span><span>item</span><span>.</span></span><span>id</span><span> </span><span>!==</span><span><span> </span><span>id</span></span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>);</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>  </span><span>getTotal</span><span>() {</span></div></div><div><div><div>17</div></div><div><span>    </span><span>return</span><span> </span><span>this</span><span>.</span><span>goods</span><span>.</span><span>reduce</span><span>(</span></div></div><div><div><div>18</div></div><div><span><span>      </span></span><span>(</span><span>sum</span><span>, </span><span>item</span><span>) </span><span>=&gt;</span><span><span> </span><span>sum</span><span> </span></span><span>+</span><span><span> </span><span>item</span><span>.</span></span><span>price</span><span>,</span></div></div><div><div><div>19</div></div><div><span>      </span><span>0</span></div></div><div><div><div>20</div></div><div><span><span>    </span></span><span>);</span></div></div><div><div><div>21</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>22</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>使用：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>cart</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Cart</span><span>();</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>cart</span><span>.</span></span><span>add</span><span>({</span></div></div><div><div><div>4</div></div><div><span>  </span><span>id</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>5</div></div><div><span>  </span><span>price</span><span>:</span><span> </span><span>100</span></div></div><div><div><div>6</div></div><div><span>});</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>cart</span><span>.</span></span><span>getTotal</span><span>());</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>三、封装组件（前端很常见）</strong></p><p>例如自己实现一个弹窗：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Modal</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>open</span><span>() {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'打开弹窗'</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>  </span><span>close</span><span>() {</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'关闭弹窗'</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div><span>const</span><span> </span><span>modal</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Modal</span><span>();</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span><span>modal</span><span>.</span></span><span>open</span><span>();</span></div></div><div><div><div>13</div></div><div><span><span>modal</span><span>.</span></span><span>close</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>四、工具类（静态方法）</strong></p><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>MathUtil</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>static</span><span> </span><span>add</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>  </span><span>static</span><span> </span><span>sub</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>7</div></div><div><span>    </span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>-</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>MathUtil</span><span>.</span></span><span>add</span><span>(</span><span>1</span><span>, </span><span>2</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>实际上 JS 内置对象就是这样：</p><ul>
<li>Math</li>
<li>Date</li>
<li>Object</li>
<li>Array</li>
</ul><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>Math</span><span>.</span></span><span>max</span><span>(</span><span>1</span><span>, </span><span>2</span><span>);</span></div></div><div><div><div>2</div></div><div><span><span>Date</span><span>.</span></span><span>now</span><span>();</span></div></div><div><div><div>3</div></div><div><span><span>Object</span><span>.</span></span><span>keys</span><span><span>(</span><span>obj</span><span>);</span></span></div></div><div><div><div>4</div></div><div><span><span>Array</span><span>.</span></span><span>isArray</span><span><span>(</span><span>arr</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这些都是静态方法。</p><p><strong>五、数据模型（Model）</strong></p><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>User</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>data</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>this</span><span>.</span><span>id</span><span> </span><span>=</span><span><span> </span><span>data</span><span>.</span></span><span>id</span><span>;</span></div></div><div><div><div>4</div></div><div><span>    </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>data</span><span>.</span></span><span>name</span><span>;</span></div></div><div><div><div>5</div></div><div><span>    </span><span>this</span><span>.</span><span>email</span><span> </span><span>=</span><span><span> </span><span>data</span><span>.</span></span><span>email</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>  </span><span>isAdmin</span><span>() {</span></div></div><div><div><div>9</div></div><div><span>    </span><span>return</span><span> </span><span>this</span><span>.</span><span>role</span><span> </span><span>===</span><span> </span><span>'admin'</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>接口：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>res</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>id</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>'张三'</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>role</span><span>:</span><span> </span><span>'admin'</span></div></div><div><div><div>5</div></div><div><span>};</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>const</span><span> </span><span>user</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>User</span><span><span>(</span><span>res</span><span>);</span></span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>user</span><span>.</span></span><span>isAdmin</span><span>());</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>六、继承（extends）</strong></p><p>例如：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>eat</span><span>() {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'吃'</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>class</span><span> </span><span>Dog</span><span> </span><span>extends</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>8</div></div><div><span>  </span><span>bark</span><span>() {</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'汪汪'</span><span>);</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>class</span><span> </span><span>Cat</span><span> </span><span>extends</span><span> </span><span>Animal</span><span> {</span></div></div><div><div><div>14</div></div><div><span>  </span><span>meow</span><span>() {</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'喵喵'</span><span>);</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>17</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>这样：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>共同逻辑</span></div></div><div><div><div>2</div></div><div><span>↓</span></div></div><div><div><div>3</div></div><div><span>放父类</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>特殊逻辑</span></div></div><div><div><div>6</div></div><div><span>↓</span></div></div><div><div><div>7</div></div><div><span>放子类</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>七、游戏开发（非常常见）</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Player</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>move</span><span>() {}</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>class</span><span> </span><span>Warrior</span><span> </span><span>extends</span><span> </span><span>Player</span><span> {</span></div></div><div><div><div>6</div></div><div><span>  </span><span>attack</span><span>() {}</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>class</span><span> </span><span>Mage</span><span> </span><span>extends</span><span> </span><span>Player</span><span> {</span></div></div><div><div><div>10</div></div><div><span>  </span><span>cast</span><span>() {}</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>很多游戏引擎大量使用 <code>class</code>。</p><p><strong>八、Node.js 后端开发</strong></p><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>UserService</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>async</span><span> </span><span>login</span><span>() {}</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>  </span><span>async</span><span> </span><span>register</span><span>() {}</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>class</span><span> </span><span>UserController</span><span> {</span></div></div><div><div><div>7</div></div><div><span>  </span><span>async</span><span> </span><span>login</span><span><span>(</span><span>req</span><span>, </span><span>res</span><span>) {}</span></span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>很多框架都喜欢这种写法，例如：</p><ul>
<li>NestJS</li>
<li>Angular</li>
</ul><p><strong>九、React 早期开发</strong></p><p>以前大量使用类组件：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>App</span><span> </span><span>extends</span><span> </span><span>React</span><span>.</span><span>Component</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>state</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>count</span><span>:</span><span> </span><span>0</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>};</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>  </span><span>render</span><span>() {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>return</span><span> &lt;</span><span>div</span><span>&gt;Hello&lt;/</span><span>div</span><span>&gt;;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>虽然现在：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>Hooks</span><span> </span></span><span>&gt;</span><span><span> </span><span>Class</span><span> </span><span>Component</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>但很多老项目还有大量 class。</p><p><strong>十、继承内置类</strong></p><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>MyArray</span><span> </span><span>extends</span><span> </span><span>Array</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>first</span><span>() {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>return</span><span> </span><span>this</span><span>[</span><span>0</span><span>];</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>MyArray</span><span>(</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>);</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>.</span></span><span>first</span><span>());</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>十一、设计模式（面试加分）</strong></p><p>单例模式</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Singleton</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>static</span><span><span> </span><span>instance</span><span>;</span></span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>  </span><span>static</span><span> </span><span>getInstance</span><span>() {</span></div></div><div><div><div>5</div></div><div><span>    </span><span>if</span><span> (</span><span>!</span><span>this</span><span>.</span><span>instance</span><span>) {</span></div></div><div><div><div>6</div></div><div><span>      </span><span>this</span><span>.</span><span>instance</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Singleton</span><span>();</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>    </span><span>return</span><span> </span><span>this</span><span>.</span><span>instance</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>工厂模式</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>User</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>name</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>  </span><span>static</span><span> </span><span>create</span><span><span>(</span><span>name</span><span>) {</span></span></div></div><div><div><div>7</div></div><div><span>    </span><span>return</span><span> </span><span>new</span><span> </span><span>User</span><span><span>(</span><span>name</span><span>);</span></span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>十二、什么时候不建议用 class？</strong></p><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>add</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>//或者：</span></div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>formatDate</span><span> </span><span>=</span><span> () </span><span>=&gt;</span><span> {};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这种纯函数 没必要写成：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>Utils</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>add</span><span>() {}</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/20261021011es6-yi-bu-promise/</id>
      <title type="text">ES6异步Promise</title>
      <published>2026-10-21T12:57:33.000Z</published>
      <updated>2026-10-21T12:57:33.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/20261021011es6-yi-bu-promise/"/>
      <summary type="text">本文主要学习ES6异步Promise</summary>
      <content type="html"><![CDATA[<section><h2>Promise 是什么<a href="#promise-是什么"><span>#</span></a></h2><p><strong>认识Promise</strong></p><ul>
<li>异步操作的一种解决方案</li>
<li><code>Promise</code> 是 JavaScript 中用于<strong>处理异步操作结果</strong>的一种对象。你可以把它理解成一个“未来会得到结果的承诺”。</li>
<li>比如，你点了一份外卖：下单时：结果还没出来 → **等待中（pending）**外卖送到了 → **成功（fulfilled）**商家取消订单 → <strong>失败（rejected）</strong></li>
</ul><p><strong>什么时候用Promise</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//网络请求（fetch）</span></div></div><div><div><div>2</div></div><div><span>//读取文件</span></div></div><div><div><div>3</div></div><div><span>//定时器（setTimeout）</span></div></div><div><div><div>4</div></div><div><span>//数据库查询</span></div></div><div><div><div>5</div></div><div><span>//没有 Promise 时，代码经常会写成：这种层层嵌套被称为回调地狱（Callback Hell）。</span></div></div><div><div><div>6</div></div><div><span>getUser</span><span>(</span><span>function</span><span><span>(</span><span>user</span><span>) {</span></span></div></div><div><div><div>7</div></div><div><span>  </span><span>getOrders</span><span><span>(</span><span>user</span><span>.</span></span><span>id</span><span>, </span><span>function</span><span><span>(</span><span>orders</span><span>) {</span></span></div></div><div><div><div>8</div></div><div><span>    </span><span>getProducts</span><span><span>(</span><span>orders</span><span>, </span></span><span>function</span><span><span>(</span><span>products</span><span>) {</span></span></div></div><div><div><div>9</div></div><div><span>      </span><span>// ...</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>});</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>12</div></div><div><span>});</span></div></div><div><div><div>13</div></div><div><span>//Promise 可以把它改成</span></div></div><div><div><div>14</div></div><div><span>getUser</span><span>()</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>user</span><span> </span></span><span>=&gt;</span><span> </span><span>getOrders</span><span><span>(</span><span>user</span><span>.</span></span><span>id</span><span>))</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>orders</span><span> </span></span><span>=&gt;</span><span> </span><span>getProducts</span><span><span>(</span><span>orders</span><span>))</span></span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>products</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>products</span><span>);</span></span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>.</span><span>catch</span><span><span>(</span><span>err</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>error</span><span><span>(</span><span>err</span><span>);</span></span></div></div><div><div><div>22</div></div><div><span><span>  </span></span><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>Promise的基本用法<a href="#promise的基本用法"><span>#</span></a></h2><p><strong>实例化构造函数生成对象</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//Promise状态一旦改变，就不会变化</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>((</span><span>resolve</span><span>, </span><span>reject</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>//resolve({ name: 'alex' }); //成功</span></div></div><div><div><div>4</div></div><div><span>  </span><span>reject</span><span>(</span><span>new</span><span> </span><span>Error</span><span>(</span><span>'reason'</span><span>)); </span><span>//失败</span></div></div><div><div><div>5</div></div><div><span>});</span></div></div><div><div><div>6</div></div><div><span>//console.log(p); //Promise { &lt;pending&gt; } 等待</span></div></div><div><div><div>7</div></div><div><span><span>p</span><span>.</span></span><span>then</span><span>(</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>(</span><span>data</span><span>) </span><span>=&gt;</span><span> {</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'success'</span><span><span>, </span><span>data</span><span>); </span></span><span>//success { name: 'alex' }</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>(</span><span>err</span><span>) </span><span>=&gt;</span><span> {</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'error'</span><span><span>, </span><span>err</span><span>);</span></span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>14</div></div><div><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>Promise 的三个状态：</strong></p><ol>
<li><strong>Pending（等待中）</strong></li>
<li><strong>Fulfilled（已成功）</strong></li>
<li><strong>Rejected（已失败）</strong></li>
</ol></section>
<section><h2>then()<a href="#then"><span>#</span></a></h2><p><code>then()</code> 根据当前 Promise 的状态（fulfilled 或 rejected）执行对应的回调，并返回一个新的 Promise</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//Promise状态一旦改变，就不会变化</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>((</span><span>resolve</span><span>, </span><span>reject</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>resolve</span><span>({ </span><span>name</span><span>:</span><span> </span><span>'alex'</span><span> }); </span><span>//成功</span></div></div><div><div><div>4</div></div><div><span>  </span><span>//reject(new Error('reason')); //失败</span></div></div><div><div><div>5</div></div><div><span>});</span></div></div><div><div><div>6</div></div><div><span><span>p</span><span>.</span></span><span>then</span><span>(</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>(</span><span>data</span><span>) </span><span>=&gt;</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'success'</span><span><span>, </span><span>data</span><span>); </span></span><span>//success { name: 'alex' }</span></div></div><div><div><div>9</div></div><div><span>    </span><span>///throw new Error('reason111');</span></div></div><div><div><div>10</div></div><div><span>    </span><span>return</span><span> </span><span>Promise</span><span>.</span><span>reject</span><span>(</span><span>new</span><span> </span><span>Error</span><span>(</span><span>'reason'</span><span>));</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>12</div></div><div><span>   </span><span>//第二个参数比较少用，错误通常统一交给catch</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>(</span><span>err</span><span>) </span><span>=&gt;</span><span> {</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'error'</span><span><span>, </span><span>err</span><span>);</span></span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>16</div></div><div><span>).</span><span>then</span><span>(</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>(</span><span>data</span><span>) </span><span>=&gt;</span><span> {</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'success1'</span><span><span>, </span><span>data</span><span>); </span></span><span>//success undefined 默认返回的undefined</span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>(</span><span>err</span><span>) </span><span>=&gt;</span><span> {</span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'error1'</span><span><span>, </span><span>err</span><span>);</span></span></div></div><div><div><div>22</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>23</div></div><div><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><ol>
<li>创建一个 Promise 对象p，resolve一个对象{name: ‘alex’ }，这里是成功状态</li>
<li>p.then接受两个参数，第一个是成功的时候执行，第二个是失败的时候执行，怎么看成功失败，取决于前面的Promise ，前面的Promise 成功并且返回{ name: ‘alex’ }，所以第一个then执行一个参数的函数，所以打印success { name: ‘alex’ }，然后返回一个失败的Promise</li>
<li>第二个then执行的前面Promise ，前面Promise是失败的，所以执行第二个参数’error1’, err</li>
</ol></section>
<section><h2>catch()<a href="#catch"><span>#</span></a></h2><p><code>catch()</code> 专门用来<strong>处理 Promise 链中的失败（rejected）和异常（throw）</strong>。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//Promise状态一旦改变，就不会变化</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>((</span><span>resolve</span><span>, </span><span>reject</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>resolve</span><span>({ </span><span>name</span><span>:</span><span> </span><span>'alex'</span><span> }); </span><span>//成功</span></div></div><div><div><div>4</div></div><div><span>  </span><span>//reject(new Error('reason')); //失败</span></div></div><div><div><div>5</div></div><div><span>});</span></div></div><div><div><div>6</div></div><div><span>//console.log(p); //Promise { &lt;pending&gt; } 等待</span></div></div><div><div><div>7</div></div><div><span><span>p</span><span>.</span></span><span>then</span><span><span>((</span><span>data</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'success'</span><span><span>, </span><span>data</span><span>); </span></span><span>//success { name: 'alex' }</span></div></div><div><div><div>9</div></div><div><span>  </span><span>///throw new Error('reason111');</span></div></div><div><div><div>10</div></div><div><span>  </span><span>return</span><span> </span><span>Promise</span><span>.</span><span>reject</span><span>(</span><span>new</span><span> </span><span>Error</span><span>(</span><span>'reason'</span><span>));</span></div></div><div><div><div>11</div></div><div><span>})</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>((</span><span>data</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'success1'</span><span><span>, </span><span>data</span><span>); </span></span><span>//success { name: 'alex' }</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>.</span><span>catch</span><span><span>((</span><span>err</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>err</span><span>);</span></span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>为什么推荐 <code>catch</code>，而不是 <code>then</code> 的第二个参数？</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span>(</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>data</span><span> </span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span>      </span><span>throw</span><span> </span><span>new</span><span> </span><span>Error</span><span>(</span><span>'boom'</span><span>);</span><span>//Uncaught Error: boom</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>},</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>err</span><span> </span><span>=&gt;</span><span> {</span></div></div><div><div><div>7</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'error'</span><span><span>, </span><span>err</span><span>);</span></span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>第二个参数<strong>没有捕获到</strong>；then(success, fail)中的 <code>fail</code>：只能处理当前 Promise 的 reject。不能处理 <code>success</code> 回调里面抛出的异常。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>((</span><span>data</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>throw</span><span> </span><span>new</span><span> </span><span>Error</span><span>(</span><span>'boom'</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>.</span><span>catch</span><span><span>((</span><span>err</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>err</span><span>.</span></span><span>message</span><span>); </span><span>//boom</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>8</div></div><div><span>//可以捕获。</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li>catch可以捕获前面的错误</li>
<li>catch也是返回一个Promise，默认返回undefined，</li>
</ul></section>
<section><h2>finally()<a href="#finally"><span>#</span></a></h2><p>无论 Promise 成功（fulfilled）还是失败（rejected）都会执行的回调。不变化不执行</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//基本语法</span></div></div><div><div><div>2</div></div><div><span>promise</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>res</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"成功："</span><span><span>, </span><span>res</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>.</span><span>catch</span><span><span>(</span><span>err</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"失败："</span><span><span>, </span><span>err</span><span>);</span></span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>.</span><span>finally</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"无论成功或失败都会执行"</span><span>);</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>12</div></div><div><span>//不会改变 Promise 的结果（重要）</span></div></div><div><div><div>13</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>.</span><span>finally</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>15</div></div><div><span>    </span><span>return</span><span> </span><span>999</span><span>; </span><span>// ❌ 没用</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>res</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>res</span><span>); </span></span><span>// 1</span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>20</div></div><div><span>//如果 finally 里抛错，会影响结果</span></div></div><div><div><div>21</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>22</div></div><div><span><span>  </span></span><span>.</span><span>finally</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>23</div></div><div><span>    </span><span>throw</span><span> </span><span>new</span><span> </span><span>Error</span><span>(</span><span>"finally error"</span><span>);</span></div></div><div><div><div>24</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>25</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>res</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>26</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>res</span><span>);</span></span></div></div><div><div><div>27</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>28</div></div><div><span><span>  </span></span><span>.</span><span>catch</span><span><span>(</span><span>err</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>29</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>err</span><span>.</span></span><span>message</span><span>); </span><span>// finally error</span></div></div><div><div><div>30</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>31</div></div><div><span>//常见使用场景</span></div></div><div><div><div>32</div></div><div><span>//关闭 loading</span></div></div><div><div><div>33</div></div><div><span><span>loading</span><span> </span></span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>34</div></div><div><span>fetchData</span><span>()</span></div></div><div><div><div>35</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>data</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>36</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>data</span><span>);</span></span></div></div><div><div><div>37</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>38</div></div><div><span><span>  </span></span><span>.</span><span>catch</span><span><span>(</span><span>err</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>39</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>err</span><span>);</span></span></div></div><div><div><div>40</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>41</div></div><div><span><span>  </span></span><span>.</span><span>finally</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>42</div></div><div><span><span>    </span></span><span>loading</span><span> </span><span>=</span><span> </span><span>false</span><span>;</span></div></div><div><div><div>43</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>44</div></div><div><span>//清理资源</span></div></div><div><div><div>45</div></div><div><span><span>db</span><span>.</span></span><span>query</span><span><span>(</span><span>sql</span><span>)</span></span></div></div><div><div><div>46</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>result</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>47</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>result</span><span>);</span></span></div></div><div><div><div>48</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>49</div></div><div><span><span>  </span></span><span>.</span><span>finally</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>50</div></div><div><span><span>    </span></span><span>db</span><span>.</span><span>close</span><span>();</span></div></div><div><div><div>51</div></div><div><span><span>  </span></span><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>和 then/catch 的区别</p>

<table><thead><tr><th>方法</th><th>是否处理成功</th><th>是否处理失败</th><th>是否一定执行</th></tr></thead><tbody><tr><td><code>then()</code></td><td>✔</td><td>✖</td><td>✖</td></tr><tr><td><code>catch()</code></td><td>✖</td><td>✔</td><td>✖</td></tr><tr><td><code>finally()</code></td><td>✖（不处理结果）</td><td>✖（不处理结果）</td><td>✔</td></tr></tbody></table></section>
<section><h2>Promise.resolve() 和 Promise.reject(）<a href="#promiseresolve-和-promisereject"><span>#</span></a></h2><p>是 Promise 提供的两个<strong>快速创建已确定状态 Promise 的方法</strong>，本质上用来“直接返回成功或失败的 Promise”。</p><p><strong>本质：</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//Promise.resolve() 是成功状态Promise 的一种简写形式</span></div></div><div><div><div>2</div></div><div><span>new</span><span> </span><span>Promise</span><span><span>(</span><span>resolve</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>resolve</span><span>(</span><span>'foo'</span><span>)</span></div></div><div><div><div>4</div></div><div><span>});</span></div></div><div><div><div>5</div></div><div><span>//等价于</span></div></div><div><div><div>6</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>'foo'</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>参数：</strong></p><p>Promise.resolve：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//Promise.resolve 一般参数 then</span></div></div><div><div><div>2</div></div><div><span>// Promise.resolve('foo').then((data) =&gt; {</span></div></div><div><div><div>3</div></div><div><span>//   console.log(data); //foo</span></div></div><div><div><div>4</div></div><div><span>// });</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>//Promise.resolve   Promise 参数</span></div></div><div><div><div>7</div></div><div><span>const</span><span> </span><span>p1</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>((</span><span>resolve</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>8</div></div><div><span>  </span><span>// setTimeout(() =&gt; {</span></div></div><div><div><div>9</div></div><div><span>  </span><span>//   resolve('我执行了');</span></div></div><div><div><div>10</div></div><div><span>  </span><span>// }, 1000);</span></div></div><div><div><div>11</div></div><div><span>  </span><span>setTimeout</span><span><span>(</span><span>resolve</span><span>, </span></span><span>2000</span><span>, </span><span>'我执行了'</span><span>);</span></div></div><div><div><div>12</div></div><div><span>});</span></div></div><div><div><div>13</div></div><div><span>////当Promise.resolve(接收的是 Promise 对象时，直接返回这个Promise对象，什么都不做</span></div></div><div><div><div>14</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span><span>(</span><span>p1</span><span>).</span></span><span>then</span><span><span>((</span><span>data</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>data</span><span>); </span></span><span>//foo</span></div></div><div><div><div>16</div></div><div><span>});</span></div></div><div><div><div>17</div></div><div><span>//判断</span></div></div><div><div><div>18</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>Promise</span><span>.</span><span>resolve</span><span><span>(</span><span>p1</span><span>) </span></span><span>===</span><span><span> </span><span>p1</span><span>); </span></span><span>//true</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>//Promise.resolve  具有then方法对象</span></div></div><div><div><div>21</div></div><div><span>const</span><span> </span><span>thenable</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>22</div></div><div><span>  </span><span>then</span><span><span>(</span><span>resolve</span><span>, </span><span>reject</span><span>) {</span></span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'具有then方法对象'</span><span>); </span><span>//具有then方法对象，会直接执行对象里面的then方法</span></div></div><div><div><div>24</div></div><div><span>    </span><span>resolve</span><span>(</span><span>'data'</span><span>);</span></div></div><div><div><div>25</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>26</div></div><div><span>};</span></div></div><div><div><div>27</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span><span>(</span><span>thenable</span><span>).</span></span><span>then</span><span>(</span></div></div><div><div><div>28</div></div><div><span><span>  </span></span><span>(</span><span>data</span><span>) </span><span>=&gt;</span><span> {</span></div></div><div><div><div>29</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>data</span><span>); </span></span><span>//不执行</span></div></div><div><div><div>30</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>31</div></div><div><span><span>  </span></span><span>(</span><span>err</span><span>) </span><span>=&gt;</span><span> {</span></div></div><div><div><div>32</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>err</span><span>); </span></span><span>//不执行</span></div></div><div><div><div>33</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>34</div></div><div><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>Promise.reject</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//Promise.reject 失败状态的一种简写</span></div></div><div><div><div>2</div></div><div><span>new</span><span> </span><span>Promise</span><span><span>((</span><span>resolve</span><span>, </span><span>reject</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>reject</span><span>(</span><span>'err'</span><span>);</span></div></div><div><div><div>4</div></div><div><span>}).</span><span>then</span><span>(</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>() </span><span>=&gt;</span><span> {},</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>(</span><span>err</span><span>) </span><span>=&gt;</span><span> {</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>err</span><span>);</span></span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>9</div></div><div><span>);</span></div></div><div><div><div>10</div></div><div><span>//等价于</span></div></div><div><div><div>11</div></div><div><span>Promise</span><span>.</span><span>reject</span><span>(</span><span>'err1'</span><span>).</span><span>then</span><span>(</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>() </span><span>=&gt;</span><span> {},</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>(</span><span>err</span><span>) </span><span>=&gt;</span><span> {</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>err</span><span>);</span></span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>16</div></div><div><span>);</span></div></div><div><div><div>17</div></div><div><span>//参数问题，不管什么参数都会原封不动向后传递</span></div></div><div><div><div>18</div></div><div><span>Promise</span><span>.</span><span>reject</span><span><span>(</span><span>p1</span><span>).</span></span><span>then</span><span>(</span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>() </span><span>=&gt;</span><span> {},</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>(</span><span>err</span><span>) </span><span>=&gt;</span><span> {</span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>err</span><span>); </span></span><span>//Promise { &lt;pending&gt; }</span></div></div><div><div><div>22</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>23</div></div><div><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>在then方法中的应用：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>new</span><span> </span><span>Promise</span><span><span>((</span><span>resolve</span><span>, </span><span>reject</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>resolve</span><span>(</span><span>123</span><span>);</span></div></div><div><div><div>3</div></div><div><span>})</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>((</span><span>data</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>5</div></div><div><span>    </span><span>//Promise.resolve和Promise.reject应用的地方</span></div></div><div><div><div>6</div></div><div><span>    </span><span>//console.log(data);</span></div></div><div><div><div>7</div></div><div><span>    </span><span>return</span><span> </span><span>Promise</span><span>.</span><span>reject</span><span>(</span><span>'reason'</span><span>); </span><span>//失败状态</span></div></div><div><div><div>8</div></div><div><span>    </span><span>//return data; //等价于return Promise.resolve(data);</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>((</span><span>data</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>data</span><span>); </span></span><span>//123 默认返回的undefined</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>.</span><span>catch</span><span><span>((</span><span>err</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>err</span><span>); </span></span><span>//reason</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>Promise.all()<a href="#promiseall"><span>#</span></a></h2><p>并发执行多个异步任务，等所有任务都成功后，返回所有结果；如果有一个失败，则立即失败。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//参数：</span></div></div><div><div><div>2</div></div><div><span>//接收一个可迭代对象（通常是数组）</span></div></div><div><div><div>3</div></div><div><span>//数组里面可以是：Promise 对象或者普通值</span></div></div><div><div><div>4</div></div><div><span>//返回：一个新的 Promise。</span></div></div><div><div><div>5</div></div><div><span>Promise</span><span>.</span><span>all</span><span><span>(</span><span>iterable</span><span>)</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>例子：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>p1</span><span> </span><span>=</span><span> </span><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>1</span><span>);</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>p2</span><span> </span><span>=</span><span> </span><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>2</span><span>);</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>p3</span><span> </span><span>=</span><span> </span><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>3</span><span>);</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>Promise</span><span>.</span><span>all</span><span><span>([</span><span>p1</span><span>, </span><span>p2</span><span>, </span><span>p3</span><span>])</span></span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>res</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>res</span><span>);</span></span><span>//[1, 2, 3]</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>模拟多个异步请求</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//注意：不是 1 + 2 + 3 = 6 秒；而是：最大时间 3 秒，因为三个请求是并发执行的。</span></div></div><div><div><div>2</div></div><div><span>//返回结果顺序：传入数组的顺序返回</span></div></div><div><div><div>3</div></div><div><span>function</span><span> </span><span>request1</span><span>() {</span></div></div><div><div><div>4</div></div><div><span>  </span><span>return</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>(</span><span>resolve</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>5</div></div><div><span>    </span><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>6</div></div><div><span>      </span><span>resolve</span><span>(</span><span>'用户信息'</span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>}, </span><span>1000</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>function</span><span> </span><span>request2</span><span>() {</span></div></div><div><div><div>12</div></div><div><span>  </span><span>return</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>(</span><span>resolve</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>13</div></div><div><span>    </span><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>14</div></div><div><span>      </span><span>resolve</span><span>(</span><span>'订单信息'</span><span>);</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>}, </span><span>2000</span><span>);</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>17</div></div><div><span>}</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>function</span><span> </span><span>request3</span><span>() {</span></div></div><div><div><div>20</div></div><div><span>  </span><span>return</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>(</span><span>resolve</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>21</div></div><div><span>    </span><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>22</div></div><div><span>      </span><span>resolve</span><span>(</span><span>'商品信息'</span><span>);</span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>}, </span><span>3000</span><span>);</span></div></div><div><div><div>24</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>25</div></div><div><span>}</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>Promise</span><span>.</span><span>all</span><span>([</span></div></div><div><div><div>28</div></div><div><span>  </span><span>request1</span><span>(),</span></div></div><div><div><div>29</div></div><div><span>  </span><span>request2</span><span>(),</span></div></div><div><div><div>30</div></div><div><span>  </span><span>request3</span><span>()</span></div></div><div><div><div>31</div></div><div><span>]).</span><span>then</span><span><span>(</span><span>res</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>32</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>res</span><span>);</span></span></div></div><div><div><div>33</div></div><div><span>});</span></div></div><div><div><div>34</div></div><div><span>//一个失败，全部失败</span></div></div><div><div><div>35</div></div><div><span>const</span><span> </span><span>p1</span><span> </span><span>=</span><span> </span><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>1</span><span>);</span></div></div><div><div><div>36</div></div><div><span>const</span><span> </span><span>p2</span><span> </span><span>=</span><span> </span><span>Promise</span><span>.</span><span>reject</span><span>(</span><span>'失败了'</span><span>);</span></div></div><div><div><div>37</div></div><div><span>const</span><span> </span><span>p3</span><span> </span><span>=</span><span> </span><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>3</span><span>);</span></div></div><div><div><div>38</div></div><div><span>Promise</span><span>.</span><span>all</span><span><span>([</span><span>p1</span><span>, </span><span>p2</span><span>, </span><span>p3</span><span>])</span></span></div></div><div><div><div>39</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>res</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>40</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>res</span><span>);</span></span></div></div><div><div><div>41</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>42</div></div><div><span><span>  </span></span><span>.</span><span>catch</span><span><span>(</span><span>err</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>43</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>err</span><span>);</span></span></div></div><div><div><div>44</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>45</div></div><div><span>//为什么叫"立即失败"</span></div></div><div><div><div>46</div></div><div><span>const</span><span> </span><span>p1</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>(</span><span>resolve</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>47</div></div><div><span>  </span><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> </span><span>resolve</span><span>(</span><span>1</span><span>), </span><span>3000</span><span>);</span></div></div><div><div><div>48</div></div><div><span>});</span></div></div><div><div><div>49</div></div><div>
</div></div><div><div><div>50</div></div><div><span>const</span><span> </span><span>p2</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>((</span><span>resolve</span><span>, </span><span>reject</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>51</div></div><div><span>  </span><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> </span><span>reject</span><span>(</span><span>'错误'</span><span>), </span><span>1000</span><span>);</span></div></div><div><div><div>52</div></div><div><span>});</span></div></div><div><div><div>53</div></div><div>
</div></div><div><div><div>54</div></div><div><span>Promise</span><span>.</span><span>all</span><span><span>([</span><span>p1</span><span>, </span><span>p2</span><span>])</span></span></div></div><div><div><div>55</div></div><div><span><span>  </span></span><span>.</span><span>catch</span><span><span>(</span><span>err</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>56</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>err</span><span>);</span></span></div></div><div><div><div>57</div></div><div><span><span>  </span></span><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>Promise.race() 和 Promise.allSettled()<a href="#promiserace-和-promiseallsettled"><span>#</span></a></h2><p><strong>Promise.race</strong></p><p>返回一个新的 Promise，谁先 <code>resolve</code>返回成功结果，谁先 <code>reject</code>返回失败结果，不会等其他 Promise。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//谁先成功就返回谁</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>p1</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>(</span><span>resolve</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span>    </span><span>resolve</span><span>(</span><span>'请求1'</span><span>);</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>}, </span><span>3000</span><span>);</span></div></div><div><div><div>6</div></div><div><span>});</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>const</span><span> </span><span>p2</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>(</span><span>resolve</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>9</div></div><div><span>  </span><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>10</div></div><div><span>    </span><span>resolve</span><span>(</span><span>'请求2'</span><span>);</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>}, </span><span>1000</span><span>);</span></div></div><div><div><div>12</div></div><div><span>});</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>Promise</span><span>.</span><span>race</span><span><span>([</span><span>p1</span><span>, </span><span>p2</span><span>])</span></span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>res</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>res</span><span>);</span></span><span>//请求2</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>18</div></div><div><span>//谁先失败也算结束</span></div></div><div><div><div>19</div></div><div><span>const</span><span> </span><span>p1</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>(</span><span>resolve</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>20</div></div><div><span>  </span><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>21</div></div><div><span>    </span><span>resolve</span><span>(</span><span>'成功'</span><span>);</span></div></div><div><div><div>22</div></div><div><span><span>  </span></span><span>}, </span><span>3000</span><span>);</span></div></div><div><div><div>23</div></div><div><span>});</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span>const</span><span> </span><span>p2</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>((</span><span>resolve</span><span>, </span><span>reject</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>26</div></div><div><span>  </span><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>27</div></div><div><span>    </span><span>reject</span><span>(</span><span>'失败'</span><span>);</span></div></div><div><div><div>28</div></div><div><span><span>  </span></span><span>}, </span><span>1000</span><span>);</span></div></div><div><div><div>29</div></div><div><span>});</span></div></div><div><div><div>30</div></div><div>
</div></div><div><div><div>31</div></div><div><span>Promise</span><span>.</span><span>race</span><span><span>([</span><span>p1</span><span>, </span><span>p2</span><span>])</span></span></div></div><div><div><div>32</div></div><div><span><span>  </span></span><span>.</span><span>catch</span><span><span>(</span><span>err</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>33</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>err</span><span>);</span></span><span>//失败</span></div></div><div><div><div>34</div></div><div><span><span>  </span></span><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//实际开发场景：请求超时</span></div></div><div><div><div>2</div></div><div><span>//正常请求</span></div></div><div><div><div>3</div></div><div><span>fetch</span><span>(</span><span>'/api/user'</span><span>)</span></div></div><div><div><div>4</div></div><div><span>//超时 Promise</span></div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>timeout</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>((</span><span>resolve</span><span>, </span><span>reject</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>6</div></div><div><span>  </span><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>reject</span><span>(</span><span>'请求超时'</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}, </span><span>5000</span><span>);</span></div></div><div><div><div>9</div></div><div><span>});</span></div></div><div><div><div>10</div></div><div><span>//看谁先返回</span></div></div><div><div><div>11</div></div><div><span>Promise</span><span>.</span><span>race</span><span>([</span></div></div><div><div><div>12</div></div><div><span>  </span><span>fetch</span><span>(</span><span>'/api/user'</span><span>),</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>timeout</span></div></div><div><div><div>14</div></div><div><span>])</span></div></div><div><div><div>15</div></div><div><span>.</span><span>then</span><span><span>(</span><span>res</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>res</span><span>);</span></span></div></div><div><div><div>17</div></div><div><span>})</span></div></div><div><div><div>18</div></div><div><span>.</span><span>catch</span><span><span>(</span><span>err</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>err</span><span>);</span></span></div></div><div><div><div>20</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>Promise.allSettled</strong></p><p>所有 Promise 都有结果（成功或失败），等待所有 Promise 都执行完。然后返回结果</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//基本用法</span></div></div><div><div><div>2</div></div><div><span>Promise</span><span>.</span><span>allSettled</span><span>([</span></div></div><div><div><div>3</div></div><div><span>  </span><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>1</span><span>),</span></div></div><div><div><div>4</div></div><div><span>  </span><span>Promise</span><span>.</span><span>reject</span><span>(</span><span>'错误'</span><span>),</span></div></div><div><div><div>5</div></div><div><span>  </span><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>3</span><span>)</span></div></div><div><div><div>6</div></div><div><span>])</span></div></div><div><div><div>7</div></div><div><span>.</span><span>then</span><span><span>(</span><span>res</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>res</span><span>);</span></span></div></div><div><div><div>9</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//输出</span></div></div><div><div><div>2</div></div><div><span>[</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>{</span></div></div><div><div><div>4</div></div><div><span>    </span><span>status</span><span>:</span><span> </span><span>'fulfilled'</span><span>,</span></div></div><div><div><div>5</div></div><div><span>    </span><span>value</span><span>:</span><span> </span><span>1</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>{</span></div></div><div><div><div>8</div></div><div><span>    </span><span>status</span><span>:</span><span> </span><span>'rejected'</span><span>,</span></div></div><div><div><div>9</div></div><div><span>    </span><span>reason</span><span>:</span><span> </span><span>'错误'</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>{</span></div></div><div><div><div>12</div></div><div><span>    </span><span>status</span><span>:</span><span> </span><span>'fulfilled'</span><span>,</span></div></div><div><div><div>13</div></div><div><span>    </span><span>value</span><span>:</span><span> </span><span>3</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span>]</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>实际开发场景</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//页面初始化</span></div></div><div><div><div>2</div></div><div><span>//广告失败不应该导致整个页面白屏。</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>result</span><span> </span><span>=</span><span> </span><span>await</span><span> </span><span>Promise</span><span>.</span><span>allSettled</span><span>([</span></div></div><div><div><div>4</div></div><div><span>  </span><span>getUser</span><span>(),</span></div></div><div><div><div>5</div></div><div><span>  </span><span>getOrders</span><span>(),</span></div></div><div><div><div>6</div></div><div><span>  </span><span>getMessage</span><span>(),</span></div></div><div><div><div>7</div></div><div><span>  </span><span>getAd</span><span>()</span></div></div><div><div><div>8</div></div><div><span>]);</span></div></div><div><div><div>9</div></div><div><span><span>result</span><span>.</span></span><span>forEach</span><span><span>(</span><span>item</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>10</div></div><div><span>  </span><span>if</span><span><span> (</span><span>item</span><span>.</span></span><span>status</span><span> </span><span>===</span><span> </span><span>'fulfilled'</span><span>) {</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>item</span><span>.</span></span><span>value</span><span>);</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>item</span><span>.</span></span><span>reason</span><span>);</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span>});</span></div></div><div><div><div>16</div></div><div><span>//筛选成功结果</span></div></div><div><div><div>17</div></div><div><span>const</span><span> </span><span>res</span><span> </span><span>=</span><span> </span><span>await</span><span> </span><span>Promise</span><span>.</span><span>allSettled</span><span><span>(</span><span>promises</span><span>);</span></span></div></div><div><div><div>18</div></div><div><span>const</span><span> </span><span>data</span><span> </span><span>=</span><span><span> </span><span>res</span></span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>.</span><span>filter</span><span><span>(</span><span>item</span><span> </span></span><span>=&gt;</span><span><span> </span><span>item</span><span>.</span></span><span>status</span><span> </span><span>===</span><span> </span><span>'fulfilled'</span><span>)</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>.</span><span>map</span><span><span>(</span><span>item</span><span> </span></span><span>=&gt;</span><span><span> </span><span>item</span><span>.</span></span><span>value</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h2>Promise 的注意事项<a href="#promise-的注意事项"><span>#</span></a></h2><p>Promise 这一块很多“坑”其实不是语法问题，而是<strong>执行机制 + 微任务队列 + 链式调用规则</strong>导致的</p><p><strong>一、executor 是同步执行的（最容易误解）</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Promise</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'A'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>});</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'B'</span><span>);</span></div></div><div><div><div>6</div></div><div><span>//输出AB</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>new Promise(executor)</code> 的 executor <strong>立即同步执行</strong></p><p>只有 <code>.then()</code> 才是异步（微任务）</p><p><strong>二、then 是异步（微任务）</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span>().</span><span>then</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'then'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>});</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'sync'</span><span>);</span></div></div><div><div><div>6</div></div><div><span>//输出sync  then</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>.then/.catch/.finally</code> 都进 <strong>微任务队列</strong></p><p>当前同步代码执行完才执行</p><p><strong>三、Promise 不是“真正并行”，只是异步调度</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>1</span><span>);</span></div></div><div><div><div>2</div></div><div><span>setTimeout</span><span>(() </span><span>=&gt;</span><span><span> </span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>2</span><span>));</span></div></div><div><div><div>3</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span>().</span><span>then</span><span>(() </span><span>=&gt;</span><span><span> </span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>3</span><span>));</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>4</span><span>);</span></div></div><div><div><div>5</div></div><div><span>//1 4 2 2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>执行顺序关键点：同步代码 → 1、4；微任务（Promise）→ 3；宏任务（setTimeout）→ 2</p><p><strong>四、then 的返回值决定链式行为</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//返回普通值 → 自动包装 Promise</span></div></div><div><div><div>2</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>res</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span>    </span><span>return</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>console</span><span>.</span></span><span>log</span><span>); </span><span>//2</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>//返回 Promise → 会“等待”</span></div></div><div><div><div>9</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>11</div></div><div><span>    </span><span>return</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>(</span><span>resolve</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>12</div></div><div><span>      </span><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> </span><span>resolve</span><span>(</span><span>2</span><span>), </span><span>1000</span><span>);</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>});</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>console</span><span>.</span></span><span>log</span><span>);</span><span>//会等 1 秒 输出2</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>//常见坑：忘记 return  setTimeout 不影响 Promise 链 没有 return Promise</span></div></div><div><div><div>18</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span>()</span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>20</div></div><div><span>    </span><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>21</div></div><div><span>      </span><span>return</span><span> </span><span>123</span><span>;</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>}, </span><span>1000</span><span>);</span></div></div><div><div><div>23</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>24</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>console</span><span>.</span></span><span>log</span><span>);</span><span>//undefined</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>五、Promise 一旦确定状态不可改变</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>((</span><span>resolve</span><span>, </span><span>reject</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>resolve</span><span>(</span><span>'成功'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>  </span><span>reject</span><span>(</span><span>'失败'</span><span>);</span></div></div><div><div><div>4</div></div><div><span>});</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>p</span><span>.</span></span><span>then</span><span><span>(</span><span>console</span><span>.</span></span><span>log</span><span>);</span><span>//成功</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>Promise 状态只能：pending → fulfilled；pending → rejected；一旦确定 → 永远不可更改</p><p><strong>六、错误不会自动“传递”，需要 catch</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//不写 catch 会：报错未捕获</span></div></div><div><div><div>2</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span>()</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span>    </span><span>throw</span><span> </span><span>new</span><span> </span><span>Error</span><span>(</span><span>'错了'</span><span>);</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'不会执行'</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>//正确写法</span></div></div><div><div><div>11</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span>()</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>13</div></div><div><span>    </span><span>throw</span><span> </span><span>new</span><span> </span><span>Error</span><span>(</span><span>'错了'</span><span>);</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>.</span><span>catch</span><span><span>(</span><span>err</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>err</span><span>.</span></span><span>message</span><span>);</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>七、catch 会“吞错误”</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Promise</span><span>.</span><span>reject</span><span>(</span><span>'error'</span><span>)</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>.</span><span>catch</span><span><span>(</span><span>err</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'处理了:'</span><span><span>, </span><span>err</span><span>);</span></span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'继续执行'</span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>8</div></div><div><span>//处理了: error</span></div></div><div><div><div>9</div></div><div><span>//继续执行</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>catch 之后默认返回 resolved Promise</p><p>除非你重新 throw</p><p><strong>八、Promise.all 有“失败即终止”特性</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//直接进入 catch不等 3</span></div></div><div><div><div>2</div></div><div><span>Promise</span><span>.</span><span>all</span><span>([</span></div></div><div><div><div>3</div></div><div><span>  </span><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>1</span><span>),</span></div></div><div><div><div>4</div></div><div><span>  </span><span>Promise</span><span>.</span><span>reject</span><span>(</span><span>'error'</span><span>),</span></div></div><div><div><div>5</div></div><div><span>  </span><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>3</span><span>)</span></div></div><div><div><div>6</div></div><div><span>]);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>九、Promise 并不会取消任务</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>fetch</span><span>(</span><span>'/api'</span><span>);</span></div></div><div><div><div>2</div></div><div><span><span>p</span><span>.</span></span><span>then</span><span>(</span><span>...</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li>Promise 本身 <strong>无法取消</strong></li>
<li>即使不需要结果，网络请求仍在执行</li>
<li>解决方案：AbortController（fetch）；标志位控制</li>
</ul><p><strong>十、then 可以“链式断开”</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//正确链式</span></div></div><div><div><div>2</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>res</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span>    </span><span>return</span><span> </span><span>Promise</span><span>.</span><span>resolve</span><span><span>(</span><span>res</span><span> </span></span><span>+</span><span> </span><span>1</span><span>);</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>res</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>res</span><span>);</span></span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>});</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>//但是如果这样</span></div></div><div><div><div>11</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>res</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>13</div></div><div><span>    </span><span>Promise</span><span>.</span><span>resolve</span><span><span>(</span><span>res</span><span> </span></span><span>+</span><span> </span><span>1</span><span>); </span><span>// ❌ 没 return</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>console</span><span>.</span></span><span>log</span><span>);</span><span>//undefined</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>十一、微任务优先级高于宏任务</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>setTimeout</span><span>(() </span><span>=&gt;</span><span><span> </span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'timeout'</span><span>), </span><span>0</span><span>);</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span>().</span><span>then</span><span>(() </span><span>=&gt;</span><span><span> </span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'promise'</span><span>));</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'sync'</span><span>);</span></div></div><div><div><div>6</div></div><div><span>//sync promise  timeout</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>十二、Promise 不会阻塞线程</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span>().</span><span>then</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>while</span><span>(</span><span>true</span><span>) {}</span></div></div><div><div><div>3</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>会卡死主线程，但不是 Promise 阻塞，而是代码阻塞。</p><p><strong>十三、finally 不改变结果</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Promise</span><span>.</span><span>resolve</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>.</span><span>finally</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'finally'</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>.</span><span>then</span><span><span>(</span><span>console</span><span>.</span></span><span>log</span><span>);</span><span>//finally  1</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>finally 不会改变值，除非 throw error</p></section>
<section><h2>Promise的应用<a href="#promise的应用"><span>#</span></a></h2><p>把“异步任务”变成“可链式、可组合、可统一处理”的结构</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!</span><span>doctype</span><span> </span><span>html</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>html</span><span> </span><span>lang</span><span>=</span><span>"en"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>head</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>meta</span><span> </span><span>charset</span><span>=</span><span>"UTF-8"</span><span> /&gt;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>&lt;</span><span>title</span><span>&gt;Document&lt;/</span><span>title</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span>      </span><span>*</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>padding: </span><span>0</span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>margin: </span><span>0</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>      </span><span>.centen</span><span> {</span></div></div><div><div><div>12</div></div><div><span><span>        </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>justify-content: </span><span>center</span><span>; </span><span>/* 水平居中 */</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>align-items: </span><span>center</span><span>; </span><span>/* 垂直居中 */</span></div></div><div><div><div>15</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>18</div></div><div><span><span>  </span></span><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"centen"</span><span>&gt;</span></div></div><div><div><div>20</div></div><div><span><span>      </span></span><span>&lt;</span><span>img</span></div></div><div><div><div>21</div></div><div><span>        </span><span>src</span><span>=</span><span>"https://img1.sycdn.imooc.com/9fa08f6a0833cfc016000682.jpg"</span></div></div><div><div><div>22</div></div><div><span>        </span><span>alt</span><span>=</span><span>""</span></div></div><div><div><div>23</div></div><div><span>        </span><span>id</span><span>=</span><span>"img"</span></div></div><div><div><div>24</div></div><div><span><span>      </span></span><span>/&gt;</span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>28</div></div><div><span>      </span><span>const</span><span> </span><span>loadimg</span><span> </span><span>=</span><span><span> (</span><span>url</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>29</div></div><div><span>        </span><span>return</span><span> </span><span>new</span><span> </span><span>Promise</span><span><span>((</span><span>resolve</span><span>, </span><span>reject</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>30</div></div><div><span>          </span><span>const</span><span> </span><span>img</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Image</span><span>();</span></div></div><div><div><div>31</div></div><div><span><span>          </span></span><span>img</span><span>.</span><span>onload</span><span> </span><span>=</span><span> () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>32</div></div><div><span>            </span><span>resolve</span><span><span>(</span><span>img</span><span>);</span></span></div></div><div><div><div>33</div></div><div><span><span>          </span></span><span>};</span></div></div><div><div><div>34</div></div><div><span><span>          </span></span><span>img</span><span>.</span><span>onerror</span><span> </span><span>=</span><span> () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>35</div></div><div><span>            </span><span>reject</span><span>(</span><span>`图片加载失败 </span><span>${</span><span>url</span><span>}</span><span>`</span><span>);</span></div></div><div><div><div>36</div></div><div><span><span>          </span></span><span>};</span></div></div><div><div><div>37</div></div><div><span><span>          </span></span><span>img</span><span>.</span><span>src</span><span> </span><span>=</span><span><span> </span><span>url</span><span>;</span></span></div></div><div><div><div>38</div></div><div><span><span>        </span></span><span>});</span></div></div><div><div><div>39</div></div><div><span><span>      </span></span><span>};</span></div></div><div><div><div>40</div></div><div><span>      </span><span>const</span><span> </span><span>imgDom</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>'img'</span><span>);</span></div></div><div><div><div>41</div></div><div><span>      </span><span>loadimg</span><span>(</span><span>'https://img1.sycdn.imooc.com/16f88d6a092f8ae717920764.jpg'</span><span>)</span></div></div><div><div><div>42</div></div><div><span><span>        </span></span><span>.</span><span>then</span><span><span>((</span><span>data</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>43</div></div><div><span><span>          </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>data</span><span>);</span></span></div></div><div><div><div>44</div></div><div><span>          </span><span>setTimeout</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>45</div></div><div><span><span>            </span></span><span>imgDom</span><span>.</span><span>src</span><span> </span><span>=</span><span><span> </span><span>data</span><span>.</span></span><span>src</span><span>;</span></div></div><div><div><div>46</div></div><div><span><span>          </span></span><span>}, </span><span>2000</span><span>);</span></div></div><div><div><div>47</div></div><div><span><span>        </span></span><span>})</span></div></div><div><div><div>48</div></div><div><span><span>        </span></span><span>.</span><span>catch</span><span><span>((</span><span>err</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>49</div></div><div><span><span>          </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>err</span><span>);</span></span></div></div><div><div><div>50</div></div><div><span><span>        </span></span><span>});</span></div></div><div><div><div>51</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>52</div></div><div><span><span>  </span></span><span>&lt;/</span><span>body</span><span>&gt;</span></div></div><div><div><div>53</div></div><div><span>&lt;/</span><span>html</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/20261021010es6-xin-zeng-fang-fa/</id>
      <title type="text">ES6新增方法</title>
      <published>2026-10-21T08:12:18.000Z</published>
      <updated>2026-10-21T08:12:18.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/20261021010es6-xin-zeng-fang-fa/"/>
      <summary type="text">本文主要学习ES6新增方法</summary>
      <content type="html"><![CDATA[<section><h1>字符串相关<a href="#字符串相关"><span>#</span></a></h1><section><h2>字符串的includes()<a href="#字符串的includes"><span>#</span></a></h2><p>是否包含某些字符</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//基本用法 判断的组合</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'abc'</span><span>.</span><span>includes</span><span>(</span><span>'a'</span><span>)); </span><span>//true</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'abc'</span><span>.</span><span>includes</span><span>(</span><span>'ab'</span><span>)); </span><span>//true</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'abc'</span><span>.</span><span>includes</span><span>(</span><span>'ac'</span><span>)); </span><span>//false</span></div></div><div><div><div>5</div></div><div><span>//第二个参数，表示开始搜索的位置</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'abc'</span><span>.</span><span>includes</span><span>(</span><span>'a'</span><span>, </span><span>1</span><span>)); </span><span>//false</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>应用：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>url</span><span> </span></span><span>=</span><span> </span><span>'https://www.imooc.com/course/list'</span><span>;</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>addURLParam</span><span> </span><span>=</span><span><span> (</span><span>url</span><span>, </span><span>name</span><span>, </span><span>value</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>url</span><span> </span><span>+=</span><span><span> </span><span>url</span><span>.</span></span><span>includes</span><span>(</span><span>'?'</span><span>) </span><span>?</span><span> </span><span>'&amp;'</span><span> </span><span>:</span><span> </span><span>'?'</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>url</span><span> </span><span>+=</span><span> </span><span>`</span><span>${</span><span>name</span><span>}</span><span>= </span><span>${</span><span>value</span><span>}</span><span>`</span><span>;</span></div></div><div><div><div>5</div></div><div><span>  </span><span>return</span><span><span> </span><span>url</span><span>;</span></span></div></div><div><div><div>6</div></div><div><span>};</span></div></div><div><div><div>7</div></div><div><span><span>url</span><span> </span></span><span>=</span><span> </span><span>addURLParam</span><span><span>(</span><span>url</span><span>, </span></span><span>'c'</span><span>, </span><span>'fe'</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>url</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>padStart()和padEnd()<a href="#padstart和padend"><span>#</span></a></h2><p>padStart()<code>和</code>padEnd()` 是 ES2017（ES8）新增的字符串方法，用来<strong>补齐字符串长度</strong>。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//padStart()语法</span></div></div><div><div><div>2</div></div><div><span>//targetLength：补齐后的总长度</span></div></div><div><div><div>3</div></div><div><span>//padString：用什么字符补，默认是空格 " "。</span></div></div><div><div><div>4</div></div><div><span><span>str</span><span>.</span></span><span>padStart</span><span><span>(</span><span>targetLength</span><span>, </span><span>padString</span><span>)</span></span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>//基本语法padStart</span></div></div><div><div><div>7</div></div><div><span>'5'</span><span>.</span><span>padStart</span><span>(</span><span>3</span><span>, </span><span>'0'</span><span>);</span><span>//‘005’</span></div></div><div><div><div>8</div></div><div><span>'123'</span><span>.</span><span>padStart</span><span>(</span><span>6</span><span>, </span><span>'*'</span><span>);</span><span>//'***123'</span></div></div><div><div><div>9</div></div><div><span>'hello'</span><span>.</span><span>padStart</span><span>(</span><span>3</span><span>, </span><span>'*'</span><span>);</span><span>//'hello'长度够了，不补</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>//基本语法padEnd()</span></div></div><div><div><div>12</div></div><div><span>'5'</span><span>.</span><span>padEnd</span><span>(</span><span>3</span><span>, </span><span>'0'</span><span>);</span><span>//'500'</span></div></div><div><div><div>13</div></div><div><span>'abc'</span><span>.</span><span>padEnd</span><span>(</span><span>6</span><span>, </span><span>'*'</span><span>);</span><span>//'abc***'</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意情况：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//长度够了，不补</span></div></div><div><div><div>2</div></div><div><span>'hello'</span><span>.</span><span>padStart</span><span>(</span><span>3</span><span>, </span><span>'*'</span><span>);</span><span>//'hello'</span></div></div><div><div><div>3</div></div><div><span>//省略第2参数，默认补空格</span></div></div><div><div><div>4</div></div><div><span>'hi'</span><span>.</span><span>padStart</span><span>(</span><span>5</span><span>);</span><span>//'   hi'</span></div></div><div><div><div>5</div></div><div><span>//超过的，原字符串不会变，只会截取填充的</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'abc'</span><span>.</span><span>padStart</span><span>(</span><span>10</span><span>, </span><span>'0123456789'</span><span>));</span><span>//0123456abc</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>应用</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//时间格式化</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>h</span><span> </span><span>=</span><span> </span><span>'9'</span><span>.</span><span>padStart</span><span>(</span><span>2</span><span>, </span><span>'0'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>m</span><span> </span><span>=</span><span> </span><span>'5'</span><span>.</span><span>padStart</span><span>(</span><span>2</span><span>, </span><span>'0'</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>`</span><span>${</span><span>h</span><span>}</span><span>:</span><span>${</span><span>m</span><span>}</span><span>`</span><span>);</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>//日期</span></div></div><div><div><div>7</div></div><div><span>const</span><span> </span><span>month</span><span> </span><span>=</span><span> </span><span>String</span><span><span>(</span><span>date</span><span>.</span></span><span>getMonth</span><span>() </span><span>+</span><span> </span><span>1</span><span>).</span><span>padStart</span><span>(</span><span>2</span><span>, </span><span>'0'</span><span>);</span></div></div><div><div><div>8</div></div><div><span>const</span><span> </span><span>day</span><span> </span><span>=</span><span> </span><span>String</span><span><span>(</span><span>date</span><span>.</span></span><span>getDate</span><span>()).</span><span>padStart</span><span>(</span><span>2</span><span>, </span><span>'0'</span><span>);</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>//隐藏手机号</span></div></div><div><div><div>11</div></div><div><span>'1234'</span><span>.</span><span>padStart</span><span>(</span><span>11</span><span>, </span><span>'*'</span><span>);</span><span>//*******1234</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>//生成固定宽度字符串</span></div></div><div><div><div>14</div></div><div><span>'VIP'</span><span>.</span><span>padEnd</span><span>(</span><span>10</span><span>, </span><span>'-'</span><span>);</span><span>//'VIP-------'</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>trimStart()和trimEnd()<a href="#trimstart和trimend"><span>#</span></a></h2><p>trimStart()<code>和</code>trimEnd() 是 ES2019（ES10）新增的字符串方法，用来<strong>删除字符串两端的空白字符</strong>中的一端。</p><p>trimStart()：删除<strong>开头</strong>的空白字符。</p><p><code>trimEnd()</code>：删除<strong>结尾</strong>的空白字符。</p><p>空白字符包括：空格 <code>" "</code>；制表符 <code>\t</code>；换行符 <code>\n</code>；回车符 <code>\r</code>；其他 Unicode 空白字符</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>str</span><span> </span><span>=</span><span> </span><span>'   hello'</span><span>;</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>str</span><span>.</span></span><span>trimStart</span><span>());</span></div></div><div><div><div>3</div></div><div><span>//制表符</span></div></div><div><div><div>4</div></div><div><span>'</span><span>\t\t</span><span>hello'</span><span>.</span><span>trimStart</span><span>();</span><span>//'hello'</span></div></div><div><div><div>5</div></div><div><span>//换行符</span></div></div><div><div><div>6</div></div><div><span>'</span><span>\n\n</span><span>hello'</span><span>.</span><span>trimStart</span><span>();</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>const</span><span> </span><span>str</span><span> </span><span>=</span><span> </span><span>'hello   '</span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>str</span><span>.</span></span><span>trimEnd</span><span>());</span></div></div><div><div><div>10</div></div><div><span>//中间的空格不会删除</span></div></div><div><div><div>11</div></div><div><span>'he   llo'</span><span>.</span><span>trim</span><span>();</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>//trim()两端都删除。</span></div></div><div><div><div>14</div></div><div><span>'   hello   '</span><span>.</span><span>trim</span><span>();</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>//用户输入处理</span></div></div><div><div><div>17</div></div><div><span>const</span><span> </span><span>username</span><span> </span><span>=</span><span><span> </span><span>input</span><span>.</span></span><span>value</span><span>.</span><span>trim</span><span>();</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>//字符串不会被修改</span></div></div><div><div><div>20</div></div><div><span>const</span><span> </span><span>str</span><span> </span><span>=</span><span> </span><span>'  hello'</span><span>;</span></div></div><div><div><div>21</div></div><div><span><span>str</span><span>.</span></span><span>trimStart</span><span>();</span></div></div><div><div><div>22</div></div><div><span>const</span><span> </span><span>newStr</span><span> </span><span>=</span><span><span> </span><span>str</span><span>.</span></span><span>trimStart</span><span>();</span></div></div><div><div><div>23</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>str</span><span>);</span></span></div></div><div><div><div>24</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>newStr</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>
<section><h1>数组相关<a href="#数组相关"><span>#</span></a></h1><section><h2>数组的includes()<a href="#数组的includes"><span>#</span></a></h2><p><code>includes()</code> 是 ES2016（ES7）新增的数组方法，用来<strong>判断数组中是否包含某个元素</strong>。</p><p>返回值：true、false</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//searchElement：要查找的元素。</span></div></div><div><div><div>2</div></div><div><span>//fromIndex：从哪个索引开始查找（可选）</span></div></div><div><div><div>3</div></div><div><span><span>arr</span><span>.</span></span><span>includes</span><span><span>(</span><span>searchElement</span><span>, </span><span>fromIndex</span><span>)</span></span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>//基本使用</span></div></div><div><div><div>6</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>];</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>.</span></span><span>includes</span><span>(</span><span>2</span><span>));</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>.</span></span><span>includes</span><span>(</span><span>5</span><span>));</span><span>//false</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>//第二个参数 fromIndex</span></div></div><div><div><div>11</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>2</span><span>];</span></div></div><div><div><div>12</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>.</span></span><span>includes</span><span>(</span><span>2</span><span>, </span><span>2</span><span>));</span><span>//true</span></div></div><div><div><div>13</div></div><div><span>//支持负数索引</span></div></div><div><div><div>14</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>];</span></div></div><div><div><div>15</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>.</span></span><span>includes</span><span>(</span><span>3</span><span>, </span><span>-</span><span>2</span><span>));</span><span>//true 往后倒数</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>//和 indexOf() 的区别（重点）</span></div></div><div><div><div>18</div></div><div><span><span>arr</span><span>.</span></span><span>indexOf</span><span>(</span><span>2</span><span>) </span><span>!==</span><span> </span><span>-</span><span>1</span></div></div><div><div><div>19</div></div><div><span><span>arr</span><span>.</span></span><span>includes</span><span>(</span><span>2</span><span>)</span><span>//更直观</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>//最大的区别：NaN</span></div></div><div><div><div>22</div></div><div><span>[</span><span>1</span><span>, </span><span>NaN</span><span>].</span><span>indexOf</span><span>(</span><span>NaN</span><span>);</span><span>//-1找不到。</span></div></div><div><div><div>23</div></div><div><span>[</span><span>1</span><span>, </span><span>NaN</span><span>].</span><span>includes</span><span>(</span><span>NaN</span><span>);</span><span>//true</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span>//对象比较</span></div></div><div><div><div>26</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> { </span><span>a</span><span>:</span><span> </span><span>1</span><span> };</span></div></div><div><div><div>27</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span><span> [</span><span>obj</span><span>];</span></span></div></div><div><div><div>28</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>.</span></span><span>includes</span><span><span>(</span><span>obj</span><span>));</span></span><span>//true</span></div></div><div><div><div>29</div></div><div><span><span>arr</span><span>.</span></span><span>includes</span><span>({ </span><span>a</span><span>:</span><span> </span><span>1</span><span> });</span><span>//false  对象比较的是引用地址。</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h2>Array.from()<a href="#arrayfrom"><span>#</span></a></h2><p><code>Array.from()</code> 是 ES6（ES2015）新增的静态方法，用于<strong>将类数组对象（Array-like）或可迭代对象（Iterable）转换为真正的数组</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//基本用法</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>Array</span><span>.</span></span><span>from</span><span>(</span><span>'str'</span><span>));</span><span>//[ 's', 't', 'r' ]</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// 2.哪些可以通过Array.from(转换成数组</span></div></div><div><div><div>5</div></div><div><span>// 2.1.所有可遍历的</span></div></div><div><div><div>6</div></div><div><span>// 数组、字符串、Set、Map、NodeList、arguments</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>Array</span><span>.</span></span><span>from</span><span>(</span><span>new</span><span> </span><span>Set</span><span>([</span><span>1</span><span>, </span><span>2</span><span>, </span><span>1</span><span>])));</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>([</span><span>...</span><span>new</span><span> </span><span>Set</span><span>([</span><span>1</span><span>, </span><span>2</span><span>, </span><span>1</span><span>])]);</span><span>//也是转数组更简洁</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>//2.2拥有length属性的任意对象</span></div></div><div><div><div>11</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>12</div></div><div><span>  </span><span>0</span><span>:</span><span> </span><span>'a'</span><span>,</span><span>//只有键值是数字才会转换</span></div></div><div><div><div>13</div></div><div><span>  </span><span>1</span><span>:</span><span> </span><span>'b'</span><span>,</span></div></div><div><div><div>14</div></div><div><span>  </span><span>2</span><span>:</span><span> </span><span>'c'</span><span>,</span></div></div><div><div><div>15</div></div><div><span>  </span><span>name</span><span>:</span><span>'alex'</span><span>//不转</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>length</span><span>: </span><span>3</span><span>//由这个决定数组长度</span></div></div><div><div><div>17</div></div><div><span>};</span></div></div><div><div><div>18</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span><span> </span><span>Array</span><span>.</span></span><span>from</span><span><span>(</span><span>obj</span><span>);</span></span></div></div><div><div><div>19</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>);</span></span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>//3.第二个参数</span></div></div><div><div><div>22</div></div><div><span>//作用类似于数组的map方法，用来对每个元素进行处理，将处理后的值放入返回的数组</span></div></div><div><div><div>23</div></div><div><span><span>Array</span><span>.</span></span><span>from</span><span>([</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span><span>], </span><span>item</span><span> </span></span><span>=&gt;</span><span><span> </span><span>item</span><span> </span></span><span>*</span><span> </span><span>2</span><span>);</span></div></div><div><div><div>24</div></div><div><span>//等价于</span></div></div><div><div><div>25</div></div><div><span><span>Array</span><span>.</span></span><span>from</span><span>([</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]).</span><span>map</span><span><span>(</span><span>item</span><span> </span></span><span>=&gt;</span><span><span> </span><span>item</span><span> </span></span><span>*</span><span> </span><span>2</span><span>);</span><span>//但前者效率更高，因为只遍历一次</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>//生成指定长度的数组</span></div></div><div><div><div>28</div></div><div><span><span>Array</span><span>.</span></span><span>from</span><span>({ </span><span>length</span><span>:</span><span> </span><span>5</span><span> }, () </span><span>=&gt;</span><span> </span><span>0</span><span>);</span><span>//[0, 0, 0, 0, 0]</span></div></div><div><div><div>29</div></div><div>
</div></div><div><div><div>30</div></div><div><span>//生成数字序列</span></div></div><div><div><div>31</div></div><div><span><span>Array</span><span>.</span></span><span>from</span><span>({ </span><span>length</span><span>:</span><span> </span><span>5</span><span><span> }, (</span><span>_</span><span>, </span><span>i</span><span>) </span></span><span>=&gt;</span><span><span> </span><span>i</span><span>);</span></span><span>//[0, 1, 2, 3, 4]</span></div></div><div><div><div>32</div></div><div>
</div></div><div><div><div>33</div></div><div><span>//4第三个参数，修改this指向 普通函数才能修改this</span></div></div><div><div><div>34</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {};</span></div></div><div><div><div>35</div></div><div><span><span>Array</span><span>.</span></span><span>from</span><span>(</span></div></div><div><div><div>36</div></div><div><span>  </span><span>'12'</span><span>,</span></div></div><div><div><div>37</div></div><div><span>  </span><span>function</span><span> () {</span></div></div><div><div><div>38</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>);</span></div></div><div><div><div>39</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>40</div></div><div><span><span>  </span></span><span>obj</span><span>,</span></div></div><div><div><div>41</div></div><div><span>);</span><span>//this-》obj</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h2>find()和findIndex()<a href="#find和findindex"><span>#</span></a></h2><p><code>find()</code> 和 <code>findIndex()</code> 是 ES6（ES2015）新增的数组方法，用来<strong>查找数组中满足条件的第一个元素</strong>。</p><p>find：返回第一个满足条件的<strong>元素本身</strong></p><p>findIndex：返回第一个满足条件的<strong>元素索引</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>arr</span><span>.</span></span><span>find</span><span><span>(</span><span>callback</span><span>)</span></span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>5</span><span>, </span><span>12</span><span>, </span><span>8</span><span>, </span><span>130</span><span>, </span><span>44</span><span>];</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>res</span><span> </span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>find</span><span><span>(</span><span>item</span><span> </span></span><span>=&gt;</span><span><span> </span><span>item</span><span> </span></span><span>&gt;</span><span> </span><span>10</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>res</span><span>);</span></span><span>//12</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>const</span><span> </span><span>f</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>5</span><span>, </span><span>7</span><span>, </span><span>8</span><span>, </span><span>9</span><span>, </span><span>3</span><span>].</span><span>find</span><span><span>((</span><span>value</span><span>, </span><span>index</span><span>, </span><span>arr</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>7</div></div><div><span>  </span><span>//value 值 index索引 ，arr数组</span></div></div><div><div><div>8</div></div><div><span>  </span><span>return</span><span><span> </span><span>value</span><span> </span></span><span>&gt;</span><span> </span><span>8</span><span>;</span></div></div><div><div><div>9</div></div><div><span>});</span></div></div><div><div><div>10</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>f</span><span>);</span></span><span>//9</span></div></div><div><div><div>11</div></div><div><span>const</span><span> </span><span>f</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>5</span><span>, </span><span>7</span><span>, </span><span>8</span><span>, </span><span>9</span><span>, </span><span>3</span><span>].</span><span>findIndex</span><span><span>((</span><span>value</span><span>, </span><span>index</span><span>, </span><span>arr</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>12</div></div><div><span>  </span><span>//value 值 index索引 ，arr数组</span></div></div><div><div><div>13</div></div><div><span>  </span><span>return</span><span><span> </span><span>value</span><span> </span></span><span>&gt;</span><span> </span><span>8</span><span>;</span></div></div><div><div><div>14</div></div><div><span>});</span></div></div><div><div><div>15</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>f</span><span>);</span></span><span>//4</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>//第三个参数，修改this指向 普通函数才能修改this</span></div></div><div><div><div>18</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {};</span></div></div><div><div><div>19</div></div><div><span>const</span><span> </span><span>f</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>5</span><span>, </span><span>7</span><span>, </span><span>8</span><span>, </span><span>9</span><span>, </span><span>3</span><span>].</span><span>findIndex</span><span>(</span><span>function</span><span><span> (</span><span>value</span><span>, </span><span>index</span><span>, </span><span>arr</span><span>) {</span></span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>);</span></div></div><div><div><div>21</div></div><div><span><span>}, </span><span>obj</span><span>);</span></span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>//应用</span></div></div><div><div><div>24</div></div><div><span>//find 查对象</span></div></div><div><div><div>25</div></div><div><span>const</span><span> </span><span>users</span><span> </span><span>=</span><span> [</span></div></div><div><div><div>26</div></div><div><span><span>  </span></span><span>{ </span><span>id</span><span>:</span><span> </span><span>1</span><span>, </span><span>name</span><span>:</span><span> </span><span>'A'</span><span> },</span></div></div><div><div><div>27</div></div><div><span><span>  </span></span><span>{ </span><span>id</span><span>:</span><span> </span><span>2</span><span>, </span><span>name</span><span>:</span><span> </span><span>'B'</span><span> }</span></div></div><div><div><div>28</div></div><div><span>];</span></div></div><div><div><div>29</div></div><div><span>const</span><span> </span><span>user</span><span> </span><span>=</span><span><span> </span><span>users</span><span>.</span></span><span>find</span><span><span>(</span><span>u</span><span> </span></span><span>=&gt;</span><span><span> </span><span>u</span><span>.</span></span><span>id</span><span> </span><span>===</span><span> </span><span>2</span><span>);</span></div></div><div><div><div>30</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>user</span><span>);</span></span><span>//{ id: 2, name: 'B' }</span></div></div><div><div><div>31</div></div><div><span>//findIndex 查位置</span></div></div><div><div><div>32</div></div><div><span>const</span><span> </span><span>index</span><span> </span><span>=</span><span><span> </span><span>users</span><span>.</span></span><span>findIndex</span><span><span>(</span><span>u</span><span> </span></span><span>=&gt;</span><span><span> </span><span>u</span><span>.</span></span><span>id</span><span> </span><span>===</span><span> </span><span>2</span><span>);</span></div></div><div><div><div>33</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>index</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>

<table><thead><tr><th>对比</th><th><code>indexOf()</code></th><th><code>findIndex()</code></th></tr></thead><tbody><tr><td>查找类型</td><td>基本类型</td><td>任意条件</td></tr><tr><td>是否支持对象</td><td>❌</td><td>✅</td></tr><tr><td>是否支持函数判断</td><td>❌</td><td>✅</td></tr><tr><td>返回值</td><td>索引</td><td>索引</td></tr></tbody></table></section></section>
<section><h1>对象相关<a href="#对象相关"><span>#</span></a></h1><section><h2>Object.assign()<a href="#objectassign"><span>#</span></a></h2><p><code>Object.assign()</code> 用于把一个或多个源对象的属性“浅拷贝”到目标对象上。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//基本用法，会修改原对象</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>obj1</span><span> </span><span>=</span><span> { </span><span>a</span><span>:</span><span> </span><span>1</span><span> };</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>obj2</span><span> </span><span>=</span><span> { </span><span>b</span><span>:</span><span> </span><span>2</span><span> };</span></div></div><div><div><div>4</div></div><div><span>const</span><span> </span><span>result</span><span> </span><span>=</span><span><span> </span><span>Object</span><span>.</span></span><span>assign</span><span><span>(</span><span>obj1</span><span>, </span><span>obj2</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>);</span></span><span>//{ a: 1, b: 2 }</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj1</span><span>);</span></span><span>//{ a: 1, b: 2 }</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>//避免污染原对象</span></div></div><div><div><div>9</div></div><div><span>const</span><span> </span><span>result</span><span> </span><span>=</span><span><span> </span><span>Object</span><span>.</span></span><span>assign</span><span><span>({}, </span><span>obj1</span><span>, </span><span>obj2</span><span>);</span></span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>//浅拷贝</span></div></div><div><div><div>12</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>13</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>14</div></div><div><span>  </span><span>b</span><span>:</span><span> { </span><span>c</span><span>:</span><span> </span><span>2</span><span> }</span></div></div><div><div><div>15</div></div><div><span>};</span></div></div><div><div><div>16</div></div><div><span>const</span><span> </span><span>copy</span><span> </span><span>=</span><span><span> </span><span>Object</span><span>.</span></span><span>assign</span><span><span>({}, </span><span>obj</span><span>);</span></span></div></div><div><div><div>17</div></div><div><span><span>copy</span><span>.</span></span><span>b</span><span>.</span><span>c</span><span> </span><span>=</span><span> </span><span>999</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj</span><span>.</span></span><span>b</span><span>.</span><span>c</span><span>);</span><span>//999</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>//数组也可以用，因为数组本质也是对象（key 是索引）不常用</span></div></div><div><div><div>21</div></div><div><span>const</span><span> </span><span>arr1</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>];</span></div></div><div><div><div>22</div></div><div><span>const</span><span> </span><span>arr2</span><span> </span><span>=</span><span> [</span><span>3</span><span>, </span><span>4</span><span>];</span></div></div><div><div><div>23</div></div><div><span><span>Object</span><span>.</span></span><span>assign</span><span><span>(</span><span>arr1</span><span>, </span><span>arr2</span><span>);</span></span></div></div><div><div><div>24</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr1</span><span>);</span></span><span>//[3, 4]与本意不符</span></div></div><div><div><div>25</div></div><div>
</div></div><div><div><div>26</div></div><div><span>//应用</span></div></div><div><div><div>27</div></div><div><span>const</span><span> </span><span>logUser</span><span> </span><span>=</span><span><span> (</span><span>UserOption</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>28</div></div><div><span>  </span><span>//默认配置</span></div></div><div><div><div>29</div></div><div><span>  </span><span>const</span><span> </span><span>DEFAULTS</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>30</div></div><div><span>    </span><span>name</span><span>:</span><span> </span><span>'zhangsan'</span><span>,</span></div></div><div><div><div>31</div></div><div><span>    </span><span>age</span><span>:</span><span> </span><span>0</span><span>,</span></div></div><div><div><div>32</div></div><div><span><span>  </span></span><span>};</span></div></div><div><div><div>33</div></div><div><span>  </span><span>//合并</span></div></div><div><div><div>34</div></div><div><span>  </span><span>const</span><span> </span><span>option</span><span> </span><span>=</span><span><span> </span><span>Object</span><span>.</span></span><span>assign</span><span>({}, </span><span>DEFAULTS</span><span><span>, </span><span>UserOption</span><span>);</span></span></div></div><div><div><div>35</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>option</span><span>);</span></span></div></div><div><div><div>36</div></div><div><span>};</span></div></div><div><div><div>37</div></div><div><span>logUser</span><span>({ </span><span>name</span><span>:</span><span> </span><span>'alex'</span><span> });</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h2>Object.keys()、Object.values()和Object.entries()<a href="#objectkeysobjectvalues和objectentries"><span>#</span></a></h2><p>这三个方法是 ES8（ES2017）里非常重要的一组 <strong>对象遍历工具</strong>，本质都是把对象“转成数组再处理”。</p><p>区别：</p>

<table><thead><tr><th>方法</th><th>返回什么</th></tr></thead><tbody><tr><td><code>Object.keys()</code></td><td>键（key）数组</td></tr><tr><td><code>Object.values()</code></td><td>值（value）数组</td></tr><tr><td><code>Object.entries()</code></td><td>键值对数组</td></tr></tbody></table><p><strong>Object.keys()</strong></p><p>返回对象所有“键”的数组</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const obj = {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>name: 'Alice',</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>age: 18</span></div></div><div><div><div>4</div></div><div><span>};</span></div></div><div><div><div>5</div></div><div><span>console.log(Object.keys(obj));//['name', 'age']</span></div></div><div><div><div>6</div></div><div><span>//遍历 key</span></div></div><div><div><div>7</div></div><div><span>for (const key of Object.keys(obj)) {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>console.log(key, obj[key]);</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div><span>//判断对象是否为空</span></div></div><div><div><div>11</div></div><div><span>Object.keys({}).length === 0;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>Object.values()</strong></p><p>返回对象所有“值”的数组</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>'Alice'</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>age</span><span>:</span><span> </span><span>18</span></div></div><div><div><div>4</div></div><div><span>};</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>Object</span><span>.</span></span><span>values</span><span><span>(</span><span>obj</span><span>));</span></span><span>//['Alice', 18]</span></div></div><div><div><div>7</div></div><div><span>//遍历值</span></div></div><div><div><div>8</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>value</span><span> </span><span>of</span><span><span> </span><span>Object</span><span>.</span></span><span>values</span><span><span>(</span><span>obj</span><span>)) {</span></span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>value</span><span>);</span></span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div><span>//判断是否存在某个值</span></div></div><div><div><div>12</div></div><div><span><span>Object</span><span>.</span></span><span>values</span><span><span>(</span><span>obj</span><span>).</span></span><span>includes</span><span>(</span><span>'Alice'</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>Object.entries()</strong></p><p>返回“键值对数组”</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>'Alice'</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>age</span><span>:</span><span> </span><span>18</span></div></div><div><div><div>4</div></div><div><span>};</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>Object</span><span>.</span></span><span>entries</span><span><span>(</span><span>obj</span><span>));</span></span></div></div><div><div><div>6</div></div><div><span>//输出</span></div></div><div><div><div>7</div></div><div><span>[</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>[</span><span>'name'</span><span>, </span><span>'Alice'</span><span>],</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>[</span><span>'age'</span><span>, </span><span>18</span><span>]</span></div></div><div><div><div>10</div></div><div><span>]</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>//遍历对象（推荐写法）</span></div></div><div><div><div>13</div></div><div><span>for</span><span> (</span><span>const</span><span> [</span><span>key</span><span>, </span><span>value</span><span>] </span><span>of</span><span><span> </span><span>Object</span><span>.</span></span><span>entries</span><span><span>(</span><span>obj</span><span>)) {</span></span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>key</span><span>, </span><span>value</span><span>);</span></span></div></div><div><div><div>15</div></div><div><span>}</span></div></div><div><div><div>16</div></div><div><span>//转 Map</span></div></div><div><div><div>17</div></div><div><span>const</span><span> </span><span>map</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span><span>(</span><span>Object</span><span>.</span></span><span>entries</span><span><span>(</span><span>obj</span><span>));</span></span></div></div><div><div><div>18</div></div><div><span>//对象转数组处理</span></div></div><div><div><div>19</div></div><div><span><span>Object</span><span>.</span></span><span>entries</span><span><span>(</span><span>obj</span><span>).</span></span><span>map</span><span><span>(([</span><span>k</span><span>, </span><span>v</span><span>]) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>k</span><span>, </span><span>v</span><span>);</span></span></div></div><div><div><div>21</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102109es6-bian-li-qi-yu-forof-xun-huan/</id>
      <title type="text">ES6遍历器与for…of循环</title>
      <published>2026-10-21T07:59:18.000Z</published>
      <updated>2026-10-21T07:59:18.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102109es6-bian-li-qi-yu-forof-xun-huan/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>Iterator 是什么<a href="#iterator-是什么"><span>#</span></a></h1><ul>
<li><code>Iterator（迭代器）</code> 是 JavaScript 中一个<strong>统一遍历数据结构的机制</strong>，核心作用一句话：让不同的数据结构都能用同一种方式逐个访问元素</li>
</ul><p><strong>Iterator的作用</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//遍历器 遍历；Iterator就是用来遍历</span></div></div><div><div><div>2</div></div><div><span>for</span><span> (</span><span>let</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>1</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span> </span><span>5</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>3</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>i</span><span>);</span></span></div></div><div><div><div>4</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span><span>      </span></span><span>[</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>].</span><span>forEach</span><span><span>((</span><span>value</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>value</span><span>);</span></span></div></div><div><div><div>7</div></div><div><span><span>      </span></span><span>});</span></div></div><div><div><div>8</div></div><div><span>      </span><span>new</span><span> </span><span>Set</span><span>([</span><span>11</span><span>, </span><span>12</span><span>, </span><span>13</span><span>]).</span><span>forEach</span><span><span>((</span><span>value</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>value</span><span>);</span></span></div></div><div><div><div>10</div></div><div><span><span>      </span></span><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>寻找Iterator</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//2025年才新增的全局构造函数，有些旧版浏览器不支持，打印出来就报错</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>Iterator</span><span>);</span></span><span>//ƒ Iterator() { [native code] }</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>//通过数组的Prototype可以看到 Symbol(Symbol.iterator)</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>([</span><span>1</span><span>, </span><span>2</span><span>]);</span></div></div><div><div><div>6</div></div><div><span>//调用执行</span></div></div><div><div><div>7</div></div><div><span><span> </span></span><span>console</span><span>.</span><span>log</span><span>([</span><span>1</span><span>, </span><span>2</span><span><span>][</span><span>Symbol</span><span>.</span></span><span>iterator</span><span>]());</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>使用Iterator</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>it</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span><span>][</span><span>Symbol</span><span>.</span></span><span>iterator</span><span>]();</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>it</span><span>.</span></span><span>next</span><span>()); </span><span>//{value: 1, done: false}</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>it</span><span>.</span></span><span>next</span><span>()); </span><span>//{value: 2, done: false}</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>it</span><span>.</span></span><span>next</span><span>()); </span><span>//{value: undefined, done: true}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>//it 可遍历对象</span></div></div><div><div><div>7</div></div><div><span>//Symbol.iterator 可遍历对象的生成方法</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>Iterator 解惑<a href="#iterator-解惑"><span>#</span></a></h1><p>为什么需要Iterator 遍历器</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//数组可以用for或者佛forEach方法</span></div></div><div><div><div>2</div></div><div><span>//对象可以用for in</span></div></div><div><div><div>3</div></div><div><span>//Iterator 并不是为数组和对象遍历，而是统一遍历方式</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>([][</span><span>Symbol</span><span>.</span></span><span>iterator</span><span>]()); </span><span>//Array Iterator {}  天生具备</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>({}[</span><span>Symbol</span><span>.</span></span><span>iterator</span><span>]); </span><span>//undefined 不具备</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>如何更方便的使用Iterator</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// Symbol.iterator-&gt;it-&gt;next()</span></div></div><div><div><div>2</div></div><div><span>//我们一般不会直接使用Iteratr去遍历-&gt;封装成一个函数</span></div></div><div><div><div>3</div></div><div><span>// for..of</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>for…of 的用法<a href="#forof-的用法"><span>#</span></a></h1><ul>
<li>
<p><code>for...of</code> 是 ES6 新增的循环语法，用来<strong>遍历可迭代对象（Iterable）中的值</strong>。</p>
</li>
<li>
<p><code>for...of</code> 用来遍历可迭代对象的value值，它的底层就是不断调用 Iterator 的 <code>next()</code> 方法。</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//基本语法</span></div></div><div><div><div>2</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>item</span><span> </span><span>of</span><span><span> </span><span>iterable</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>  </span><span>// 使用 item</span></div></div><div><div><div>4</div></div><div><span>  </span><span>//item每次遍历得到的值</span></div></div><div><div><div>5</div></div><div><span>  </span><span>//iterable可迭代对象</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>//遍历数组，没有索引</span></div></div><div><div><div>9</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>];</span></div></div><div><div><div>10</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>item</span><span> </span><span>of</span><span><span> </span><span>arr</span><span>) {</span></span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>item</span><span>);</span></span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>//遍历字符串</span></div></div><div><div><div>15</div></div><div><span>const</span><span> </span><span>str</span><span> </span><span>=</span><span> </span><span>'hello'</span><span>;</span></div></div><div><div><div>16</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>ch</span><span> </span><span>of</span><span><span> </span><span>str</span><span>) {</span></span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>ch</span><span>);</span></span></div></div><div><div><div>18</div></div><div><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>//遍历 Set</span></div></div><div><div><div>21</div></div><div><span>const</span><span> </span><span>set</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span>([</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]);</span></div></div><div><div><div>22</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>item</span><span> </span><span>of</span><span><span> </span><span>set</span><span>) {</span></span></div></div><div><div><div>23</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>item</span><span>);</span></span></div></div><div><div><div>24</div></div><div><span>}</span></div></div><div><div><div>25</div></div><div>
</div></div><div><div><div>26</div></div><div><span>//遍历 Map</span></div></div><div><div><div>27</div></div><div><span>const</span><span> </span><span>map</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>([</span></div></div><div><div><div>28</div></div><div><span><span>  </span></span><span>[</span><span>'name'</span><span>, </span><span>'Alice'</span><span>],</span></div></div><div><div><div>29</div></div><div><span><span>  </span></span><span>[</span><span>'age'</span><span>, </span><span>18</span><span>]</span></div></div><div><div><div>30</div></div><div><span>]);</span></div></div><div><div><div>31</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>item</span><span> </span><span>of</span><span><span> </span><span>map</span><span>) {</span></span></div></div><div><div><div>32</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>item</span><span>);</span></span></div></div><div><div><div>33</div></div><div><span>}</span></div></div><div><div><div>34</div></div><div><span>for</span><span> (</span><span>const</span><span> [</span><span>key</span><span>, </span><span>value</span><span>] </span><span>of</span><span><span> </span><span>map</span><span>) {</span></span></div></div><div><div><div>35</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>key</span><span>, </span><span>value</span><span>);</span></span></div></div><div><div><div>36</div></div><div><span>}</span></div></div><div><div><div>37</div></div><div>
</div></div><div><div><div>38</div></div><div><span>//遍历 DOM 集合</span></div></div><div><div><div>39</div></div><div><span>const</span><span> </span><span>ps</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelectorAll</span><span>(</span><span>'p'</span><span>);</span></div></div><div><div><div>40</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>p</span><span> </span><span>of</span><span><span> </span><span>ps</span><span>) {</span></span></div></div><div><div><div>41</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>p</span><span>);</span></span></div></div><div><div><div>42</div></div><div><span>}</span></div></div><div><div><div>43</div></div><div>
</div></div><div><div><div>44</div></div><div><span>//不能直接遍历 Object</span></div></div><div><div><div>45</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>46</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>'Alice'</span><span>,</span></div></div><div><div><div>47</div></div><div><span>  </span><span>age</span><span>:</span><span> </span><span>18</span></div></div><div><div><div>48</div></div><div><span>};</span></div></div><div><div><div>49</div></div><div>
</div></div><div><div><div>50</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>item</span><span> </span><span>of</span><span><span> </span><span>obj</span><span>) {}</span></span><span>//报错</span></div></div><div><div><div>51</div></div><div><span>//遍历键</span></div></div><div><div><div>52</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>key</span><span> </span><span>of</span><span><span> </span><span>Object</span><span>.</span></span><span>keys</span><span><span>(</span><span>obj</span><span>)) {</span></span></div></div><div><div><div>53</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>key</span><span>);</span></span></div></div><div><div><div>54</div></div><div><span>}</span></div></div><div><div><div>55</div></div><div><span>//遍历值</span></div></div><div><div><div>56</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>value</span><span> </span><span>of</span><span><span> </span><span>Object</span><span>.</span></span><span>values</span><span><span>(</span><span>obj</span><span>)) {</span></span></div></div><div><div><div>57</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>value</span><span>);</span></span></div></div><div><div><div>58</div></div><div><span>}</span></div></div><div><div><div>59</div></div><div><span>//遍历键和值</span></div></div><div><div><div>60</div></div><div><span>for</span><span> (</span><span>const</span><span> [</span><span>key</span><span>, </span><span>value</span><span>] </span><span>of</span><span><span> </span><span>Object</span><span>.</span></span><span>entries</span><span><span>(</span><span>obj</span><span>)) {</span></span></div></div><div><div><div>61</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>key</span><span>, </span><span>value</span><span>);</span></span></div></div><div><div><div>62</div></div><div><span>}</span></div></div><div><div><div>63</div></div><div>
</div></div><div><div><div>64</div></div><div><span>//可以配合 break、continue forEach没有break、continue，这是区别</span></div></div><div><div><div>65</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>n</span><span> </span><span>of</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>, </span><span>5</span><span>]) {</span></div></div><div><div><div>66</div></div><div><span>  </span><span>if</span><span><span> (</span><span>n</span><span> </span></span><span>===</span><span> </span><span>3</span><span>) </span><span>break</span><span>;</span></div></div><div><div><div>67</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>n</span><span>);</span></span></div></div><div><div><div>68</div></div><div><span>}</span></div></div><div><div><div>69</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>n</span><span> </span><span>of</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>]) {</span></div></div><div><div><div>70</div></div><div><span>  </span><span>if</span><span><span> (</span><span>n</span><span> </span></span><span>%</span><span> </span><span>2</span><span> </span><span>===</span><span> </span><span>0</span><span>) </span><span>continue</span><span>;</span></div></div><div><div><div>71</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>n</span><span>);</span></span></div></div><div><div><div>72</div></div><div><span>}</span></div></div><div><div><div>73</div></div><div><span>//数组遍历时拿索引怎么办for...of 默认只有值，没有索引。</span></div></div><div><div><div>74</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];</span></div></div><div><div><div>75</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>arr</span><span>.</span></span><span>keys</span><span>());</span></div></div><div><div><div>76</div></div><div><span>      </span><span>for</span><span> (</span><span>const</span><span> </span><span>key</span><span> </span><span>of</span><span><span> </span><span>arr</span><span>.</span></span><span>keys</span><span>()) {</span></div></div><div><div><div>77</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>key</span><span>);</span></span></div></div><div><div><div>78</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>79</div></div><div><span>      </span><span>for</span><span> (</span><span>const</span><span> </span><span>value</span><span> </span><span>of</span><span><span> </span><span>arr</span><span>) {</span></span></div></div><div><div><div>80</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>value</span><span>);</span></span></div></div><div><div><div>81</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>82</div></div><div><span>//方法 1：entries() 既想得带value和key</span></div></div><div><div><div>83</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>'a'</span><span>, </span><span>'b'</span><span>, </span><span>'c'</span><span>];</span></div></div><div><div><div>84</div></div><div><span>for</span><span> (</span><span>const</span><span> [</span><span>index</span><span>, </span><span>value</span><span>] </span><span>of</span><span><span> </span><span>arr</span><span>.</span></span><span>entries</span><span>()) {</span></div></div><div><div><div>85</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>index</span><span>, </span><span>value</span><span>);</span></span></div></div><div><div><div>86</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
</li>
</ul></section>
<section><h1>for…of、for…in、forEach、for、while区别<a href="#forofforinforeachforwhile区别"><span>#</span></a></h1><p><strong>一、核心区别表</strong></p>

<table><thead><tr><th>特性</th><th><code>for</code></th><th><code>while</code></th><th><code>for...of</code></th><th><code>for...in</code></th><th><code>forEach</code></th></tr></thead><tbody><tr><td>类型</td><td>循环语句</td><td>循环语句</td><td>循环语句</td><td>循环语句</td><td>数组方法</td></tr><tr><td>遍历内容</td><td>自己控制</td><td>自己控制</td><td>值（value）</td><td>键（key）</td><td>值（value）</td></tr><tr><td>是否需要索引</td><td>自己维护</td><td>自己维护</td><td>默认没有</td><td>键本身</td><td>自带 index</td></tr><tr><td>支持数组</td><td>✅</td><td>✅</td><td>✅</td><td>⚠️ 不推荐</td><td>✅</td></tr><tr><td>支持对象 Object</td><td>✅</td><td>✅</td><td>❌</td><td>✅</td><td>❌</td></tr><tr><td>支持 Set</td><td>✅</td><td>✅</td><td>✅</td><td>❌</td><td>✅</td></tr><tr><td>支持 Map</td><td>✅</td><td>✅</td><td>✅</td><td>❌</td><td>✅</td></tr><tr><td>支持 String</td><td>✅</td><td>✅</td><td>✅</td><td>⚠️ 可用但少见</td><td>❌</td></tr><tr><td>支持 NodeList</td><td>✅</td><td>✅</td><td>✅</td><td>⚠️ 可用但少见</td><td>部分环境支持</td></tr><tr><td>支持 Generator</td><td>✅</td><td>✅</td><td>✅</td><td>❌</td><td>❌</td></tr><tr><td>支持 break</td><td>✅</td><td>✅</td><td>✅</td><td>✅</td><td>❌</td></tr><tr><td>支持 continue</td><td>✅</td><td>✅</td><td>✅</td><td>✅</td><td>❌</td></tr><tr><td>支持 return 退出函数</td><td>✅</td><td>✅</td><td>✅</td><td>✅</td><td>❌（只能退出回调）</td></tr><tr><td>支持 await</td><td>✅</td><td>✅</td><td>✅</td><td>✅</td><td>❌</td></tr><tr><td>会遍历原型链属性</td><td>自己控制</td><td>自己控制</td><td>❌</td><td>✅</td><td></td></tr><tr><td>底层依赖 Iterator</td><td>❌</td><td>❌</td><td>✅</td><td>❌</td><td>❌</td></tr></tbody></table><hr /><p><strong>二、最常见使用场景</strong></p>

<table><thead><tr><th>场景</th><th>推荐</th></tr></thead><tbody><tr><td>普通数组遍历</td><td><code>for...of</code></td></tr><tr><td>需要索引</td><td><code>for</code></td></tr><tr><td>需要中途退出</td><td><code>for</code>、<code>for...of</code></td></tr><tr><td>需要 <code>await</code></td><td><code>for...of</code></td></tr><tr><td>遍历 Object</td><td><code>for...in</code>、<code>Object.entries()</code></td></tr><tr><td>遍历 Map</td><td><code>for...of</code></td></tr><tr><td>遍历 Set</td><td><code>for...of</code></td></tr><tr><td>无限循环</td><td><code>while</code></td></tr><tr><td>简单数组遍历</td><td><code>forEach</code></td></tr></tbody></table><hr /><p><strong>三、获取的东西不一样（最容易混）</strong></p><p>假设：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>'a'</span><span>, </span><span>'b'</span><span>, </span><span>'c'</span><span>];</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>'Alice'</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>age</span><span>:</span><span> </span><span>18</span></div></div><div><div><div>5</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong><code>for</code></strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>let</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>arr</span><span>.</span></span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>i</span><span>, </span><span>arr</span><span>[</span><span>i</span><span>]);</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>//0 a</span></div></div><div><div><div>5</div></div><div><span>//1 b</span></div></div><div><div><div>6</div></div><div><span>//2 c</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong><code>for...of</code></strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>v</span><span> </span><span>of</span><span><span> </span><span>arr</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>v</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>//a</span></div></div><div><div><div>5</div></div><div><span>//b</span></div></div><div><div><div>6</div></div><div><span>//c</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong><code>for...in</code></strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>k</span><span> </span><span>in</span><span><span> </span><span>arr</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>k</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>//0</span></div></div><div><div><div>5</div></div><div><span>//1</span></div></div><div><div><div>6</div></div><div><span>//2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong><code>forEach</code></strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>arr</span><span>.</span></span><span>forEach</span><span><span>((</span><span>v</span><span>, </span><span>i</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>i</span><span>, </span><span>v</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>});</span></div></div><div><div><div>4</div></div><div><span>//0 a</span></div></div><div><div><div>5</div></div><div><span>//1 b</span></div></div><div><div><div>6</div></div><div><span>//2 c</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong><code>while</code></strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>while</span><span><span> (</span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>arr</span><span>.</span></span><span>length</span><span>) {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>arr</span><span>[</span><span>i</span><span>]);</span></span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>i</span><span>++</span><span>;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div><span>//输出;abc</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>四、为什么数组不推荐 <code>for...in</code>？</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Array</span><span>.</span><span>prototype</span><span>.</span><span>test</span><span> </span><span>=</span><span> </span><span>'hello'</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>k</span><span> </span><span>in</span><span><span> </span><span>arr</span><span>) {</span></span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>k</span><span>);</span></span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div><span>//输出：</span></div></div><div><div><div>9</div></div><div><span>//0</span></div></div><div><div><div>10</div></div><div><span>//1</span></div></div><div><div><div>11</div></div><div><span>//2</span></div></div><div><div><div>12</div></div><div><span>//test</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>因为：<code>for...in</code> 遍历的是可枚举属性，包括原型链上的属性。所以：❌不推荐遍历数组。</p><p><strong>五、实际开发怎么选？</strong></p><p>数组</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>item</span><span> </span><span>of</span><span><span> </span><span>arr</span><span>) {}</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>数组 + 索引</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>let</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>arr</span><span>.</span></span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>) {}</span></div></div><div><div><div>2</div></div><div><span>//或者：</span></div></div><div><div><div>3</div></div><div><span>for</span><span> (</span><span>const</span><span> [</span><span>i</span><span>, </span><span>item</span><span>] </span><span>of</span><span><span> </span><span>arr</span><span>.</span></span><span>entries</span><span>()) {}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>对象</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>const</span><span> [</span><span>k</span><span>, </span><span>v</span><span>] </span><span>of</span><span><span> </span><span>Object</span><span>.</span></span><span>entries</span><span><span>(</span><span>obj</span><span>)) {}</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>Map</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>const</span><span> [</span><span>k</span><span>, </span><span>v</span><span>] </span><span>of</span><span><span> </span><span>map</span><span>) {}</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>Set</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>v</span><span> </span><span>of</span><span><span> </span><span>set</span><span>) {}</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>异步循环</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>item</span><span> </span><span>of</span><span><span> </span><span>arr</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>await</span><span> </span><span>fn</span><span><span>(</span><span>item</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>记忆口诀</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>for</span><span>       —— </span><span>最灵活</span></span></div></div><div><div><div>2</div></div><div><span>while</span><span><span>     —— </span><span>条件循环</span></span></div></div><div><div><div>3</div></div><div><span>for</span><span>...</span><span>of</span><span><span>  —— </span><span>遍历值</span><span>（</span><span>Iterator</span><span>）</span></span></div></div><div><div><div>4</div></div><div><span>for</span><span>...</span><span>in</span><span><span>  —— </span><span>遍历键</span><span>（</span><span>Object</span><span>）</span></span></div></div><div><div><div>5</div></div><div><span><span>forEach</span><span>   —— </span><span>数组工具方法</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>一句话总结</strong></p><blockquote><p><strong>数组优先 <code>for...of</code>，对象优先 <code>Object.entries()</code>，需要索引用 <code>for</code>，需要异步用 <code>for...of</code>，简单遍历可以用 <code>forEach</code>。</strong></p></blockquote></section>
<section><h1>原生可遍历和非原生可遍历<a href="#原生可遍历和非原生可遍历"><span>#</span></a></h1><p>哪些对象天生（原生）支持 <code>for...of</code>，哪些对象默认不支持。</p><p>判断标准只有一个：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>typeof</span><span><span> </span><span>obj</span><span>[</span><span>Symbol</span><span>.</span></span><span>iterator</span><span>] </span><span>===</span><span> </span><span>'function'</span></div></div><div><div><div>2</div></div><div><span>//有这个方法：原生可遍历（Iterable）;没有：非原生可遍历（Non-Iterable）</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>原生可遍历对象</p>

<table><thead><tr><th>类型</th><th><code>for...of</code></th><th><code>Symbol.iterator</code></th></tr></thead><tbody><tr><td><code>Array</code></td><td>✅</td><td>有</td></tr><tr><td><code>String</code></td><td>✅</td><td>有</td></tr><tr><td><code>Set</code></td><td>✅</td><td>有</td></tr><tr><td><code>Map</code></td><td>✅</td><td>有</td></tr><tr><td><code>NodeList</code></td><td>✅</td><td>有</td></tr><tr><td><code>TypedArray</code></td><td>✅</td><td>有</td></tr><tr><td>Generator 返回对象</td><td>✅</td><td>有</td></tr><tr><td><code>arguments</code>（现代浏览器）</td><td>✅</td><td>有</td></tr></tbody></table><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//Array</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];</span></div></div><div><div><div>3</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>x</span><span> </span><span>of</span><span><span> </span><span>arr</span><span>) {</span></span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>x</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>//String</span></div></div><div><div><div>8</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>ch</span><span> </span><span>of</span><span> </span><span>'abc'</span><span>) {</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>ch</span><span>);</span></span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>//Set</span></div></div><div><div><div>13</div></div><div><span>const</span><span> </span><span>set</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span>([</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]);</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>x</span><span> </span><span>of</span><span><span> </span><span>set</span><span>) {</span></span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>x</span><span>);</span></span></div></div><div><div><div>17</div></div><div><span>}</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>//Map</span></div></div><div><div><div>20</div></div><div><span>const</span><span> </span><span>map</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>([</span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>[</span><span>'name'</span><span>, </span><span>'Alice'</span><span>],</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>[</span><span>'age'</span><span>, </span><span>18</span><span>]</span></div></div><div><div><div>23</div></div><div><span>]);</span></div></div><div><div><div>24</div></div><div><span>for</span><span> (</span><span>const</span><span> [</span><span>k</span><span>, </span><span>v</span><span>] </span><span>of</span><span><span> </span><span>map</span><span>) {</span></span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>k</span><span>, </span><span>v</span><span>);</span></span></div></div><div><div><div>26</div></div><div><span>}</span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span>//NodeList</span></div></div><div><div><div>29</div></div><div><span>const</span><span> </span><span>ps</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelectorAll</span><span>(</span><span>'p'</span><span>);</span></div></div><div><div><div>30</div></div><div>
</div></div><div><div><div>31</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>p</span><span> </span><span>of</span><span><span> </span><span>ps</span><span>) {</span></span></div></div><div><div><div>32</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>p</span><span>);</span></span></div></div><div><div><div>33</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>非原生可遍历：</p>

<table><thead><tr><th>数据类型</th><th>原生可遍历</th></tr></thead><tbody><tr><td><code>Object</code></td><td>❌</td></tr><tr><td><code>Function</code></td><td>❌</td></tr><tr><td><code>Date</code></td><td>❌</td></tr><tr><td><code>RegExp</code></td><td>❌</td></tr></tbody></table></section>
<section><h1>使用了 Iterator 的场合<a href="#使用了-iterator-的场合"><span>#</span></a></h1><p><strong>场合总结：</strong></p>

<table><thead><tr><th>场景</th><th>是否使用 Iterator</th></tr></thead><tbody><tr><td><code>for...of</code></td><td>✅</td></tr><tr><td><code>...</code> 扩展运算符</td><td>✅</td></tr><tr><td>解构赋值</td><td>✅</td></tr><tr><td><code>yield*</code></td><td>✅</td></tr><tr><td><code>Array.from()</code></td><td>✅</td></tr><tr><td><code>new Set(iterable)</code></td><td>✅</td></tr><tr><td><code>new Map(iterable)</code></td><td>✅</td></tr><tr><td><code>Promise.all()</code></td><td>✅</td></tr><tr><td><code>Promise.race()</code></td><td>✅</td></tr><tr><td><code>Promise.any()</code></td><td>✅</td></tr><tr><td><code>Promise.allSettled()</code></td><td>✅</td></tr><tr><td><code>Iterator.from()</code></td><td>✅</td></tr></tbody></table><p>特例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//数组解构赋值，原生可遍历的都可以被解构赋值</span></div></div><div><div><div>2</div></div><div><span>const</span><span>[</span><span>a</span><span>,</span><span>b</span><span>] </span><span>=</span><span> </span><span>'hi'</span></div></div><div><div><div>3</div></div><div><span>//等价于，因为字符串可以天生遍历</span></div></div><div><div><div>4</div></div><div><span>const</span><span>[</span><span>a</span><span>,</span><span>b</span><span>] </span><span>=</span><span> [</span><span>...</span><span>'hi'</span><span>]</span></div></div><div><div><div>5</div></div><div><span>//因为Set可以天生遍历</span></div></div><div><div><div>6</div></div><div><span>const</span><span>[</span><span>a</span><span>,</span><span>b</span><span>] </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span>([</span><span>3</span><span>,</span><span>2</span><span>])</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102108es6set-he-map-shu-ju-jie-gou/</id>
      <title type="text">ES6Set和Map数据结构</title>
      <published>2026-10-21T07:46:14.000Z</published>
      <updated>2026-10-21T07:46:14.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102108es6set-he-map-shu-ju-jie-gou/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>Set是什么<a href="#set是什么"><span>#</span></a></h1><p><code>Set</code> 是 ES6 引入的一种<strong>集合（Collection）类型</strong>，特点是存储唯一值，不允许重复元素。有点像数组，但会自动去重。</p><p>Set没有下标去标示每一个值，所以Set是<strong>无序</strong>的，也不<strong>能像数组那样通过下标去访问Set的成员</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>set</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span>();</span></div></div><div><div><div>2</div></div><div><span><span>set</span><span>.</span></span><span>add</span><span>(</span><span>1</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>set</span><span>.</span></span><span>add</span><span>(</span><span>2</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>set</span><span>.</span></span><span>add</span><span>(</span><span>2</span><span>);</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>set</span><span>);</span></span><span>//Set(2) { 1, 2 }</span></div></div></code></pre><div><div></div><div></div></div></figure></div><section><h2>Set实例的方法和属性<a href="#set实例的方法和属性"><span>#</span></a></h2><p><strong>常用方法</strong></p><p>add() 添加元素</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>set</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span>();</span></div></div><div><div><div>2</div></div><div><span><span>set</span><span>.</span></span><span>add</span><span>(</span><span>'Tom'</span><span>).</span><span>add</span><span>(</span><span>'Alex'</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>set</span><span>.</span></span><span>add</span><span>(</span><span>'Jerry'</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>set</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>delete() 删除元素</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>set</span><span>.</span></span><span>delete</span><span>(</span><span>'Tom'</span><span>);</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>set</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>has()判断是否存在</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>set</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span>([</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]);</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>set</span><span>.</span></span><span>has</span><span>(</span><span>2</span><span>)); </span><span>// true</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>set</span><span>.</span></span><span>has</span><span>(</span><span>4</span><span>)); </span><span>// false</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>clear()清空集合</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>set</span><span>.</span></span><span>clear</span><span>();</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>set</span><span>.</span></span><span>size</span><span>); </span><span>// 0</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>size获取元素个数</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>set</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span>([</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]);</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>set</span><span>.</span></span><span>size</span><span>); </span><span>// 3</span></div></div><div><div><div>3</div></div><div><span>//类似数组的：arr.length</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>遍历 Set获取元素值</strong></p><p>for…of</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>set</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span>([</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]);</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>item</span><span> </span><span>of</span><span><span> </span><span>set</span><span>) {</span></span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>item</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>forEach</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>set</span><span>.</span></span><span>forEach</span><span><span>(</span><span>item</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>item</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>});</span></div></div><div><div><div>4</div></div><div><span>//this指向谁，取决于外部环境，this 指向的是 外层作用域的 this</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>forEach的this指向问题</strong></p><p>以下代码中：this指向谁：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>set</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span>();</span></div></div><div><div><div>2</div></div><div><span><span>set</span><span>.</span></span><span>add</span><span>(</span><span>'Tom'</span><span>).</span><span>add</span><span>(</span><span>'Alex'</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>set</span><span>.</span></span><span>add</span><span>(</span><span>'Jerry'</span><span>);</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>set</span><span>.</span></span><span>forEach</span><span><span>((</span><span>item</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>item</span><span>);</span></span></div></div><div><div><div>7</div></div><div><span>});</span></div></div><div><div><div>8</div></div><div><span>//对象</span></div></div><div><div><div>9</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>10</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>'A'</span><span>,</span></div></div><div><div><div>11</div></div><div><span>  </span><span>run</span><span>() {</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>set</span><span>.</span><span>forEach</span><span><span>((</span><span>item</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>13</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>name</span><span>);</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>});</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>16</div></div><div><span>};</span></div></div><div><div><div>17</div></div><div><span>//class</span></div></div><div><div><div>18</div></div><div><span>class</span><span> </span><span>A</span><span> {</span></div></div><div><div><div>19</div></div><div><span>  </span><span>run</span><span>() {</span></div></div><div><div><div>20</div></div><div><span><span>    </span></span><span>set</span><span>.</span><span>forEach</span><span><span>((</span><span>item</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>21</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>);</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>});</span></div></div><div><div><div>23</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>24</div></div><div><span>}</span></div></div><div><div><div>25</div></div><div><span>//普通函数</span></div></div><div><div><div>26</div></div><div><span><span>set</span><span>.</span></span><span>forEach</span><span>(</span><span>function</span><span><span>(</span><span>item</span><span>) {</span></span></div></div><div><div><div>27</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>);</span></div></div><div><div><div>28</div></div><div><span>});</span></div></div><div><div><div>29</div></div><div><span>//普通函数，forEach第二个参数指定this</span></div></div><div><div><div>30</div></div><div><span><span>set</span><span>.</span></span><span>forEach</span><span>(</span><span>function</span><span><span>(</span><span>item</span><span>) {</span></span></div></div><div><div><div>31</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>);</span></div></div><div><div><div>32</div></div><div><span><span>}, </span><span>obj</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><ul>
<li>在浏览器普通脚本中：<code>this === window</code>（非严格模式）或 <code>undefined</code>（严格模式）</li>
<li>在对象方法中：这里 <code>this === obj</code></li>
<li>在 class 中：this === 当前 class 实例</li>
<li>换成普通函数：默认：<code>undefined</code>（严格模式），或 <code>window</code>（非严格模式）或可以通过 <code>forEach 第二个参数</code> 指定</li>
</ul><p><strong>Set 与 Array 对比</strong></p>

<table><thead><tr><th>特性</th><th>Array</th><th>Set</th></tr></thead><tbody><tr><td>允许重复</td><td>✅</td><td>❌</td></tr><tr><td>按索引访问</td><td>✅</td><td>❌</td></tr><tr><td>自动去重</td><td>❌</td><td>✅</td></tr><tr><td>长度</td><td><code>length</code></td><td><code>size</code></td></tr><tr><td>查找元素</td><td><code>includes()</code></td><td><code>has()</code></td></tr></tbody></table></section><section><h2>Set构造函数的参数<a href="#set构造函数的参数"><span>#</span></a></h2><p><code>Set</code> 构造函数的参数是一个<strong>可迭代对象（iterable）</strong>，用来初始化集合中的元素。</p><p>可以是任何<strong>可迭代对象</strong>，比如：Array（数组）、String（字符串）、Map（会取 key-value 中的 key）、Set、arguments、任何实现了 <code>Symbol.iterator</code> 的对象，如果不传参数，默认创建一个空 Set。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//数组</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>s</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span>([</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]);</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>s</span><span>); </span></span><span>// Set(3) {1, 2, 3}</span></div></div><div><div><div>4</div></div><div><span>//自动去重（核心特性）</span></div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>s</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span>([</span><span>1</span><span>, </span><span>1</span><span>, </span><span>2</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]);</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>s</span><span>); </span></span><span>// Set(3) {1, 2, 3}</span></div></div><div><div><div>7</div></div><div><span>//字符串（按字符拆分）</span></div></div><div><div><div>8</div></div><div><span>const</span><span> </span><span>s</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span>(</span><span>"hello"</span><span>);</span></div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>s</span><span>); </span></span><span>// Set(4) {'h','e','l','o'}</span></div></div><div><div><div>10</div></div><div><span>//Map（只取 key）</span></div></div><div><div><div>11</div></div><div><span>const</span><span> </span><span>m</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>([</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>[</span><span>"a"</span><span>, </span><span>1</span><span>],</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>[</span><span>"b"</span><span>, </span><span>2</span><span>]</span></div></div><div><div><div>14</div></div><div><span>]);</span></div></div><div><div><div>15</div></div><div><span>//Map（只取 key）</span></div></div><div><div><div>16</div></div><div><span>const</span><span> </span><span>s</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span><span>(</span><span>m</span><span>);</span></span></div></div><div><div><div>17</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>s</span><span>); </span></span><span>// Set(2) {'a', 'b'}</span></div></div><div><div><div>18</div></div><div><span>//不传参数</span></div></div><div><div><div>19</div></div><div><span>const</span><span> </span><span>s</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span>();</span></div></div><div><div><div>20</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>s</span><span>); </span></span><span>// Set(0) {}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h2>Set 的注意事项<a href="#set-的注意事项"><span>#</span></a></h2><p><strong>如何判断重复值</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//注意点：Set 判断元素是否重复使用的是 SameValueZero（类似 ===，但 NaN 也相等）</span></div></div><div><div><div>2</div></div><div><span>//对象引用不同即使内容一样也不会去重：</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span>([{</span><span>a</span><span>:</span><span>1</span><span>}, {</span><span>a</span><span>:</span><span>1</span><span>}]) </span><span>// 仍然是两个元素</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj</span><span>); </span></span><span>// Set(2) { { a: 1 }, { a: 1 } }</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>什么时候用Set</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//数组或者字符串去重的时候</span></div></div><div><div><div>2</div></div><div><span>//不需要通过下标访问，只需要遍历时</span></div></div><div><div><div>3</div></div><div><span>//为了使用Set提供的方法和属性时(add delete clear has forEach size 等)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>Set的应用<a href="#set的应用"><span>#</span></a></h2><p>黑名单：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>blacklist</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span>([</span></div></div><div><div><div>2</div></div><div><span>  </span><span>'Tom'</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>'Jerry'</span></div></div><div><div><div>4</div></div><div><span>]);</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>if</span><span><span> (</span><span>blacklist</span><span>.</span></span><span>has</span><span><span>(</span><span>username</span><span>)) {</span></span></div></div><div><div><div>7</div></div><div><span>  </span><span>// 禁止访问</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>展开set</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>s</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span>([</span><span>1</span><span>,</span><span>2</span><span>,</span><span>3</span><span>])</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>([</span><span>...</span><span><span>s</span><span>]);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>字符串去重</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>s</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span><span>(‘</span><span>abbaerfghh</span><span>’)</span></span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>([</span><span>...</span><span><span>s</span><span>].</span></span><span>join</span><span>(</span><span>''</span><span>));</span><span>//去重之后，重新展开，重新转为字符串 数组的join()方法可以使数组转为字符串</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>存放DOM元素</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>selected</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Set</span><span><span>(</span><span>document</span><span>.</span></span><span>querySelectorAll</span><span>(</span><span>"p"</span><span>));</span></div></div><div><div><div>2</div></div><div><span><span>selected</span><span>.</span></span><span>forEach</span><span><span>(</span><span>el</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>el</span><span>.</span><span>style</span><span>.</span><span>color</span><span> </span><span>=</span><span> </span><span>"red"</span><span>;</span></div></div><div><div><div>4</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h1>Map是什么<a href="#map是什么"><span>#</span></a></h1><p><code>Map</code> 是 JavaScript 中的一种<strong>键值对集合结构</strong>，和普通对象 <code>{}</code> 类似，但功能更强、更规范。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>map</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>();</span></div></div><div><div><div>2</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>'name'</span><span>, </span><span>'Alice'</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>'age'</span><span>, </span><span>18</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>map</span><span>.</span></span><span>get</span><span>(</span><span>'name'</span><span>)); </span><span>// Alice</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>Map 和 Object 的核心区别</strong></p><p>key 的类型更自由（Map 更强）</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//Object  key 只能是 字符串 / Symbol</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {};</span></div></div><div><div><div>3</div></div><div><span><span>obj</span><span>[</span></span><span>1</span><span>] </span><span>=</span><span> </span><span>"a"</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>obj</span><span>[</span></span><span>true</span><span>] </span><span>=</span><span> </span><span>"b"</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj</span><span>); </span></span><span>// key 会被转成字符串</span></div></div><div><div><div>6</div></div><div><span>//Map key 可以是任何类型</span></div></div><div><div><div>7</div></div><div><span>const</span><span> </span><span>map</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>();</span></div></div><div><div><div>8</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>1</span><span>, </span><span>"数字key"</span><span>);</span></div></div><div><div><div>9</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>true</span><span>, </span><span>"布尔key"</span><span>);</span></div></div><div><div><div>10</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>({}, </span><span>"对象key"</span><span>);</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>map</span><span>.</span></span><span>get</span><span>(</span><span>1</span><span>)); </span><span>// 数字key</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>Map 保持插入顺序</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>map</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>();</span></div></div><div><div><div>2</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>"a"</span><span>, </span><span>1</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>"b"</span><span>, </span><span>2</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>"c"</span><span>, </span><span>3</span><span>);</span></div></div><div><div><div>5</div></div><div><span>for</span><span> (</span><span>const</span><span> [</span><span>k</span><span>, </span><span>v</span><span>] </span><span>of</span><span><span> </span><span>map</span><span>) {</span></span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>k</span><span>, </span><span>v</span><span>);</span></span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>Map 自带 size</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>map</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>();</span></div></div><div><div><div>2</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>"a"</span><span>, </span><span>1</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>"b"</span><span>, </span><span>2</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>map</span><span>.</span></span><span>size</span><span>); </span><span>// 2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><section><h2>Map 实例的属性和方法<a href="#map-实例的属性和方法"><span>#</span></a></h2><p><strong>常用方法</strong></p><p>set（添加/修改）</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>"name"</span><span>, </span><span>"Tom"</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>get（获取）</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>map</span><span>.</span></span><span>get</span><span>(</span><span>"name"</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>delete() 删除</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>map</span><span>.</span></span><span>delete</span><span>(</span><span>"name"</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>has()判断是否存在</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>map</span><span>.</span></span><span>has</span><span>(</span><span>"name"</span><span>); </span><span>// true</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>clear()清空</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>map</span><span>.</span></span><span>clear</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>size获取个数</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>map</span><span>.</span></span><span>size</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>遍历Map获取元素值</strong></p><p>for…of</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>const</span><span> [</span><span>key</span><span>, </span><span>value</span><span>] </span><span>of</span><span><span> </span><span>map</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>key</span><span>, </span><span>value</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>forEach(callback)</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>map</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>([</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>[</span><span>"a"</span><span>, </span><span>1</span><span>],</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>[</span><span>"b"</span><span>, </span><span>2</span><span>]</span></div></div><div><div><div>4</div></div><div><span>]);</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>map</span><span>.</span></span><span>forEach</span><span><span>((</span><span>value</span><span>, </span><span>key</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>key</span><span>, </span><span>value</span><span>);</span></span><span>//注意顺序是：value 在前，key 在后（和 set 不同）</span></div></div><div><div><div>8</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>keys / values / entries</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>key</span><span> </span><span>of</span><span><span> </span><span>map</span><span>.</span></span><span>keys</span><span>()) {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>key</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>value</span><span> </span><span>of</span><span><span> </span><span>map</span><span>.</span></span><span>values</span><span>()) {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>value</span><span>);</span></span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>entry</span><span> </span><span>of</span><span><span> </span><span>map</span><span>.</span></span><span>entries</span><span>()) {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>entry</span><span>);</span></span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div><span>for</span><span> (</span><span>const</span><span> [</span><span>k</span><span>, </span><span>v</span><span>] </span><span>of</span><span><span> </span><span>map</span><span>) {</span></span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>k</span><span>, </span><span>v</span><span>);</span></span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div><span>//map.keys();</span></div></div><div><div><div>14</div></div><div><span>//map.values();</span></div></div><div><div><div>15</div></div><div><span>//map.entries();</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h2>Map 构造函数的参数<a href="#map-构造函数的参数"><span>#</span></a></h2><p><code>Map</code> 构造函数的参数是一个<strong>可迭代对象（iterable）</strong>，用于在创建 Map 时<strong>初始化键值对数据</strong>。</p><p>set、map、键值对数组</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//数组，必须是二维结构</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>map</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>([</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>[</span><span>"name"</span><span>, </span><span>"Alice"</span><span>],</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>[</span><span>"age"</span><span>, </span><span>18</span><span>]</span></div></div><div><div><div>5</div></div><div><span>]);</span></div></div><div><div><div>6</div></div><div><span>// new Map(["a", "b"]);//❌ 错误用法</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>map</span><span>.</span></span><span>get</span><span>(</span><span>"name"</span><span>)); </span><span>// Alice</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>//由 Map 构造 Map（复制）相当于浅拷贝（key/value 引用不变）</span></div></div><div><div><div>10</div></div><div><span>const</span><span> </span><span>m1</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>([</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>[</span><span>"a"</span><span>, </span><span>1</span><span>],</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>[</span><span>"b"</span><span>, </span><span>2</span><span>]</span></div></div><div><div><div>13</div></div><div><span>]);</span></div></div><div><div><div>14</div></div><div><span>const</span><span> </span><span>m2</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span><span>(</span><span>m1</span><span>);</span></span></div></div><div><div><div>15</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>m2</span><span>.</span></span><span>get</span><span>(</span><span>"a"</span><span>)); </span><span>// 1</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>//Set ❌ 不能直接用（容易踩坑）</span></div></div><div><div><div>18</div></div><div><span>new</span><span> </span><span>Map</span><span>(</span><span>new</span><span> </span><span>Set</span><span>([</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>]));</span><span>//❌ 错误用法</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h2>Map 的注意事项<a href="#map-的注意事项"><span>#</span></a></h2><p>key 不会自动转换类型</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>map</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>();</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>1</span><span>, </span><span>"number"</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>"1"</span><span>, </span><span>"string"</span><span>);</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>map</span><span>.</span></span><span>size</span><span>); </span><span>// 2，在 Object 里 "1" 和 1 可能会混在一起，但 Map 不会</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>NaN 是相等的（特殊规则）</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>map</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>();</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>NaN</span><span>, </span><span>1</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>NaN</span><span>, </span><span>2</span><span>);</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>map</span><span>.</span></span><span>size</span><span>); </span><span>// 1</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>map</span><span>.</span></span><span>get</span><span>(</span><span>NaN</span><span>)); </span><span>// 2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>对象 key 比较的是“引用”</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>map</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>();</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>({}, </span><span>1</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>({}, </span><span>2</span><span>);</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>map</span><span>.</span></span><span>size</span><span>); </span><span>// 2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>delete 返回值很重要</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>map</span><span>.</span></span><span>delete</span><span>(</span><span>"a"</span><span>); </span><span>// true / false用来判断是否真的删除成功</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>Map 不会自动去重 value</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>"a"</span><span>, </span><span>1</span><span>);</span></div></div><div><div><div>2</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>"b"</span><span>, </span><span>1</span><span>);</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>map</span><span>.</span></span><span>size</span><span>); </span><span>// 2去重只针对 key，不针对 value</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>如何判断键名是否相同</strong>：Map 的 key 判断遵循 ===</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//基本类型（字符串/数字/布尔）相同 key（直接覆盖）</span></div></div><div><div><div>2</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>"a"</span><span>, </span><span>1</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>"a"</span><span>, </span><span>2</span><span>);</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>//NaN 特殊处理 认为相同 key</span></div></div><div><div><div>6</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>NaN</span><span>, </span><span>1</span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>NaN</span><span>, </span><span>2</span><span>);</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>//对象，引用比较，不相同（不同引用）</span></div></div><div><div><div>10</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>({</span><span>a</span><span>:</span><span>1</span><span>}, </span><span>1</span><span>);</span></div></div><div><div><div>11</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>({</span><span>a</span><span>:</span><span>1</span><span>}, </span><span>2</span><span>);</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>//同一个对象才算同一个 key</span></div></div><div><div><div>14</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span><span>a</span><span>:</span><span>1</span><span>};</span></div></div><div><div><div>15</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span><span>(</span><span>obj</span><span>, </span></span><span>1</span><span>);</span></div></div><div><div><div>16</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span><span>(</span><span>obj</span><span>, </span></span><span>2</span><span>);</span></div></div><div><div><div>17</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>map</span><span>.</span></span><span>size</span><span>); </span><span>// 1</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>什么时候用Map</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//key 不是字符串时（必须用 Map）Object 做不到（会变成 "[object Object]"）</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>map</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>();</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>el</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelector</span><span>(</span><span>"div"</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span><span>(</span><span>el</span><span>, { </span></span><span>clicked</span><span>:</span><span> </span><span>true</span><span> });</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>//频繁增删数据；Map 比 Object 更稳定，不会触发 hidden class 变化</span></div></div><div><div><div>7</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>"a"</span><span>, </span><span>1</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>map</span><span>.</span></span><span>delete</span><span>(</span><span>"a"</span><span>);</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>//需要有序数据结构；遍历顺序 = 插入顺序</span></div></div><div><div><div>11</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>"a"</span><span>, </span><span>1</span><span>);</span></div></div><div><div><div>12</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>"b"</span><span>, </span><span>2</span><span>);</span></div></div><div><div><div>13</div></div><div><span><span>map</span><span>.</span></span><span>set</span><span>(</span><span>"c"</span><span>, </span><span>3</span><span>);</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>//需要快速查找 + 动态变化</span></div></div><div><div><div>16</div></div><div><span>//缓存</span></div></div><div><div><div>17</div></div><div><span>const</span><span> </span><span>cache</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>();</span></div></div><div><div><div>18</div></div><div><span>function</span><span> </span><span>getData</span><span><span>(</span><span>key</span><span>) {</span></span></div></div><div><div><div>19</div></div><div><span>  </span><span>if</span><span><span> (</span><span>cache</span><span>.</span></span><span>has</span><span><span>(</span><span>key</span><span>)) </span></span><span>return</span><span><span> </span><span>cache</span><span>.</span></span><span>get</span><span><span>(</span><span>key</span><span>);</span></span></div></div><div><div><div>20</div></div><div><span>  </span><span>const</span><span> </span><span>result</span><span> </span><span>=</span><span><span> </span><span>key</span><span> </span></span><span>*</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>21</div></div><div><span><span>  </span></span><span>cache</span><span>.</span><span>set</span><span><span>(</span><span>key</span><span>, </span><span>result</span><span>);</span></span></div></div><div><div><div>22</div></div><div><span>  </span><span>return</span><span><span> </span><span>result</span><span>;</span></span></div></div><div><div><div>23</div></div><div><span>}</span></div></div><div><div><div>24</div></div><div><span>//DOM 状态管理</span></div></div><div><div><div>25</div></div><div><span>const</span><span> </span><span>selected</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>();</span></div></div><div><div><div>26</div></div><div><span><span>selected</span><span>.</span></span><span>set</span><span><span>(</span><span>dom</span><span>, </span></span><span>true</span><span>);</span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span>//需要避免 Object 原型污染Map 没有这个问题</span></div></div><div><div><div>29</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {};</span></div></div><div><div><div>30</div></div><div><span><span>obj</span><span>.</span></span><span>__proto__</span><span> </span><span>=</span><span> </span><span>"hack"</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>什么时候不用 Map</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//静态数据（推荐 Object）更简单 + JSON 友好</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>user</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>"Alice"</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>age</span><span>:</span><span> </span><span>18</span></div></div><div><div><div>5</div></div><div><span>};</span></div></div><div><div><div>6</div></div><div><span>//需要 JSON 序列化：Map 不能直接 stringify</span></div></div><div><div><div>7</div></div><div><span>//简单配置数据 Object 更清晰</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>Map的应用<a href="#map的应用"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!</span><span>doctype</span><span> </span><span>html</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>html</span><span> </span><span>lang</span><span>=</span><span>"en"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>head</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>meta</span><span> </span><span>charset</span><span>=</span><span>"UTF-8"</span><span> /&gt;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>&lt;</span><span>meta</span><span> </span><span>name</span><span>=</span><span>"viewport"</span><span> </span><span>content</span><span>=</span><span>"width=device-width, initial-scale=1.0"</span><span> /&gt;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>&lt;</span><span>title</span><span>&gt;Document&lt;/</span><span>title</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span>      </span><span>/* p {</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>background-color: orange;</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>font-size: 40px;</span></div></div><div><div><div>11</div></div><div><span><span>      </span></span><span>} */</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;1&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;2&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;3&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>19</div></div><div><span>      </span><span>const</span><span> </span><span>p</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelectorAll</span><span>(</span><span>'p'</span><span>);</span></div></div><div><div><div>20</div></div><div><span>      </span><span>// console.log(p);</span></div></div><div><div><div>21</div></div><div><span>      </span><span>//解构</span></div></div><div><div><div>22</div></div><div><span>      </span><span>const</span><span> [</span><span>p1</span><span>, </span><span>p2</span><span>, </span><span>p3</span><span>] </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelectorAll</span><span>(</span><span>'p'</span><span>);</span></div></div><div><div><div>23</div></div><div><span>      </span><span>const</span><span> </span><span>m</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>([</span></div></div><div><div><div>24</div></div><div><span><span>        </span></span><span>[</span><span>p1</span><span>, { </span><span>color</span><span>:</span><span> </span><span>'red'</span><span>, </span><span>backgroundColor</span><span>:</span><span> </span><span>'pink'</span><span>, </span><span>fontSize</span><span>:</span><span> </span><span>'40px'</span><span> }],</span></div></div><div><div><div>25</div></div><div><span><span>        </span></span><span>[</span><span>p2</span><span>, { </span><span>color</span><span>:</span><span> </span><span>'blue'</span><span>, </span><span>backgroundColor</span><span>:</span><span> </span><span>'orange'</span><span>, </span><span>fontSize</span><span>:</span><span> </span><span>'40px'</span><span> }],</span></div></div><div><div><div>26</div></div><div><span><span>        </span></span><span>[</span><span>p3</span><span>, { </span><span>color</span><span>:</span><span> </span><span>'yellow'</span><span>, </span><span>backgroundColor</span><span>:</span><span> </span><span>'green'</span><span>, </span><span>fontSize</span><span>:</span><span> </span><span>'40px'</span><span> }],</span></div></div><div><div><div>27</div></div><div><span><span>      </span></span><span>]);</span></div></div><div><div><div>28</div></div><div><span><span>      </span></span><span>m</span><span>.</span><span>forEach</span><span><span>((</span><span>propObject</span><span>, </span><span>elem</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>29</div></div><div><span>        </span><span>//console.log(propObject);</span></div></div><div><div><div>30</div></div><div><span>        </span><span>for</span><span> (</span><span>const</span><span> </span><span>p</span><span> </span><span>in</span><span><span> </span><span>propObject</span><span>) {</span></span></div></div><div><div><div>31</div></div><div><span>          </span><span>// console.log(propObject);</span></div></div><div><div><div>32</div></div><div><span>          </span><span>// console.log(p);</span></div></div><div><div><div>33</div></div><div><span>          </span><span>// console.log(propObject[p]);</span></div></div><div><div><div>34</div></div><div><span><span>          </span></span><span>elem</span><span>.</span><span>style</span><span><span>[</span><span>p</span><span>] </span></span><span>=</span><span><span> </span><span>propObject</span><span>[</span><span>p</span><span>];</span></span></div></div><div><div><div>35</div></div><div><span>          </span><span>//elem.style.p = propObject[p]; 错误，这是静态调用</span></div></div><div><div><div>36</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>37</div></div><div><span><span>      </span></span><span>});</span></div></div><div><div><div>38</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>39</div></div><div><span><span>  </span></span><span>&lt;/</span><span>body</span><span>&gt;</span></div></div><div><div><div>40</div></div><div><span>&lt;/</span><span>html</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>把对象改为Map：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!</span><span>doctype</span><span> </span><span>html</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>html</span><span> </span><span>lang</span><span>=</span><span>"en"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>head</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>meta</span><span> </span><span>charset</span><span>=</span><span>"UTF-8"</span><span> /&gt;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>&lt;</span><span>meta</span><span> </span><span>name</span><span>=</span><span>"viewport"</span><span> </span><span>content</span><span>=</span><span>"width=device-width, initial-scale=1.0"</span><span> /&gt;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>&lt;</span><span>title</span><span>&gt;Document&lt;/</span><span>title</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span>      </span><span>/* p {</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>background-color: orange;</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>font-size: 40px;</span></div></div><div><div><div>11</div></div><div><span><span>      </span></span><span>} */</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;1&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;2&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;3&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>19</div></div><div><span>      </span><span>const</span><span> </span><span>p</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelectorAll</span><span>(</span><span>'p'</span><span>);</span></div></div><div><div><div>20</div></div><div><span>      </span><span>// console.log(p);</span></div></div><div><div><div>21</div></div><div><span>      </span><span>//解构</span></div></div><div><div><div>22</div></div><div><span>      </span><span>const</span><span> [</span><span>p1</span><span>, </span><span>p2</span><span>, </span><span>p3</span><span>] </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelectorAll</span><span>(</span><span>'p'</span><span>);</span></div></div><div><div><div>23</div></div><div><span>      </span><span>const</span><span> </span><span>m</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>([</span></div></div><div><div><div>24</div></div><div><span><span>        </span></span><span>[</span></div></div><div><div><div>25</div></div><div><span><span>          </span></span><span>p1</span><span>,</span></div></div><div><div><div>26</div></div><div><span>          </span><span>new</span><span> </span><span>Map</span><span>([</span></div></div><div><div><div>27</div></div><div><span><span>            </span></span><span>[</span><span>'color'</span><span>, </span><span>'red'</span><span>],</span></div></div><div><div><div>28</div></div><div><span><span>            </span></span><span>[</span><span>'backgroundColor'</span><span>, </span><span>'pink'</span><span>],</span></div></div><div><div><div>29</div></div><div><span><span>            </span></span><span>[</span><span>'fontSize'</span><span>, </span><span>'40px'</span><span>],</span></div></div><div><div><div>30</div></div><div><span><span>          </span></span><span>]),</span></div></div><div><div><div>31</div></div><div><span><span>        </span></span><span>],</span></div></div><div><div><div>32</div></div><div>
</div></div><div><div><div>33</div></div><div><span><span>        </span></span><span>[</span></div></div><div><div><div>34</div></div><div><span><span>          </span></span><span>p2</span><span>,</span></div></div><div><div><div>35</div></div><div><span>          </span><span>new</span><span> </span><span>Map</span><span>([</span></div></div><div><div><div>36</div></div><div><span><span>            </span></span><span>[</span><span>'color'</span><span>, </span><span>'blue'</span><span>],</span></div></div><div><div><div>37</div></div><div><span><span>            </span></span><span>[</span><span>'backgroundColor'</span><span>, </span><span>'orange'</span><span>],</span></div></div><div><div><div>38</div></div><div><span><span>            </span></span><span>[</span><span>'fontSize'</span><span>, </span><span>'40px'</span><span>],</span></div></div><div><div><div>39</div></div><div><span><span>          </span></span><span>]),</span></div></div><div><div><div>40</div></div><div><span><span>        </span></span><span>],</span></div></div><div><div><div>41</div></div><div>
</div></div><div><div><div>42</div></div><div><span><span>        </span></span><span>[</span></div></div><div><div><div>43</div></div><div><span><span>          </span></span><span>p3</span><span>,</span></div></div><div><div><div>44</div></div><div><span>          </span><span>new</span><span> </span><span>Map</span><span>([</span></div></div><div><div><div>45</div></div><div><span><span>            </span></span><span>[</span><span>'color'</span><span>, </span><span>'yellow'</span><span>],</span></div></div><div><div><div>46</div></div><div><span><span>            </span></span><span>[</span><span>'backgroundColor'</span><span>, </span><span>'green'</span><span>],</span></div></div><div><div><div>47</div></div><div><span><span>            </span></span><span>[</span><span>'fontSize'</span><span>, </span><span>'40px'</span><span>],</span></div></div><div><div><div>48</div></div><div><span><span>          </span></span><span>]),</span></div></div><div><div><div>49</div></div><div><span><span>        </span></span><span>],</span></div></div><div><div><div>50</div></div><div><span><span>      </span></span><span>]);</span></div></div><div><div><div>51</div></div><div><span><span>      </span></span><span>m</span><span>.</span><span>forEach</span><span><span>((</span><span>styleMap</span><span>, </span><span>elem</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>52</div></div><div><span><span>        </span></span><span>styleMap</span><span>.</span><span>forEach</span><span><span>((</span><span>value</span><span>, </span><span>key</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>53</div></div><div><span><span>          </span></span><span>elem</span><span>.</span><span>style</span><span><span>[</span><span>key</span><span>] </span></span><span>=</span><span><span> </span><span>value</span><span>;</span></span></div></div><div><div><div>54</div></div><div><span><span>        </span></span><span>});</span></div></div><div><div><div>55</div></div><div><span><span>      </span></span><span>});</span></div></div><div><div><div>56</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>57</div></div><div><span><span>  </span></span><span>&lt;/</span><span>body</span><span>&gt;</span></div></div><div><div><div>58</div></div><div><span>&lt;/</span><span>html</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102107es6-zhan-kai-yun-suan-fu/</id>
      <title type="text">ES6展开运算符</title>
      <published>2026-10-21T07:40:53.000Z</published>
      <updated>2026-10-21T07:40:53.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102107es6-zhan-kai-yun-suan-fu/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>数组展开运算符的基本用法<a href="#数组展开运算符的基本用法"><span>#</span></a></h1><p>数组展开运算符是 ES6 的 <code>...</code> 语法，用来把“数组拆开成单个元素”。</p><p>基本语法</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>...</span><span><span>arr</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>//等价于</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>区分剩余参数和展开运算符<a href="#区分剩余参数和展开运算符"><span>#</span></a></h1><p>与剩余参数的区别：剩余参数是把多个值收集成数组，展开运算符是把数组拆成多个值；同一个符号，不同位置决定含义</p>

<table><thead><tr><th>写法</th><th>位置</th><th>作用</th></tr></thead><tbody><tr><td><code>...args</code></td><td>函数参数</td><td>收集剩余参数</td></tr><tr><td><code>...arr</code></td><td>调用/表达式</td><td>展开数组</td></tr></tbody></table><p>例子：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//剩余参数</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>add</span><span> </span><span>=</span><span> (</span><span>...</span><span><span>args</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>...</span><span><span>args</span><span>); </span></span><span>//扩展运算符</span></div></div><div><div><div>4</div></div><div><span>};</span></div></div><div><div><div>5</div></div><div><span>add</span><span>(</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>);</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>([</span><span>...</span><span>[</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>], </span><span>4</span><span>]); </span><span>//扩展运算符[ 1, 2, 3, 4 ]</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>数组展开运算符的应用<a href="#数组展开运算符的应用"><span>#</span></a></h1><p>例子：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//数组合并</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>a</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>];</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>b</span><span> </span><span>=</span><span> [</span><span>3</span><span>, </span><span>4</span><span>];</span></div></div><div><div><div>4</div></div><div><span>const</span><span> </span><span>c</span><span> </span><span>=</span><span> [</span><span>...</span><span><span>a</span><span>, </span></span><span>...</span><span><span>b</span><span>];</span></span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>c</span><span>); </span></span><span>// [1, 2, 3, 4]</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>//数组拷贝（浅拷贝）</span></div></div><div><div><div>8</div></div><div><span>const</span><span> </span><span>arr1</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];</span></div></div><div><div><div>9</div></div><div><span>const</span><span> </span><span>arr2</span><span> </span><span>=</span><span> [</span><span>...</span><span><span>arr1</span><span>];</span></span></div></div><div><div><div>10</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr2</span><span>); </span></span><span>// [1, 2, 3]</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>//函数传参展开</span></div></div><div><div><div>13</div></div><div><span>function</span><span> </span><span>sum</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>, </span><span>c</span><span>) {</span></span></div></div><div><div><div>14</div></div><div><span>  </span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span> </span></span><span>+</span><span><span> </span><span>c</span><span>;</span></span></div></div><div><div><div>15</div></div><div><span>}</span></div></div><div><div><div>16</div></div><div><span>const</span><span> </span><span>nums</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];</span></div></div><div><div><div>17</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>sum</span><span>(</span><span>...</span><span><span>nums</span><span>)); </span></span><span>// 6</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>//找最大/最小值</span></div></div><div><div><div>20</div></div><div><span>const</span><span> </span><span>nums</span><span> </span><span>=</span><span> [</span><span>5</span><span>, </span><span>2</span><span>, </span><span>9</span><span>];</span></div></div><div><div><div>21</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>Math</span><span>.</span></span><span>max</span><span>(</span><span>...</span><span><span>nums</span><span>)); </span></span><span>// 9</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>//字符串转数组</span></div></div><div><div><div>24</div></div><div><span>const</span><span> </span><span>str</span><span> </span><span>=</span><span> </span><span>"abc"</span><span>;</span></div></div><div><div><div>25</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>([</span><span>...</span><span><span>str</span><span>]); </span></span><span>// ['a', 'b', 'c']</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>//类数组转数组</span></div></div><div><div><div>28</div></div><div><span>function</span><span> </span><span>fn</span><span>() {</span></div></div><div><div><div>29</div></div><div><span>  </span><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>...</span><span>arguments</span><span>];</span></div></div><div><div><div>30</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>arr</span><span>);</span></span></div></div><div><div><div>31</div></div><div><span>}</span></div></div><div><div><div>32</div></div><div><span>fn</span><span>(</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>);</span></div></div><div><div><div>33</div></div><div><span>//nodelist也是类数组</span></div></div><div><div><div>34</div></div><div><span>const</span><span> </span><span>nodes</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelectorAll</span><span>(</span><span>"div"</span><span>);</span></div></div><div><div><div>35</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>...</span><span><span>nodes</span><span>];</span></span></div></div><div><div><div>36</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h1>对象展开运算符的基本用法<a href="#对象展开运算符的基本用法"><span>#</span></a></h1><p><strong>展开对象</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> { </span><span>a</span><span>:</span><span> </span><span>1</span><span>, </span><span>b</span><span>:</span><span> </span><span>2</span><span> };</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>({</span><span>...</span><span><span>arr</span><span>} </span></span><span>===</span><span><span> </span><span>obj</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>合并对象</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>obj1</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>"Tom"</span></div></div><div><div><div>3</div></div><div><span>};</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>obj2</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>6</div></div><div><span>  </span><span>age</span><span>:</span><span> </span><span>18</span><span>////如果属性相同，会覆盖前面对象的属性</span></div></div><div><div><div>7</div></div><div><span>};</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>const</span><span> </span><span>result</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>...</span><span><span>obj1</span><span>,</span></span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>...</span><span>obj2</span></div></div><div><div><div>12</div></div><div><span>};</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>);</span></span></div></div><div><div><div>15</div></div><div><span>// { name: 'Tom', age: 18 }</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>对象展开的疑惑</strong></p><p>“展开（spread）”这个名字容易让人误以为：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> { </span><span>a</span><span>:</span><span> </span><span>1</span><span>, </span><span>b</span><span>:</span><span> </span><span>2</span><span> };</span></div></div><div><div><div>2</div></div><div><span>...</span><span>obj</span></div></div><div><div><div>3</div></div><div><span>//会变成</span></div></div><div><div><div>4</div></div><div><span><span>a</span><span>: </span></span><span>1</span><span><span>, </span><span>b</span><span>: </span></span><span>2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>然后单独存在。实际上 <strong>对象展开只能出现在另一个对象字面量中</strong>，它的作用是：将源对象的可枚举属性复制到当前对象中。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> { </span><span>a</span><span>:</span><span> </span><span>1</span><span>, </span><span>b</span><span>:</span><span> </span><span>2</span><span> };</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>newObj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>...</span><span>obj</span></div></div><div><div><div>5</div></div><div><span>};</span></div></div><div><div><div>6</div></div><div><span>//JavaScript 引擎实际上会理解成类似：</span></div></div><div><div><div>7</div></div><div><span>const</span><span> </span><span>newObj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>8</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>9</div></div><div><span>  </span><span>b</span><span>:</span><span> </span><span>2</span></div></div><div><div><div>10</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这里确实发生了“展开”，但展开后的结果必须放进一个新的对象里。</p><p>为什么数组看起来更像“展开”？</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>...</span><span><span>arr</span><span>);</span></span><span>//1 2 3</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>因为数组的展开运算符会把元素变成多个独立值，所以数组的“展开感”特别强。</p><p>对象为什么不能这样？假设允许：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>...</span><span><span>obj</span><span>);</span></span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>:</span></span><span>1</span><span><span>, </span><span>b</span><span>:</span></span><span>2</span><span>)  </span><span>// 这根本不是合法JS</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>对象本身不是一个值序列，而是一组 <strong>key-value 映射</strong>。因此对象展开只能出现在需要属性列表的地方</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>{</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>...</span><span>obj</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>因此对象展开运算符的本质不是：把对象拆开；而是：把对象的属性复制到当前位置的对象中</p><p>所以很多开发者更愿意把对象展开理解成：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>Object</span><span>.</span></span><span>assign</span><span><span>({}, </span><span>obj</span><span>)</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>的语法糖，而不是像数组那样真正意义上的“展开成多个值”。这样理解会更准确。</p></section>
<section><h1>对象展开运算符的注意事项<a href="#对象展开运算符的注意事项"><span>#</span></a></h1><p><strong>空对象的展开</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>({ </span><span>...</span><span>{} });</span><span>//{}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>非对象展开</strong></p><p>如果不是对象，会转其对象，然后将属性展开</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>({ </span><span>...</span><span>1</span><span> });</span></div></div><div><div><div>2</div></div><div><span>//等价于</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>new</span><span> </span><span>Object</span><span>(</span><span>1</span><span>));</span></div></div><div><div><div>4</div></div><div><span>//console.log({ ...new Object(1) });</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>({ </span><span>...</span><span>'hello'</span><span> }); </span><span>//特殊，类数组：{ '0': 'h', '1': 'e', '2': 'l', '3': 'l', '4': 'o' }</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>({ </span><span>...</span><span>[</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>] });</span><span>//在对象中展开数组类数组：{ '0': 1, '1': 2, '2': 3 }</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>对象中的对象属性展开</strong></p><p>不会展开对象中的对象属性</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>user</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>'Tom'</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>address</span><span>:</span><span> {</span></div></div><div><div><div>4</div></div><div><span>    </span><span>city</span><span>:</span><span> </span><span>'Beijing'</span><span>,</span></div></div><div><div><div>5</div></div><div><span>    </span><span>street</span><span>:</span><span> </span><span>'xxx'</span><span>,</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>7</div></div><div><span>};</span></div></div><div><div><div>8</div></div><div><span>const</span><span> </span><span>user1</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>9</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>'Alex'</span><span>,</span></div></div><div><div><div>10</div></div><div><span>  </span><span>address</span><span>:</span><span> {</span></div></div><div><div><div>11</div></div><div><span>    </span><span>city1</span><span>:</span><span> </span><span>'Shenzheng'</span><span>,</span></div></div><div><div><div>12</div></div><div><span>    </span><span>street1</span><span>:</span><span> </span><span>'xxx'</span><span>,</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>14</div></div><div><span>};</span></div></div><div><div><div>15</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>({ </span><span>...</span><span><span>user</span><span> });</span></span></div></div><div><div><div>16</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>({ </span><span>...</span><span><span>user</span><span>, </span></span><span>...</span><span><span>user1</span><span> }); </span></span><span>//addr没有展开所以覆盖了{ name: 'Alex', address: { city1: 'Shenzheng', street1: 'xxx' } }</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>//正常的合并对象只有属性名相同才会覆盖否则不会</span></div></div><div><div><div>19</div></div><div><span>const</span><span> </span><span>address</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>20</div></div><div><span>  </span><span>city</span><span>:</span><span> </span><span>'Beijing'</span><span>,</span></div></div><div><div><div>21</div></div><div><span>  </span><span>street</span><span>:</span><span> </span><span>'xxx'</span><span>,</span></div></div><div><div><div>22</div></div><div><span>};</span></div></div><div><div><div>23</div></div><div><span>const</span><span> </span><span>address1</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>24</div></div><div><span>  </span><span>city1</span><span>:</span><span> </span><span>'Beijing'</span><span>,</span></div></div><div><div><div>25</div></div><div><span>  </span><span>street1</span><span>:</span><span> </span><span>'xxx'</span><span>,</span></div></div><div><div><div>26</div></div><div><span>};</span></div></div><div><div><div>27</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>({ </span><span>...</span><span><span>address</span><span>, </span></span><span>...</span><span><span>address1</span><span> }); </span></span><span>//{ city: 'Beijing', street: 'xxx', city1: 'Beijing', street1: 'xxx' }</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h1>对象展开运算符的应用<a href="#对象展开运算符的应用"><span>#</span></a></h1><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//使用展开运算符设置默认配置</span></div></div><div><div><div>2</div></div><div><span>function</span><span> </span><span>createUser</span><span><span>(</span><span>options</span><span> </span></span><span>=</span><span> {}) {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>const</span><span> </span><span>config</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>4</div></div><div><span>    </span><span>name</span><span>:</span><span> </span><span>'Guest'</span><span>,</span></div></div><div><div><div>5</div></div><div><span>    </span><span>age</span><span>:</span><span> </span><span>18</span><span>,</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>...</span><span>options</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>};</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>  </span><span>return</span><span><span> </span><span>config</span><span>;</span></span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>createUser</span><span>({</span></div></div><div><div><div>13</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>'Tom'</span></div></div><div><div><div>14</div></div><div><span>});</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>//删除属性（结合解构）</span></div></div><div><div><div>17</div></div><div><span>const</span><span> </span><span>user</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>18</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>'Tom'</span><span>,</span></div></div><div><div><div>19</div></div><div><span>  </span><span>age</span><span>:</span><span> </span><span>18</span><span>,</span></div></div><div><div><div>20</div></div><div><span>  </span><span>password</span><span>:</span><span> </span><span>'123456'</span><span>,</span></div></div><div><div><div>21</div></div><div><span>};</span></div></div><div><div><div>22</div></div><div><span>const</span><span> { </span><span>password</span><span>, </span><span>...</span><span>safeUser</span><span> } </span><span>=</span><span><span> </span><span>user</span><span>;</span></span></div></div><div><div><div>23</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>password</span><span>, </span><span>safeUser</span><span>); </span></span><span>//123456 { name: 'Tom', age: 18 }</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span>//展开嵌套对象属性</span></div></div><div><div><div>26</div></div><div><span>const</span><span> </span><span>user</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>27</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>'Tom'</span><span>,</span></div></div><div><div><div>28</div></div><div><span>  </span><span>address</span><span>:</span><span> {</span></div></div><div><div><div>29</div></div><div><span>    </span><span>city</span><span>:</span><span> </span><span>'Beijing'</span><span>,</span></div></div><div><div><div>30</div></div><div><span>    </span><span>street</span><span>:</span><span> </span><span>'xxx'</span></div></div><div><div><div>31</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>32</div></div><div><span>};</span></div></div><div><div><div>33</div></div><div>
</div></div><div><div><div>34</div></div><div><span>const</span><span> </span><span>result</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>35</div></div><div><span><span>  </span></span><span>...</span><span><span>user</span><span>,</span></span></div></div><div><div><div>36</div></div><div><span><span>  </span></span><span>...</span><span><span>user</span><span>.</span></span><span>address</span></div></div><div><div><div>37</div></div><div><span>};</span></div></div><div><div><div>38</div></div><div>
</div></div><div><div><div>39</div></div><div><span>//条件添加属性</span></div></div><div><div><div>40</div></div><div><span>const</span><span> </span><span>isAdmin</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>41</div></div><div><span>const</span><span> </span><span>user</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>42</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>'Tom'</span><span>,</span></div></div><div><div><div>43</div></div><div><span><span>  </span></span><span>...</span><span><span>(</span><span>isAdmin</span><span> </span></span><span>&amp;&amp;</span><span> {</span></div></div><div><div><div>44</div></div><div><span>    </span><span>role</span><span>:</span><span> </span><span>'admin'</span></div></div><div><div><div>45</div></div><div><span><span>  </span></span><span>})</span></div></div><div><div><div>46</div></div><div><span>};</span></div></div><div><div><div>47</div></div><div>
</div></div><div><div><div>48</div></div><div><span>//更新对象属性</span></div></div><div><div><div>49</div></div><div><span>const</span><span> </span><span>user</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>50</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>'Tom'</span><span>,</span></div></div><div><div><div>51</div></div><div><span>  </span><span>age</span><span>:</span><span> </span><span>18</span></div></div><div><div><div>52</div></div><div><span>};</span></div></div><div><div><div>53</div></div><div><span>const</span><span> </span><span>updatedUser</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>54</div></div><div><span><span>  </span></span><span>...</span><span><span>user</span><span>,</span></span></div></div><div><div><div>55</div></div><div><span>  </span><span>age</span><span>:</span><span> </span><span>20</span></div></div><div><div><div>56</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102106es6-sheng-yu-can-shu/</id>
      <title type="text">ES6剩余参数</title>
      <published>2026-10-21T07:37:11.000Z</published>
      <updated>2026-10-21T07:37:11.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102106es6-sheng-yu-can-shu/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>剩余参数是什么<a href="#剩余参数是什么"><span>#</span></a></h1><p>剩余参数（Rest Parameters）是 ES6 提供的一种语法，用来把函数中“多出来的参数”收集成一个数组。把不确定数量的参数打包成一个数组</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>add</span><span> </span><span>=</span><span> (</span><span>...</span><span><span>args</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>args</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>};</span></div></div><div><div><div>4</div></div><div><span>add</span><span>(</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>, </span><span>5</span><span>, </span><span>6</span><span>, </span><span>7</span><span>, </span><span>8</span><span>, </span><span>9</span><span>);</span><span>//[1,2,3,4, 5, 6, 7, 8, 9 ]</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>剩余参数的本质：是数组</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>add</span><span> </span><span>=</span><span><span> (</span><span>x</span><span>, </span><span>y</span><span>, </span><span>z</span><span>, </span></span><span>...</span><span><span>args</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>x</span><span>, </span><span>y</span><span>, </span><span>z</span><span>, </span><span>args</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>};</span></div></div><div><div><div>4</div></div><div><span>add</span><span>(</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>, </span><span>5</span><span>, </span><span>6</span><span>, </span><span>7</span><span>, </span><span>8</span><span>, </span><span>9</span><span>);</span><span>//1 2 3 [ 4, 5, 6, 7, 8, 9 ]</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>剩余参数的注意事项<a href="#剩余参数的注意事项"><span>#</span></a></h1><p><strong>箭头函数的剩余参数</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>add</span><span> </span><span>=</span><span> (</span><span>...</span><span><span>args</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>//即使只有一个剩余参数，括号不能省略</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>args</span><span>);</span></span></div></div><div><div><div>4</div></div><div><span>};</span></div></div><div><div><div>5</div></div><div><span>add</span><span>(</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>, </span><span>5</span><span>, </span><span>6</span><span>, </span><span>7</span><span>, </span><span>8</span><span>, </span><span>9</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>代替arguments获取实际参数</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//箭头函数没有arguments</span></div></div><div><div><div>2</div></div><div><span>// const add = () =&gt; {</span></div></div><div><div><div>3</div></div><div><span>//   console.log(arguments);</span></div></div><div><div><div>4</div></div><div><span>// };</span></div></div><div><div><div>5</div></div><div><span>// add(1, 2);</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>//普通函数获取剩余参数</span></div></div><div><div><div>8</div></div><div><span>// const add1 = function () {</span></div></div><div><div><div>9</div></div><div><span>//   console.log(arguments[0]); //{ '0': 1, '1': 2 }类数组</span></div></div><div><div><div>10</div></div><div><span>// };</span></div></div><div><div><div>11</div></div><div><span>// add1(1, 2);</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>//箭头函数获取剩余参数</span></div></div><div><div><div>14</div></div><div><span>const</span><span> </span><span>add</span><span> </span><span>=</span><span> (</span><span>...</span><span><span>args</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>args</span><span>); </span></span><span>//[ 1, 2 ]真数组</span></div></div><div><div><div>16</div></div><div><span>};</span></div></div><div><div><div>17</div></div><div><span>add</span><span>(</span><span>1</span><span>, </span><span>2</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>剩余参数的书写位置</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//剩余参数的书写位置：只能写到最后，否则报错</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>add</span><span> </span><span>=</span><span> (</span><span>...</span><span><span>args</span><span>,</span><span>x</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>args</span><span>); </span></span><span>//[ 1, 2 ]真数组</span></div></div><div><div><div>4</div></div><div><span>};</span></div></div><div><div><div>5</div></div><div><span>add</span><span>(</span><span>1</span><span>, </span><span>2</span><span>);</span><span>//报错</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>剩余参数的应用<a href="#剩余参数的应用"><span>#</span></a></h1><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//参数累加</span></div></div><div><div><div>2</div></div><div><span>// const add = (...args) =&gt; {</span></div></div><div><div><div>3</div></div><div><span>//   let sum = 0;</span></div></div><div><div><div>4</div></div><div><span>//   for (let i = 0; i &lt; args.length; i++) {</span></div></div><div><div><div>5</div></div><div><span>//     sum += args[i];</span></div></div><div><div><div>6</div></div><div><span>//   }</span></div></div><div><div><div>7</div></div><div><span>//   return sum;</span></div></div><div><div><div>8</div></div><div><span>// };</span></div></div><div><div><div>9</div></div><div><span>// console.log(add(1, 2));</span></div></div><div><div><div>10</div></div><div><span>//必须最后一个</span></div></div><div><div><div>11</div></div><div><span>// const [num, ...args] = [1, 2, 3, 4, 5, 6];</span></div></div><div><div><div>12</div></div><div><span>// console.log(num, args);</span></div></div><div><div><div>13</div></div><div><span>//数组参数也能使用</span></div></div><div><div><div>14</div></div><div><span>// const func = ([num, ...args]) =&gt; {</span></div></div><div><div><div>15</div></div><div><span>//   console.log(num, args);</span></div></div><div><div><div>16</div></div><div><span>// };</span></div></div><div><div><div>17</div></div><div><span>// func([1, 2, 3]);</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>// const { x, y, ...z } = { a: 3, x: 1, y: 2, b: 4 };</span></div></div><div><div><div>20</div></div><div><span>// console.log(x, y, z); //输出 1 2 { a: 3, b: 4 }</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>const</span><span> </span><span>func</span><span> </span><span>=</span><span><span> ({ </span><span>x</span><span>, </span><span>y</span><span>, </span></span><span>...</span><span><span>z</span><span> }) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>23</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>x</span><span>, </span><span>y</span><span>, </span><span>z</span><span>);</span></span></div></div><div><div><div>24</div></div><div><span>};</span></div></div><div><div><div>25</div></div><div><span>func</span><span>({ </span><span>a</span><span>:</span><span> </span><span>3</span><span>, </span><span>x</span><span>:</span><span> </span><span>1</span><span>, </span><span>y</span><span>:</span><span> </span><span>2</span><span>, </span><span>b</span><span>:</span><span> </span><span>4</span><span> });</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102105es6-dui-xiang-zi-mian-liang-de-zeng-qiang-yu-han-shu-can-shu-mo-ren-zhi/</id>
      <title type="text">ES6对象字面量的增强与函数参数默认值</title>
      <published>2026-10-21T07:31:36.000Z</published>
      <updated>2026-10-21T07:31:36.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102105es6-dui-xiang-zi-mian-liang-de-zeng-qiang-yu-han-shu-can-shu-mo-ren-zhi/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>对象字面量的增强<a href="#对象字面量的增强"><span>#</span></a></h1><section><h2>属性和方法的简洁表示法<a href="#属性和方法的简洁表示法"><span>#</span></a></h2><p><strong>对象字面量是什么</strong></p><p>在 JavaScript 中用一对 <code>{}</code> 直接创建对象的一种写法</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//这整段 { name: "Alice", age: 20 } 就叫 对象字面量。</span></div></div><div><div><div>2</div></div><div><span>//直接写出来就代表一个值，而不是通过 new 或函数生成</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>4</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>"Alice"</span><span>,</span></div></div><div><div><div>5</div></div><div><span>  </span><span>age</span><span>:</span><span> </span><span>20</span></div></div><div><div><div>6</div></div><div><span>};</span></div></div><div><div><div>7</div></div><div><span>//构造方式（不是字面量）</span></div></div><div><div><div>8</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Object</span><span>();</span></div></div><div><div><div>9</div></div><div><span><span>obj</span><span>.</span></span><span>name</span><span> </span><span>=</span><span> </span><span>"Alice"</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>属性的简洁表示法</strong></p><p>当 <strong>变量名 = 属性名</strong> 时，可以直接写变量名。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//标准</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>name</span><span> </span><span>=</span><span> </span><span>"Alice"</span><span>;</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>age</span><span> </span><span>=</span><span> </span><span>20</span><span>;</span></div></div><div><div><div>4</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>5</div></div><div><span>  </span><span>name</span><span>:</span><span><span> </span><span>name</span><span>,</span></span></div></div><div><div><div>6</div></div><div><span>  </span><span>age</span><span>:</span><span><span> </span><span>age</span></span></div></div><div><div><div>7</div></div><div><span>};</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>//简洁</span></div></div><div><div><div>10</div></div><div><span>const</span><span> </span><span>name</span><span> </span><span>=</span><span> </span><span>"Alice"</span><span>;</span></div></div><div><div><div>11</div></div><div><span>const</span><span> </span><span>age</span><span> </span><span>=</span><span> </span><span>20</span><span>;</span></div></div><div><div><div>12</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>name</span><span>,</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>age</span></div></div><div><div><div>15</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>方法的简洁表示法</strong></p><p>在对象里定义函数时，可以省略 <code>function</code> 关键字和冒号 <code>:</code>。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//传统</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>say</span><span>:</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"Hello"</span><span>);</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>6</div></div><div><span>};</span></div></div><div><div><div>7</div></div><div><span>//简洁</span></div></div><div><div><div>8</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>9</div></div><div><span>  </span><span>say</span><span>() {</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"Hello"</span><span>);</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>方括号语法<a href="#方括号语法"><span>#</span></a></h2><p>方括号语法是 JavaScript 对象字面量里的一种写法，用来动态决定对象的属性名。</p><p><strong>基本用法：</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//传统</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>"Alice"</span></div></div><div><div><div>4</div></div><div><span>};</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj</span><span>.</span></span><span>name</span><span>); </span><span>// Alice</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>//方括号语法</span></div></div><div><div><div>8</div></div><div><span>const</span><span> </span><span>key</span><span> </span><span>=</span><span> </span><span>"name1"</span><span>;</span></div></div><div><div><div>9</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>[</span><span>key</span><span>]</span><span>:</span><span> </span><span>"Alice"</span></div></div><div><div><div>11</div></div><div><span>};</span></div></div><div><div><div>12</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj</span><span>.</span></span><span>name1</span><span>); </span><span>// Alice</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>方括号语法可以放什么</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//方括号里不只是变量，还可以是表达式，只要能求值：</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>[</span><span>"user"</span><span> </span><span>+</span><span> </span><span>"Name"</span><span>]</span><span>:</span><span> </span><span>"Alice"</span></div></div><div><div><div>4</div></div><div><span>};</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj</span><span>.</span></span><span>userName</span><span>); </span><span>// Alice</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h1>函数参数默认值<a href="#函数参数默认值"><span>#</span></a></h1><section><h2>函数参数的默认值是什么<a href="#函数参数的默认值是什么"><span>#</span></a></h2><p>**函数参数的默认值（Default Parameters）**是 ES6 提供的语法，用来给函数的参数设置“默认值”。简单说：<strong>如果调用函数时没传这个参数，就用默认值</strong></p><p><strong>基本语法</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>greet</span><span><span>(</span><span>name</span><span> </span></span><span>=</span><span> </span><span>"Guest"</span><span>) {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"Hello "</span><span> </span><span>+</span><span><span> </span><span>name</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>greet</span><span>();        </span><span>// Hello Guest</span></div></div><div><div><div>5</div></div><div><span>greet</span><span>(</span><span>"Alice"</span><span>); </span><span>// Hello Alice</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>多个参数</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>add</span><span><span>(</span><span>a</span><span> </span></span><span>=</span><span> </span><span>1</span><span><span>, </span><span>b</span><span> </span></span><span>=</span><span> </span><span>2</span><span>) {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>add</span><span>();      </span><span>// 3</span></div></div><div><div><div>6</div></div><div><span>add</span><span>(</span><span>5</span><span>);     </span><span>// 7</span></div></div><div><div><div>7</div></div><div><span>add</span><span>(</span><span>5</span><span>, </span><span>10</span><span>); </span><span>// 15</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>函数参数默认值的注意事项<a href="#函数参数默认值的注意事项"><span>#</span></a></h2><p>只在“undefined”时生效</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>test</span><span><span>(</span><span>x</span><span> </span></span><span>=</span><span> </span><span>10</span><span>) {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>x</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>test</span><span>(</span><span>undefined</span><span>); </span><span>// 10</span></div></div><div><div><div>6</div></div><div><span>test</span><span>(</span><span>null</span><span>);      </span><span>// null ❗不会用默认值</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>默认值可以是表达式</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>getTime</span><span><span>(</span><span>time</span><span> </span></span><span>=</span><span><span> </span><span>Date</span><span>.</span></span><span>now</span><span>()) {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span><span> </span><span>time</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>function</span><span> </span><span>random</span><span><span>(</span><span>num</span><span> </span></span><span>=</span><span><span> </span><span>Math</span><span>.</span></span><span>random</span><span>()) {</span></div></div><div><div><div>5</div></div><div><span>  </span><span>return</span><span><span> </span><span>num</span><span>;</span></span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div><span>//每次调用都会重新计算</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>默认值可以依赖其他参数</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>sum</span><span><span>(</span><span>a</span><span> </span></span><span>=</span><span> </span><span>1</span><span><span>, </span><span>b</span><span> </span></span><span>=</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span> </span><span>1</span><span>) {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>sum</span><span>(); </span><span>// 1 + 2 = 3</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>开发小技巧：默认值最好从右边开始设置</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//左边设置</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>add</span><span> {x</span><span>=</span><span>1</span><span>,</span><span>y</span><span>} </span><span>=&gt;</span><span><span> </span><span>x</span></span><span>+</span><span><span>y</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>add</span><span>(</span><span>undefined</span><span>,</span><span>5</span><span>)</span><span>//6</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>//右边设置</span></div></div><div><div><div>6</div></div><div><span>const</span><span> </span><span>add</span><span> {x,</span><span>y</span><span>=</span><span>1</span><span>} </span><span>=&gt;</span><span><span> </span><span>x</span></span><span>+</span><span><span>y</span><span>;</span></span></div></div><div><div><div>7</div></div><div><span>add</span><span>(</span><span>5</span><span>)</span><span>//6</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>函数参数默认值的应用<a href="#函数参数默认值的应用"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//接受多个参数</span></div></div><div><div><div>2</div></div><div><span>// const logUser = (username = '张三', age = 0, sex = 'male') =&gt; {</span></div></div><div><div><div>3</div></div><div><span>//   console.log(username, age, sex);</span></div></div><div><div><div>4</div></div><div><span>// };</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>// logUser('Alex', 18, 'male');</span></div></div><div><div><div>7</div></div><div><span>// logUser();</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>//接受一个对象</span></div></div><div><div><div>10</div></div><div><span>// const logUser = (options) =&gt; {</span></div></div><div><div><div>11</div></div><div><span>//   console.log(options.username, options.age, options.sex);</span></div></div><div><div><div>12</div></div><div><span>// };</span></div></div><div><div><div>13</div></div><div><span>// logUser({ username: '张三', age: 0, sex: 'male' });</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>//接受一个对象，用解构赋值</span></div></div><div><div><div>16</div></div><div><span>// const logUser = ({ username, age, sex }) =&gt; {</span></div></div><div><div><div>17</div></div><div><span>//   console.log(username, age, sex);</span></div></div><div><div><div>18</div></div><div><span>// };</span></div></div><div><div><div>19</div></div><div><span>// logUser({ username: '张三', age: 0, sex: 'male' });</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>//接受一个对象，用解构赋值，用默认值,如果什么都不传，有问题，不传是undefined，undefined不能解构赋值</span></div></div><div><div><div>22</div></div><div><span>// const logUser = ({ username = '默认名字', age = 0, sex = '未知' }) =&gt; {</span></div></div><div><div><div>23</div></div><div><span>//   console.log(username, age, sex);</span></div></div><div><div><div>24</div></div><div><span>// };</span></div></div><div><div><div>25</div></div><div><span>// logUser({ username: '张三', age: 0 });</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>//</span></div></div><div><div><div>28</div></div><div><span>const</span><span> </span><span>logUser</span><span> </span><span>=</span><span><span> ({ </span><span>username</span><span> </span></span><span>=</span><span> </span><span>'默认名字'</span><span><span>, </span><span>age</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>, </span><span>sex</span><span> </span></span><span>=</span><span> </span><span>'未知'</span><span> } </span><span>=</span><span> {}) </span><span>=&gt;</span><span> {</span></div></div><div><div><div>29</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>username</span><span>, </span><span>age</span><span>, </span><span>sex</span><span>);</span></span></div></div><div><div><div>30</div></div><div><span>};</span></div></div><div><div><div>31</div></div><div><span>logUser</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102104es6-jie-gou-fu-zhi/</id>
      <title type="text">ES6解构赋值</title>
      <published>2026-10-21T06:22:04.000Z</published>
      <updated>2026-10-21T06:22:04.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102104es6-jie-gou-fu-zhi/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>解构赋值是什么<a href="#解构赋值是什么"><span>#</span></a></h1><p><strong>认识解构赋值</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 下标获取数组</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>a</span><span> </span><span>=</span><span><span> </span><span>arr</span><span>[</span></span><span>0</span><span>];</span></div></div><div><div><div>4</div></div><div><span>const</span><span> </span><span>b</span><span> </span><span>=</span><span><span> </span><span>arr</span><span>[</span></span><span>1</span><span>];</span></div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>c</span><span> </span><span>=</span><span><span> </span><span>arr</span><span>[</span></span><span>2</span><span>];</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>);</span></span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>b</span><span>);</span></span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>c</span><span>);</span></span></div></div><div><div><div>9</div></div><div><span>//解构赋值</span></div></div><div><div><div>10</div></div><div><span>const</span><span> [</span><span>a</span><span>, </span><span>b</span><span>, </span><span>c</span><span>] </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];</span></div></div><div><div><div>11</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>, </span><span>c</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>什么是解构赋值</strong>：解析某一数据结构，将我们想要的的东西提取出来，赋值给变量或</p></section>
<section><h1>数组解构赋值的原理<a href="#数组解构赋值的原理"><span>#</span></a></h1><p>模式（结构）匹配</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> [</span><span>a</span><span>, </span><span>b</span><span>, </span><span>c</span><span>] </span><span>=</span><span><span> [</span><span>a</span><span>,</span><span>b</span><span>,</span><span>c</span><span>];</span></span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>, </span><span>c</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>等价于“按位置匹配数组元素”：第 0 位 → a；第 1 位 → b；第 2 位 → c；底层逻辑是：<strong>左边是“结构模板”，右边是“数据源”</strong></p><p>索引值相同的完成赋值</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> [</span><span>a</span><span>, [, , </span><span>b</span><span>], </span><span>c</span><span>] </span><span>=</span><span> [</span><span>1</span><span>, [</span><span>2</span><span>, </span><span>4</span><span>, </span><span>5</span><span>], </span><span>3</span><span>];</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>, </span><span>c</span><span>, </span><span>b</span><span>);</span></span><span>//1,3,5  不取的，可以直接用逗号跳过</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>先求值右侧表达式</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>getArr</span><span>() {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'getArr 被调用'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>  </span><span>return</span><span> [</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>];</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div><span>const</span><span> [</span><span>a</span><span>, </span><span>b</span><span>, </span><span>c</span><span>] </span><span>=</span><span> </span><span>getArr</span><span>();</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>, </span><span>c</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>数组解构赋值的默认值<a href="#数组解构赋值的默认值"><span>#</span></a></h1><p>数组解构赋值的<strong>默认值机制</strong>，本质是：当“取到的值是 undefined 时”，才使用默认值，注意：不是 null，也不是“没有值”，而是 <strong>严格 === undefined</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//基本用法</span></div></div><div><div><div>2</div></div><div><span>const</span><span> [</span><span>a</span><span> </span><span>=</span><span> </span><span>10</span><span>, </span><span>b</span><span> </span><span>=</span><span> </span><span>20</span><span>] </span><span>=</span><span> [];</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>);</span></span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>//正常有值时，不使用默认值</span></div></div><div><div><div>6</div></div><div><span>const</span><span> [</span><span>a</span><span> </span><span>=</span><span> </span><span>10</span><span>, </span><span>b</span><span> </span><span>=</span><span> </span><span>20</span><span>] </span><span>=</span><span> [</span><span>1</span><span>];</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 1</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>b</span><span>); </span></span><span>// 20</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>//只有 undefined 才触发默认值，重点</span></div></div><div><div><div>11</div></div><div><span>const</span><span> [</span><span>a</span><span> </span><span>=</span><span> </span><span>10</span><span>] </span><span>=</span><span> [</span><span>null</span><span>];</span></div></div><div><div><div>12</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// null ❗不是 10</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>//位置缺失才会触发默认值</span></div></div><div><div><div>15</div></div><div><span>const</span><span> [</span><span>a</span><span> </span><span>=</span><span> </span><span>10</span><span>, </span><span>b</span><span> </span><span>=</span><span> </span><span>20</span><span>, </span><span>c</span><span> </span><span>=</span><span> </span><span>30</span><span>] </span><span>=</span><span> [</span><span>1</span><span>, </span><span>undefined</span><span>];</span></div></div><div><div><div>16</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 1</span></div></div><div><div><div>17</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>b</span><span>); </span></span><span>// 20</span></div></div><div><div><div>18</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>c</span><span>); </span></span><span>// 30</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>//默认值可以是表达式（惰性执行）</span></div></div><div><div><div>21</div></div><div><span>function</span><span> </span><span>getValue</span><span>() {</span></div></div><div><div><div>22</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"执行了 getValue"</span><span>);</span></div></div><div><div><div>23</div></div><div><span>  </span><span>return</span><span> </span><span>99</span><span>;</span></div></div><div><div><div>24</div></div><div><span>}</span></div></div><div><div><div>25</div></div><div><span>const</span><span> [</span><span>a</span><span> </span><span>=</span><span> </span><span>getValue</span><span>()] </span><span>=</span><span> [];</span></div></div><div><div><div>26</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>);</span></span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span>//默认值不会重复执行（只在需要时执行）</span></div></div><div><div><div>29</div></div><div><span>const</span><span> [</span><span>a</span><span> </span><span>=</span><span> </span><span>getValue</span><span>()] </span><span>=</span><span> [</span><span>1</span><span>];</span></div></div><div><div><div>30</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>);</span></span><span>//不会打印 "执行了 getValue"因为a 已经是 1不需要默认值</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h1>数组解构赋值的应用<a href="#数组解构赋值的应用"><span>#</span></a></h1><p><strong>快速交换变量</strong>（最经典）：不用临时变量，本质是用数组打包 → 再解构</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>2</div></div><div><span>let</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>[</span><span>a</span><span>, </span><span>b</span><span>] </span></span><span>=</span><span><span> [</span><span>b</span><span>, </span><span>a</span><span>];</span></span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>); </span></span><span>// 2 1</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>函数返回多个值</strong>：替代“返回对象+手动取属性”</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>getUser</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span> [</span><span>"Tom"</span><span>, </span><span>18</span><span>];</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>const</span><span> [</span><span>name</span><span>, </span><span>age</span><span>] </span><span>=</span><span> </span><span>getUser</span><span>();</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>name</span><span>); </span></span><span>// Tom</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>age</span><span>);  </span></span><span>// 18</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>忽略不需要的值</strong>：中间用空位跳过</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> [</span><span>a</span><span>, , </span><span>c</span><span>] </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 1</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>c</span><span>); </span></span><span>// 3</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>结合默认值</strong>（防 undefined）： 常用于接口数据不完整时</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> [</span><span>a</span><span> </span><span>=</span><span> </span><span>10</span><span>, </span><span>b</span><span> </span><span>=</span><span> </span><span>20</span><span>] </span><span>=</span><span> [</span><span>1</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 1</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>b</span><span>); </span></span><span>// 20</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>拆分函数返回的数组</strong>（API常见）：很多“Promise封装库”都这么设计</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> [</span><span>data</span><span>, </span><span>error</span><span>] </span><span>=</span><span> </span><span>await</span><span> </span><span>fetchData</span><span>();</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>if</span><span><span> (</span><span>error</span><span>) {</span></span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"出错了"</span><span>);</span></div></div><div><div><div>5</div></div><div><span>} </span><span>else</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>data</span><span>);</span></span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>处理 split 字符串结果</strong>：超高频使用</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> [</span><span>year</span><span>, </span><span>month</span><span>, </span><span>day</span><span>] </span><span>=</span><span> </span><span>"2026-06-17"</span><span>.</span><span>split</span><span>(</span><span>"-"</span><span>);</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>year</span><span>);  </span></span><span>// 2026</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>month</span><span>); </span></span><span>// 06</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>day</span><span>);   </span></span><span>// 17</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>遍历数组时同时取 index / value</strong>：配合 entries：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>"a"</span><span>, </span><span>"b"</span><span>, </span><span>"c"</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>for</span><span> (</span><span>const</span><span> [</span><span>index</span><span>, </span><span>value</span><span>] </span><span>of</span><span><span> </span><span>arr</span><span>.</span></span><span>entries</span><span>()) {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>index</span><span>, </span><span>value</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>//输出：</span></div></div><div><div><div>7</div></div><div><span>//0 a</span></div></div><div><div><div>8</div></div><div><span>//1 b</span></div></div><div><div><div>9</div></div><div><span>//2 c</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>解构 Map</strong> Map 天然就是可解构结构</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>map</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Map</span><span>([</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>[</span><span>"name"</span><span>, </span><span>"Tom"</span><span>],</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>[</span><span>"age"</span><span>, </span><span>18</span><span>]</span></div></div><div><div><div>4</div></div><div><span>]);</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>for</span><span> (</span><span>const</span><span> [</span><span>key</span><span>, </span><span>value</span><span>] </span><span>of</span><span><span> </span><span>map</span><span>) {</span></span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>key</span><span>, </span><span>value</span><span>);</span></span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>函数参数解构</strong>（非常重要）：直接在参数里解构数组</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>sum</span><span><span>([</span><span>a</span><span>, </span><span>b</span><span>]) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>sum</span><span>([</span><span>3</span><span>, </span><span>5</span><span>])); </span><span>// 8</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>类数组解构</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>fn</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>const</span><span> [</span><span>a</span><span>, </span><span>b</span><span>, </span><span>c</span><span>] </span><span>=</span><span> </span><span>arguments</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>, </span><span>c</span><span>);</span></span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div><span>fn</span><span>(</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>对象解构赋值的原理<a href="#对象解构赋值的原理"><span>#</span></a></h1><p>从对象中快速提取属性并赋值给变量。</p><p>模式（结构）匹配</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>{}</span><span>=</span><span>{}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>属性名相同的完成赋值</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> { </span><span>age</span><span>, </span><span>name</span><span> } </span><span>=</span><span> { </span><span>name</span><span>:</span><span> </span><span>'Alex'</span><span>, </span><span>age</span><span>:</span><span> </span><span>18</span><span> };</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>age</span><span>, </span><span>name</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>对象解构的本质</strong></p><p><strong>对象解构并不是创建新的对象</strong>，而是根据属性名从对象中读取对应的值，然后赋值给变量。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> { </span><span>name</span><span>, </span><span>age</span><span> } </span><span>=</span><span><span> </span><span>user</span><span>;</span></span></div></div><div><div><div>2</div></div><div><span>//本质上等价于</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>name</span><span> </span><span>=</span><span><span> </span><span>user</span><span>.</span></span><span>name</span><span>;</span></div></div><div><div><div>4</div></div><div><span>const</span><span> </span><span>age</span><span> </span><span>=</span><span><span> </span><span>user</span><span>.</span></span><span>age</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>属性重命名</strong></p><p>如果不想使用同名变量，可以进行重命名：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>user</span><span> </span><span>=</span><span> { </span><span>name</span><span>:</span><span> </span><span>'Tom'</span><span>, </span><span>age</span><span>:</span><span> </span><span>18</span><span> };</span></div></div><div><div><div>2</div></div><div><span>const</span><span> { </span><span>name</span><span>: </span><span>userName</span><span> } </span><span>=</span><span><span> </span><span>user</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>//等价于</span></div></div><div><div><div>4</div></div><div><span>// const userName = user.name;</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>userName</span><span>); </span></span><span>// Tom</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>对象解构赋值的注意事项<a href="#对象解构赋值的注意事项"><span>#</span></a></h1><p>对象解构赋值的默认值，默认值仅在属性值为 <code>undefined</code> 时生效。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/**</span></div></div><div><div><div>2</div></div><div><span><span> </span></span><span>* 1. 基本用法：没有对应属性时使用默认值</span></div></div><div><div><div>3</div></div><div><span><span> </span></span><span>*/</span></div></div><div><div><div>4</div></div><div><span>const</span><span> </span><span>obj1</span><span> </span><span>=</span><span> {};</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>const</span><span> { </span><span>a</span><span> </span><span>=</span><span> </span><span>10</span><span>, </span><span>b</span><span> </span><span>=</span><span> </span><span>20</span><span> } </span><span>=</span><span><span> </span><span>obj1</span><span>;</span></span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'1:'</span><span><span>, </span><span>a</span><span>, </span><span>b</span><span>); </span></span><span>// 10 20</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>/**</span></div></div><div><div><div>11</div></div><div><span><span> </span></span><span>* 2. 有值时不使用默认值</span></div></div><div><div><div>12</div></div><div><span><span> </span></span><span>*/</span></div></div><div><div><div>13</div></div><div><span>const</span><span> </span><span>obj2</span><span> </span><span>=</span><span> { </span><span>a</span><span>:</span><span> </span><span>1</span><span> };</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>const</span><span> { </span><span>a</span><span>: </span><span>a2</span><span> </span><span>=</span><span> </span><span>10</span><span>, </span><span>b</span><span>: </span><span>b2</span><span> </span><span>=</span><span> </span><span>20</span><span> } </span><span>=</span><span><span> </span><span>obj2</span><span>;</span></span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'2:'</span><span><span>, </span><span>a2</span><span>); </span></span><span>// 1</span></div></div><div><div><div>18</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'2:'</span><span><span>, </span><span>b2</span><span>); </span></span><span>// 20</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>/**</span></div></div><div><div><div>21</div></div><div><span><span> </span></span><span>* 3. 重点：只有 undefined 才会触发默认值</span></div></div><div><div><div>22</div></div><div><span><span> </span></span><span>* null 不会触发默认值</span></div></div><div><div><div>23</div></div><div><span><span> </span></span><span>*/</span></div></div><div><div><div>24</div></div><div><span>const</span><span> </span><span>obj3</span><span> </span><span>=</span><span> { </span><span>a</span><span>:</span><span> </span><span>null</span><span> };</span></div></div><div><div><div>25</div></div><div>
</div></div><div><div><div>26</div></div><div><span>const</span><span> { </span><span>a</span><span>: </span><span>a3</span><span> </span><span>=</span><span> </span><span>10</span><span> } </span><span>=</span><span><span> </span><span>obj3</span><span>;</span></span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'3:'</span><span><span>, </span><span>a3</span><span>); </span></span><span>// null ❗不是 10</span></div></div><div><div><div>29</div></div><div>
</div></div><div><div><div>30</div></div><div><span>/**</span></div></div><div><div><div>31</div></div><div><span><span> </span></span><span>* 4. 属性缺失 / undefined 才会触发默认值</span></div></div><div><div><div>32</div></div><div><span><span> </span></span><span>*/</span></div></div><div><div><div>33</div></div><div><span>const</span><span> </span><span>obj4</span><span> </span><span>=</span><span> { </span><span>a</span><span>:</span><span> </span><span>1</span><span>, </span><span>b</span><span>:</span><span> </span><span>undefined</span><span> };</span></div></div><div><div><div>34</div></div><div>
</div></div><div><div><div>35</div></div><div><span>const</span><span> { </span><span>a</span><span>: </span><span>a4</span><span> </span><span>=</span><span> </span><span>10</span><span>, </span><span>b</span><span>: </span><span>b4</span><span> </span><span>=</span><span> </span><span>20</span><span>, </span><span>c</span><span>: </span><span>c4</span><span> </span><span>=</span><span> </span><span>30</span><span> } </span><span>=</span><span><span> </span><span>obj4</span><span>;</span></span></div></div><div><div><div>36</div></div><div>
</div></div><div><div><div>37</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'4:'</span><span><span>, </span><span>a4</span><span>); </span></span><span>// 1</span></div></div><div><div><div>38</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'4:'</span><span><span>, </span><span>b4</span><span>); </span></span><span>// 20（undefined -&gt; 默认值）</span></div></div><div><div><div>39</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'4:'</span><span><span>, </span><span>c4</span><span>); </span></span><span>// 30（不存在 -&gt; 默认值）</span></div></div><div><div><div>40</div></div><div>
</div></div><div><div><div>41</div></div><div><span>/**</span></div></div><div><div><div>42</div></div><div><span><span> </span></span><span>* 5. 默认值可以是表达式（惰性执行）</span></div></div><div><div><div>43</div></div><div><span><span> </span></span><span>*/</span></div></div><div><div><div>44</div></div><div><span>function</span><span> </span><span>getValue</span><span>() {</span></div></div><div><div><div>45</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'执行了 getValue()'</span><span>);</span></div></div><div><div><div>46</div></div><div><span>  </span><span>return</span><span> </span><span>99</span><span>;</span></div></div><div><div><div>47</div></div><div><span>}</span></div></div><div><div><div>48</div></div><div>
</div></div><div><div><div>49</div></div><div><span>const</span><span> </span><span>obj5</span><span> </span><span>=</span><span> {};</span></div></div><div><div><div>50</div></div><div>
</div></div><div><div><div>51</div></div><div><span>const</span><span> { </span><span>a</span><span>: </span><span>a5</span><span> </span><span>=</span><span> </span><span>getValue</span><span>() } </span><span>=</span><span><span> </span><span>obj5</span><span>;</span></span></div></div><div><div><div>52</div></div><div>
</div></div><div><div><div>53</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'5:'</span><span><span>, </span><span>a5</span><span>); </span></span><span>// 会触发 getValue()</span></div></div><div><div><div>54</div></div><div>
</div></div><div><div><div>55</div></div><div><span>/**</span></div></div><div><div><div>56</div></div><div><span><span> </span></span><span>* 6. 默认值不会重复执行（只有需要时才执行）</span></div></div><div><div><div>57</div></div><div><span><span> </span></span><span>*/</span></div></div><div><div><div>58</div></div><div><span>const</span><span> </span><span>obj6</span><span> </span><span>=</span><span> { </span><span>a</span><span>:</span><span> </span><span>1</span><span> };</span></div></div><div><div><div>59</div></div><div>
</div></div><div><div><div>60</div></div><div><span>const</span><span> { </span><span>a</span><span>: </span><span>a6</span><span> </span><span>=</span><span> </span><span>getValue</span><span>() } </span><span>=</span><span><span> </span><span>obj6</span><span>;</span></span></div></div><div><div><div>61</div></div><div>
</div></div><div><div><div>62</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'6:'</span><span><span>, </span><span>a6</span><span>);</span></span></div></div><div><div><div>63</div></div><div><span>// 不会执行 getValue()</span></div></div><div><div><div>64</div></div><div>
</div></div><div><div><div>65</div></div><div><span>/**</span></div></div><div><div><div>66</div></div><div><span><span> </span></span><span>* 7. 属性重命名 + 默认值</span></div></div><div><div><div>67</div></div><div><span><span> </span></span><span>*/</span></div></div><div><div><div>68</div></div><div><span>const</span><span> </span><span>obj7</span><span> </span><span>=</span><span> {};</span></div></div><div><div><div>69</div></div><div>
</div></div><div><div><div>70</div></div><div><span>const</span><span> { </span><span>a</span><span>: </span><span>x7</span><span> </span><span>=</span><span> </span><span>10</span><span> } </span><span>=</span><span><span> </span><span>obj7</span><span>;</span></span></div></div><div><div><div>71</div></div><div>
</div></div><div><div><div>72</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'7:'</span><span><span>, </span><span>x7</span><span>); </span></span><span>// 10</span></div></div><div><div><div>73</div></div><div>
</div></div><div><div><div>74</div></div><div><span>/**</span></div></div><div><div><div>75</div></div><div><span><span> </span></span><span>* 8. 嵌套对象解构 + 默认值</span></div></div><div><div><div>76</div></div><div><span><span> </span></span><span>*/</span></div></div><div><div><div>77</div></div><div><span>const</span><span> </span><span>obj8</span><span> </span><span>=</span><span> {};</span></div></div><div><div><div>78</div></div><div>
</div></div><div><div><div>79</div></div><div><span>const</span><span> {</span><span>profile</span><span>: { </span><span>name</span><span>: </span><span>name8</span><span> </span><span>=</span><span> </span><span>'Anonymous'</span><span> } </span><span>=</span><span> {} } </span><span>=</span><span><span> </span><span>obj8</span><span>;</span></span><span>// ⚠️ 防止 profile 是 undefined</span></div></div><div><div><div>80</div></div><div>
</div></div><div><div><div>81</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'8:'</span><span><span>, </span><span>name8</span><span>); </span></span><span>// Anonymous</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>将一个已经声明的变量用于解构赋值</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>2</div></div><div><span>const</span><span> { </span><span>b</span><span> } </span><span>=</span><span> { </span><span>b</span><span>:</span><span> </span><span>2</span><span> };</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>b</span><span>);</span></span><span>//报错</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>var</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>6</div></div><div><span>const</span><span> { </span><span>b</span><span> } </span><span>=</span><span> { </span><span>b</span><span>:</span><span> </span><span>2</span><span> };</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>b</span><span>);</span></span><span>//报错</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>let</span><span><span> </span><span>c</span><span> </span></span><span>=</span><span> </span><span>5</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>[</span><span>c</span><span>] </span></span><span>=</span><span> [</span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>];</span></div></div><div><div><div>11</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>c</span><span>);</span></span><span>//2 覆盖let c = 5</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>const</span><span> </span><span>c</span><span> </span><span>=</span><span> </span><span>5</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>[</span><span>c</span><span>] </span></span><span>=</span><span> [</span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>];</span></div></div><div><div><div>15</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>c</span><span>);</span></span><span>//报错，接口出变量c，c是常量无法更改</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>可以取到继承的属性</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> { </span><span>toString</span><span> } </span><span>=</span><span> {};</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>toString</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>parent</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>10</span></div></div><div><div><div>3</div></div><div><span>};</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span><span> </span><span>Object</span><span>.</span></span><span>create</span><span><span>(</span><span>parent</span><span>);</span></span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>obj</span><span>.</span></span><span>b</span><span> </span><span>=</span><span> </span><span>20</span><span>;</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>const</span><span> { </span><span>a</span><span>, </span><span>b</span><span> } </span><span>=</span><span><span> </span><span>obj</span><span>;</span></span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 10</span></div></div><div><div><div>12</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>b</span><span>); </span></span><span>// 20</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>对象解构：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>obj</span></div></div><div><div><div>2</div></div><div><span><span> </span></span><span>├── </span><span>b</span><span>: </span><span>20</span><span><span> (</span><span>自身属性</span><span>)</span></span></div></div><div><div><div>3</div></div><div><span><span> </span></span><span>└── [[</span><span>Prototype</span><span>]]</span></div></div><div><div><div>4</div></div><div><span><span>       </span></span><span>└── </span><span>a</span><span>: </span><span>10</span><span><span> (</span><span>继承属性</span><span>)</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>解构时：b → 在自身找到；a → 在原型链找到</p><p>常见错误：</p><p>解构 undefined</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> { </span><span>name</span><span> } </span><span>=</span><span> </span><span>undefined</span><span>;</span></div></div><div><div><div>2</div></div><div><span>//报错TypeError: Cannot destructure property 'name' of undefined</span></div></div><div><div><div>3</div></div><div><span>//undefined.name 本身就是非法操作。</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>解构 null</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> { </span><span>name</span><span> } </span><span>=</span><span> </span><span>null</span><span>;</span></div></div><div><div><div>2</div></div><div><span>//TypeError</span></div></div><div><div><div>3</div></div><div><span>//null.name本身就是非法操作。</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>解构只“读取”，不复制结构</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>parent</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>3</div></div><div><span>};</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span><span> </span><span>Object</span><span>.</span></span><span>create</span><span><span>(</span><span>parent</span><span>); </span></span><span>//obj = {} 创建一个新对象 obj，并让它的原型指向 parent</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>const</span><span> { </span><span>a</span><span> } </span><span>=</span><span><span> </span><span>obj</span><span>; </span></span><span>//const a = 1</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span><span>obj</span><span>.</span></span><span>a</span><span> </span><span>=</span><span> </span><span>999</span><span>;</span><span>//这是在解构之后赋值的，所以a还是1，如果写在解构之前，a就是999</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 1 ❗不会变</span></div></div><div><div><div>12</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj</span><span>); </span></span><span>//999</span></div></div><div><div><div>13</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>parent</span><span>.</span></span><span>a</span><span>); </span><span>//1</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>对象解构与数组解构的区别</strong></p>

<table><thead><tr><th>特性</th><th>对象解构</th><th>数组解构</th></tr></thead><tbody><tr><td>匹配方式</td><td>按属性名匹配</td><td>按位置匹配</td></tr><tr><td>是否依赖顺序</td><td>否</td><td>是</td></tr><tr><td>底层原理</td><td>属性读取</td><td>迭代器读取</td></tr><tr><td>典型写法</td><td><code>{ name }</code></td><td><code>[first]</code></td></tr></tbody></table></section>
<section><h1>对象解构赋值的应用<a href="#对象解构赋值的应用"><span>#</span></a></h1><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//函数参数的解构赋值</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>logPersonInfo</span><span> </span><span>=</span><span><span> ({ </span><span>username</span><span>, </span><span>age</span><span> }) </span></span><span>=&gt;</span><span><span> </span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>username</span><span>, </span><span>age</span><span>);</span></span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>logPersonInfo</span><span>({ </span><span>username</span><span>:</span><span> </span><span>'alex'</span><span>, </span><span>age</span><span>:</span><span> </span><span>18</span><span> });</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>//复杂嵌套 模式匹配-跳过的用逗号</span></div></div><div><div><div>7</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>8</div></div><div><span>  </span><span>x</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>9</div></div><div><span>  </span><span>y</span><span>:</span><span> [</span><span>3</span><span>, </span><span>4</span><span>, </span><span>5</span><span>],</span></div></div><div><div><div>10</div></div><div><span>  </span><span>z</span><span>:</span><span> {</span></div></div><div><div><div>11</div></div><div><span>    </span><span>a</span><span>:</span><span> </span><span>5</span><span>,</span></div></div><div><div><div>12</div></div><div><span>    </span><span>b</span><span>:</span><span> </span><span>6</span><span>,</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>14</div></div><div><span>};</span></div></div><div><div><div>15</div></div><div><span>// const { x, y, z } = obj;</span></div></div><div><div><div>16</div></div><div><span>// console.log(x, y, z);</span></div></div><div><div><div>17</div></div><div><span>const</span><span> {</span></div></div><div><div><div>18</div></div><div><span>  </span><span>x</span><span>,</span></div></div><div><div><div>19</div></div><div><span>  </span><span>y</span><span>: [, </span><span>b</span><span>, </span><span>c</span><span>], </span><span>//这个一定要写对属性名，根据属性名匹配</span></div></div><div><div><div>20</div></div><div><span>  </span><span>y</span><span>: </span><span>y</span><span>, </span><span>//第一个y是属性值，第二个y是常量</span></div></div><div><div><div>21</div></div><div><span>  </span><span>y</span><span>, </span><span>//简写</span></div></div><div><div><div>22</div></div><div><span>} </span><span>=</span><span><span> </span><span>obj</span><span>;</span></span></div></div><div><div><div>23</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>b</span><span>, </span><span>y</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h1>其它数据类型的解构赋值<a href="#其它数据类型的解构赋值"><span>#</span></a></h1><p>字符串解构赋值：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//字符串解构赋值，可以数组解构也可以是对象</span></div></div><div><div><div>2</div></div><div><span>const</span><span> [</span><span>a</span><span>, </span><span>b</span><span>, </span><span>c</span><span>, , </span><span>d</span><span>] </span><span>=</span><span> </span><span>'hello'</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>, </span><span>c</span><span>, </span><span>d</span><span>);</span></span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>const</span><span> { </span><span>0</span><span>: </span><span>e</span><span>, </span><span>1</span><span>: </span><span>f</span><span>, </span><span>length</span><span> } </span><span>=</span><span> </span><span>'hello'</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>e</span><span>, </span><span>f</span><span>, </span><span>length</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>数值和布尔值</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 数值和布尔值的解构赋值-没有意义-只能拿到的是方法，不是数字的“结构内容”。</span></div></div><div><div><div>2</div></div><div><span>// 先将右边的值转为对象</span></div></div><div><div><div>3</div></div><div><span>const</span><span> { </span><span>toString</span><span> } </span><span>=</span><span> </span><span>123</span><span>; </span><span>//等价于：const { toString }new Number(123);</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>toString</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span>// 布尔值也一样</span></div></div><div><div><div>6</div></div><div><span>const</span><span> </span><span>flag</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>7</div></div><div><span>const</span><span> { </span><span>toString</span><span>, </span><span>valueOf</span><span> } </span><span>=</span><span><span> </span><span>flag</span><span>;</span></span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>toString</span><span>); </span></span><span>// function toString()</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>undefined和null</p><ul>
<li>这两个没法解构赋值，直接报错</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102103es6-jian-tou-han-shu/</id>
      <title type="text">ES6箭头函数</title>
      <published>2026-10-21T03:01:10.000Z</published>
      <updated>2026-10-21T03:01:10.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102103es6-jian-tou-han-shu/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>箭头函数是什么<a href="#箭头函数是什么"><span>#</span></a></h1><p><strong>认识箭头函数</strong></p><p>箭头函数本质上还是函数，只是写法更短、更清晰。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>add</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>//声明的函数一般不会再赋值，所以一般使用const</span></div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>add</span><span> </span><span>=</span><span><span> (</span><span>a</span><span>, </span><span>b</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>6</div></div><div><span>  </span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>7</div></div><div><span>};</span></div></div><div><div><div>8</div></div><div><span>const</span><span> </span><span>add</span><span> </span><span>=</span><span><span> (</span><span>a</span><span>, </span><span>b</span><span>) </span></span><span>=&gt;</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>箭头函数结构</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>(参数) =&gt; { 函数体 }</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>参数部分：0 个参数：<code>()</code>；1 个参数：可以省略括号；多个参数：必须加括号</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>f1</span><span> </span><span>=</span><span> () </span><span>=&gt;</span><span><span> </span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>"hello"</span><span>);</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>f2</span><span> </span><span>=</span><span><span> </span><span>x</span><span> </span></span><span>=&gt;</span><span><span> </span><span>x</span><span> </span></span><span>*</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>f3</span><span> </span><span>=</span><span><span> (</span><span>x</span><span>, </span><span>y</span><span>) </span></span><span>=&gt;</span><span><span> </span><span>x</span><span> </span></span><span>+</span><span><span> </span><span>y</span><span>;</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>箭头 <code>=&gt;</code>：这是箭头函数的标志，用来连接“参数”和“函数体”。</p><p>函数体：多行代码需要大括号；单行表达式可省略 return 和大括号，自动返回结果</p><p><strong>如何将一般函数改写成箭头函数</strong></p><p>普通函数</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>square</span><span><span>(</span><span>x</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span><span> </span><span>x</span><span> </span></span><span>*</span><span><span> </span><span>x</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>//改成箭头函数</span></div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>square</span><span> </span><span>=</span><span><span> (</span><span>x</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>6</div></div><div><span>  </span><span>return</span><span><span> </span><span>x</span><span> </span></span><span>*</span><span><span> </span><span>x</span><span>;</span></span></div></div><div><div><div>7</div></div><div><span>};</span></div></div><div><div><div>8</div></div><div><span>//再简化</span></div></div><div><div><div>9</div></div><div><span>const</span><span> </span><span>square</span><span> </span><span>=</span><span><span> </span><span>x</span><span> </span></span><span>=&gt;</span><span><span> </span><span>x</span><span> </span></span><span>*</span><span><span> </span><span>x</span><span>;</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>多个参数</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>add</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>//改成箭头函数</span></div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>add</span><span> </span><span>=</span><span><span> (</span><span>a</span><span>, </span><span>b</span><span>) </span></span><span>=&gt;</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>无参数</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>greet</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span> </span><span>"hello"</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>//改成箭头函数</span></div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>greet</span><span> </span><span>=</span><span> () </span><span>=&gt;</span><span> </span><span>"hello"</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>有多行逻辑</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>max</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>if</span><span><span> (</span><span>a</span><span> </span></span><span>&gt;</span><span><span> </span><span>b</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>return</span><span><span> </span><span>a</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>  </span><span>return</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div><span>//改成箭头函数</span></div></div><div><div><div>8</div></div><div><span>const</span><span> </span><span>max</span><span> </span><span>=</span><span><span> (</span><span>a</span><span>, </span><span>b</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>9</div></div><div><span>  </span><span>if</span><span><span> (</span><span>a</span><span> </span></span><span>&gt;</span><span><span> </span><span>b</span><span>) {</span></span></div></div><div><div><div>10</div></div><div><span>    </span><span>return</span><span><span> </span><span>a</span><span>;</span></span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>  </span><span>return</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>13</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>单行对象</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>add</span><span><span>(</span><span>x</span><span>, </span><span>y</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span> { </span><span>value</span><span>:</span><span><span> </span><span>x</span><span> </span></span><span>+</span><span><span> </span><span>y</span><span> };</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>add</span><span>(</span><span>1</span><span>, </span><span>2</span><span>));</span></div></div><div><div><div>5</div></div><div><span>//常规改写</span></div></div><div><div><div>6</div></div><div><span>const</span><span> </span><span>add1</span><span> </span><span>=</span><span><span> (</span><span>x</span><span>, </span><span>y</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>7</div></div><div><span>  </span><span>return</span><span> { </span><span>value</span><span>:</span><span><span> </span><span>x</span><span> </span></span><span>+</span><span><span> </span><span>y</span><span> };</span></span></div></div><div><div><div>8</div></div><div><span>};</span></div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>add1</span><span>(</span><span>1</span><span>, </span><span>2</span><span>));</span></div></div><div><div><div>10</div></div><div><span>//隐式返回对象，箭头函数想直接返回对象，必须用 (),箭头函数没有 return,默认返回undefined</span></div></div><div><div><div>11</div></div><div><span>const</span><span> </span><span>add2</span><span> </span><span>=</span><span><span> (</span><span>x</span><span>, </span><span>y</span><span>) </span></span><span>=&gt;</span><span> ({</span></div></div><div><div><div>12</div></div><div><span>  </span><span>value</span><span>:</span><span><span> </span><span>x</span><span> </span></span><span>+</span><span><span> </span><span>y</span><span>,</span></span></div></div><div><div><div>13</div></div><div><span>});</span></div></div><div><div><div>14</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>add2</span><span>(</span><span>1</span><span>, </span><span>2</span><span>));</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>数组</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>add3</span><span> </span><span>=</span><span><span> (</span><span>x</span><span>, </span><span>y</span><span>) </span></span><span>=&gt;</span><span><span> [</span><span>x</span><span>, </span><span>y</span><span>];</span></span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>add3</span><span>(</span><span>1</span><span>, </span><span>2</span><span>));</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>提前预习：</strong></p><blockquote><p>this 绑定不同：普通函数：this 取决于调用方式；箭头函数：this 继承外层作用域</p></blockquote></section>
<section><h1>箭头函数的注意事项<a href="#箭头函数的注意事项"><span>#</span></a></h1><section><h2>没有自己的 this<a href="#没有自己的-this"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>"Tom"</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>say</span><span>:</span><span> () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>name</span><span>);</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>6</div></div><div><span>};</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span><span>obj</span><span>.</span></span><span>say</span><span>();</span><span>//输出：undefined</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>"Tom"</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>say</span><span>() {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>name</span><span>);</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>6</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>对象方法、类方法不要用箭头函数</p></section><section><h2>不能作为构造函数（不能 new）<a href="#不能作为构造函数不能-new"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>Person</span><span> </span><span>=</span><span><span> (</span><span>name</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>};</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Person</span><span>(</span><span>"Tom"</span><span>); </span><span>// ❌ 报错</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>Person</span><span><span>(</span><span>name</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>p</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Person</span><span>(</span><span>"Tom"</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>构造函数需要this和prototype，但箭头函数没有这两个机制</p></section><section><h2>没有arguments<a href="#没有arguments"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>fn</span><span> </span><span>=</span><span> () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>arguments</span><span>);</span></div></div><div><div><div>3</div></div><div><span>};</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>fn</span><span>(</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>);</span><span>//报错：arguments is not defined</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>fn</span><span> </span><span>=</span><span> (</span><span>...</span><span><span>args</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>args</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>};</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>fn</span><span>(</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>箭头函数必须用 …args 替代 arguments</p></section><section><h2>不能用作 prototype 方法（不适合对象方法）<a href="#不能用作-prototype-方法不适合对象方法"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>Person</span><span><span>(</span><span>name</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>Person</span><span>.</span><span>prototype</span><span>.</span><span>say</span><span> </span><span>=</span><span> () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>name</span><span>);</span></div></div><div><div><div>7</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Person</span><span>.</span><span>prototype</span><span>.</span><span>say</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>name</span><span>);</span></div></div><div><div><div>3</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>原型方法必须用普通函数，如果使用箭头函数，this 指向会错误，变成外层。</p></section><section><h2>不能使用 yield（不能当 Generator）<a href="#不能使用-yield不能当-generator"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>gen</span><span> </span><span>=</span><span> </span><span>*</span><span>() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>yield</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>3</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function*</span><span> </span><span>gen</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>yield</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>语法错误</p><p>总结：箭头函数适合“短逻辑 + 回调”，但不适合“对象方法 + 构造函数 + 需要动态 this 的场景”</p></section></section>
<section><h1>非箭头函数中的 this 指向<a href="#非箭头函数中的-this-指向"><span>#</span></a></h1><p>复习之前的上下文规则：分为全局作用域中this指向和一般函数的this</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 'use strict';</span></div></div><div><div><div>2</div></div><div><span>//console.log(this); //window</span></div></div><div><div><div>3</div></div><div><span>function</span><span> </span><span>add</span><span>() {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>);</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>//只有函数执行才能明确this指向</span></div></div><div><div><div>7</div></div><div><span>//this指向和函数在哪里调用哪调用没关系，只和谁调用有关</span></div></div><div><div><div>8</div></div><div><span>// add(); //非严格模式下window/global 严格模式下undefined</span></div></div><div><div><div>9</div></div><div><span>const</span><span> </span><span>calc</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>10</div></div><div><span>  </span><span>add</span><span>:</span><span><span> </span><span>add</span><span>,</span></span></div></div><div><div><div>11</div></div><div><span>};</span></div></div><div><div><div>12</div></div><div><span><span>calc</span><span>.</span></span><span>add</span><span>(); </span><span>//指向这个对象</span></div></div><div><div><div>13</div></div><div><span>const</span><span> </span><span>adder</span><span> </span><span>=</span><span><span> </span><span>calc</span><span>.</span></span><span>add</span><span>;</span></div></div><div><div><div>14</div></div><div><span>adder</span><span>(); </span><span>//非严格模式下window/global 严格模式下undefined</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li>只有函数执行才能明确this指向</li>
<li>this指向和函数在哪里调用哪调用没关系，只和谁调用有关</li>
</ul></section>
<section><h1>箭头函数中的 this 指向<a href="#箭头函数中的-this-指向"><span>#</span></a></h1><p>箭头函数没有this指向，没有自己的this</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>calc</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>add</span><span>:</span><span> () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>5</div></div><div><span>};</span></div></div><div><div><div>6</div></div><div><span><span>calc</span><span>.</span></span><span>add</span><span>(); </span><span>//window,箭头函数没有自己的this，会往外找this</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//练习</span></div></div><div><div><div>2</div></div><div><span><span>global</span><span>.</span></span><span>a</span><span> </span><span>=</span><span> </span><span>2</span><span>; </span><span>//node环境这么写</span></div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>2</span><span>; </span><span>//浏览器，var会挂在全局window上，let和const不会</span></div></div><div><div><div>4</div></div><div><span>const</span><span> </span><span>calc</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>5</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>6</div></div><div><span>  </span><span>add</span><span>:</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>const</span><span> </span><span>adder</span><span> </span><span>=</span><span> () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>a</span><span>);</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>};</span></div></div><div><div><div>10</div></div><div><span>    </span><span>adder</span><span>();</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>12</div></div><div><span>};</span></div></div><div><div><div>13</div></div><div><span><span>calc</span><span>.</span></span><span>add</span><span>(); </span><span>//箭头函数this，往外找是function 函数，calc.add()this指向calc</span></div></div><div><div><div>14</div></div><div><span>const</span><span> </span><span>adder</span><span> </span><span>=</span><span><span> </span><span>calc</span><span>.</span></span><span>add</span><span>;</span></div></div><div><div><div>15</div></div><div><span>adder</span><span>();</span><span>//2，this指向全局window</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h1>不适用箭头函数的场景<a href="#不适用箭头函数的场景"><span>#</span></a></h1><p>在箭头函数的注意事项已经有提到：</p><ul>
<li>❌ 不能作为构造函数（不能 new）</li>
<li>❌ 需要this指向调用对象的时候</li>
<li>❌ 没有 arguments</li>
</ul></section>
<section><h1>箭头函数的应用<a href="#箭头函数的应用"><span>#</span></a></h1><ul>
<li>按钮点击 → 每秒数字 +1 → 显示在页面</li>
<li>用箭头函数把“多层函数中的 this 丢失问题”变成“稳定继承链”</li>
</ul><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!</span><span>DOCTYPE</span><span> </span><span>html</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>html</span><span> </span><span>lang</span><span>=</span><span>"en"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>head</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>meta</span><span> </span><span>charset</span><span>=</span><span>"UTF-8"</span><span> /&gt;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>&lt;</span><span>title</span><span>&gt;箭头函数的应用&lt;/</span><span>title</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span>      </span><span>body</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>padding: </span><span><span>50</span><span>px</span></span><span> </span><span>0</span><span> </span><span>0</span><span> </span><span><span>250</span><span>px</span></span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>font-size: </span><span><span>30</span><span>px</span></span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>      </span><span>#btn</span><span> {</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>width: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>height: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>15</div></div><div><span><span>        </span></span><span>margin-right: </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>font-size: </span><span><span>30</span><span>px</span></span><span>;</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>cursor: </span><span>pointer</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>21</div></div><div><span><span>  </span></span><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>&lt;</span><span>button</span><span> </span><span>id</span><span>=</span><span>"btn"</span><span>&gt;开始&lt;/</span><span>button</span><span>&gt;</span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>&lt;</span><span>span</span><span> </span><span>id</span><span>=</span><span>"result"</span><span>&gt;0&lt;/</span><span>span</span><span>&gt;</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>26</div></div><div><span>      </span><span>const</span><span> </span><span>btn</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>'btn'</span><span>);</span></div></div><div><div><div>27</div></div><div><span>      </span><span>const</span><span> </span><span>result</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>'result'</span><span>);</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>      </span><span>// const timer = {</span></div></div><div><div><div>30</div></div><div><span>      </span><span>//   time: 0,</span></div></div><div><div><div>31</div></div><div><span>      </span><span>//   start: function () {</span></div></div><div><div><div>32</div></div><div><span>      </span><span>//     // this</span></div></div><div><div><div>33</div></div><div><span>      </span><span>//     var that = this;</span></div></div><div><div><div>34</div></div><div><span>      </span><span>//     // var self = this;</span></div></div><div><div><div>35</div></div><div><span>      </span><span>//     btn.addEventListener(</span></div></div><div><div><div>36</div></div><div><span>      </span><span>//       'click',</span></div></div><div><div><div>37</div></div><div><span>      </span><span>//       function () {</span></div></div><div><div><div>38</div></div><div><span>      </span><span>//         setInterval(function () {</span></div></div><div><div><div>39</div></div><div><span>      </span><span>//           console.log(this);</span></div></div><div><div><div>40</div></div><div><span>      </span><span>//           // this.time++;</span></div></div><div><div><div>41</div></div><div><span>      </span><span>//           // result.innerHTML = this.time;</span></div></div><div><div><div>42</div></div><div><span>      </span><span>//           that.time++;</span></div></div><div><div><div>43</div></div><div><span>      </span><span>//           result.innerHTML = that.time;</span></div></div><div><div><div>44</div></div><div><span>      </span><span>//         }, 1000);</span></div></div><div><div><div>45</div></div><div><span>      </span><span>//       },</span></div></div><div><div><div>46</div></div><div><span>      </span><span>//       false</span></div></div><div><div><div>47</div></div><div><span>      </span><span>//     );</span></div></div><div><div><div>48</div></div><div><span>      </span><span>//   }</span></div></div><div><div><div>49</div></div><div><span>      </span><span>// };</span></div></div><div><div><div>50</div></div><div>
</div></div><div><div><div>51</div></div><div><span>      </span><span>const</span><span> </span><span>timer</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>52</div></div><div><span>        </span><span>time</span><span>:</span><span> </span><span>0</span><span>,</span></div></div><div><div><div>53</div></div><div><span>        </span><span>start</span><span>:</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>54</div></div><div><span>          </span><span>// this</span></div></div><div><div><div>55</div></div><div><span><span>          </span></span><span>btn</span><span>.</span><span>addEventListener</span><span>(</span></div></div><div><div><div>56</div></div><div><span>            </span><span>'click'</span><span>,</span></div></div><div><div><div>57</div></div><div><span><span>            </span></span><span>() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>58</div></div><div><span>              </span><span>// this</span></div></div><div><div><div>59</div></div><div><span>              </span><span>setInterval</span><span>(() </span><span>=&gt;</span><span> {</span></div></div><div><div><div>60</div></div><div><span><span>                </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>);</span></div></div><div><div><div>61</div></div><div><span>                </span><span>this</span><span>.</span><span>time</span><span>++</span><span>;</span></div></div><div><div><div>62</div></div><div><span><span>                </span></span><span>result</span><span>.</span><span>innerHTML</span><span> </span><span>=</span><span> </span><span>this</span><span>.</span><span>time</span><span>;</span></div></div><div><div><div>63</div></div><div><span><span>              </span></span><span>}, </span><span>1000</span><span>);</span></div></div><div><div><div>64</div></div><div><span><span>            </span></span><span>},</span></div></div><div><div><div>65</div></div><div><span>            </span><span>false</span></div></div><div><div><div>66</div></div><div><span><span>          </span></span><span>);</span></div></div><div><div><div>67</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>68</div></div><div><span><span>      </span></span><span>};</span></div></div><div><div><div>69</div></div><div>
</div></div><div><div><div>70</div></div><div><span><span>      </span></span><span>timer</span><span>.</span><span>start</span><span>();</span></div></div><div><div><div>71</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>72</div></div><div><span><span>  </span></span><span>&lt;/</span><span>body</span><span>&gt;</span></div></div><div><div><div>73</div></div><div><span>&lt;/</span><span>html</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><ul>
<li>
<p>this 一共经历了 3 层：</p>
</li>
<li>
<p>第一层：timer.start()</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>timer.start();</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>start 是谁调用的？ this = timer</p>
</li>
<li>
<p>第二层：点击事件函数</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>btn.addEventListener('click', () =&gt; { ... })</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>这里是<strong>箭头函数</strong> ，箭头函数不会绑定自己的 this，它继承外层 this，外层是谁？this = timer</p>
</li>
<li>
<p>第三层：setInterval</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>setInterval(() =&gt; {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>this.time++;</span></div></div><div><div><div>3</div></div><div><span>}, 1000);</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>这里又是箭头函数，外层是 click 箭头函数，click 箭头函数 this = timer，所以最终 this === timer，永远指向 timer</p>
</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102102es6-mo-ban-zi-fu/</id>
      <title type="text">ES6模板字符</title>
      <published>2026-10-21T02:54:08.000Z</published>
      <updated>2026-10-21T02:54:08.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102102es6-mo-ban-zi-fu/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>模板字符串是什么<a href="#模板字符串是什么"><span>#</span></a></h1><p>在 JavaScript 里，模板字符串用 **反引号 “**表示，而不是单引号或双引号。</p><p>基本用法：嵌入变量</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>name</span><span> </span><span>=</span><span> </span><span>"Alice"</span><span>;</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>msg</span><span> </span><span>=</span><span> </span><span>`Hello, </span><span>${</span><span>name</span><span>}</span><span>!`</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>msg</span><span>); </span></span><span>// Hello, Alice!</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>支持表达式</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>5</span><span>;</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>b</span><span> </span><span>=</span><span> </span><span>3</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>`Sum = </span><span>${</span><span>a</span><span> </span><span>+</span><span> </span><span>b</span><span>}</span><span>`</span><span>); </span><span>// Sum = 8</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>支持多行字符串</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>text</span><span> </span><span>=</span><span> </span><span>`第一行</span></div></div><div><div><div>2</div></div><div><span>第二行</span></div></div><div><div><div>3</div></div><div><span>第三行`</span><span>;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>text</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>模板字符串的注意事项<a href="#模板字符串的注意事项"><span>#</span></a></h1><ul>
<li>
<p>必须用反引号</p>
</li>
<li>
<p><code>${}</code> 里可以写任意表达式（函数调用、运算等）</p>
</li>
<li>
<p>在模板字符串中，所有的空格、换行或者缩进都会保留到输出中</p>
</li>
<li>
<p>输出反引号和反斜杆，在前面写反斜杆</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>info</span><span> </span><span>=</span><span> </span><span>`</span><span>\\\`</span><span>`</span><span>;</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>info</span><span>);\\  </span><span>输出</span><span>：\</span></span><span>`</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h1>模板字符串的应用<a href="#模板字符串的应用"><span>#</span></a></h1><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!</span><span>doctype</span><span> </span><span>html</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>html</span><span> </span><span>lang</span><span>=</span><span>"en"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>head</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>meta</span><span> </span><span>charset</span><span>=</span><span>"UTF-8"</span><span> /&gt;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>&lt;</span><span>title</span><span>&gt;模板字符串的应用&lt;/</span><span>title</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span>      </span><span>body</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>padding: </span><span><span>50</span><span>px</span></span><span> </span><span>0</span><span> </span><span>0</span><span> </span><span><span>300</span><span>px</span></span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>font-size: </span><span><span>22</span><span>px</span></span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>      </span><span>ul</span><span> {</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>padding: </span><span>0</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>      </span><span>p</span><span> {</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>margin-bottom: </span><span><span>10</span><span>px</span></span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>21</div></div><div><span><span>  </span></span><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;学生信息表&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>&lt;</span><span>ul</span><span> </span><span>id</span><span>=</span><span>"list"</span><span>&gt;</span></div></div><div><div><div>24</div></div><div><span><span>      </span></span><span>&lt;</span><span>li</span><span> </span><span>style</span><span>=</span><span>"</span><span>list-style: none</span><span>"</span><span>&gt;信息加载中……&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>&lt;/</span><span>ul</span><span>&gt;</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>28</div></div><div><span>      </span><span>// 数据</span></div></div><div><div><div>29</div></div><div><span>      </span><span>const</span><span> </span><span>students</span><span> </span><span>=</span><span> [</span></div></div><div><div><div>30</div></div><div><span><span>        </span></span><span>{</span></div></div><div><div><div>31</div></div><div><span>          </span><span>username</span><span>:</span><span> </span><span>'Alex'</span><span>,</span></div></div><div><div><div>32</div></div><div><span>          </span><span>age</span><span>:</span><span> </span><span>18</span><span>,</span></div></div><div><div><div>33</div></div><div><span>          </span><span>sex</span><span>:</span><span> </span><span>'male'</span><span>,</span></div></div><div><div><div>34</div></div><div><span><span>        </span></span><span>},</span></div></div><div><div><div>35</div></div><div><span><span>        </span></span><span>{</span></div></div><div><div><div>36</div></div><div><span>          </span><span>username</span><span>:</span><span> </span><span>'ZhangSan'</span><span>,</span></div></div><div><div><div>37</div></div><div><span>          </span><span>age</span><span>:</span><span> </span><span>28</span><span>,</span></div></div><div><div><div>38</div></div><div><span>          </span><span>sex</span><span>:</span><span> </span><span>'male'</span><span>,</span></div></div><div><div><div>39</div></div><div><span><span>        </span></span><span>},</span></div></div><div><div><div>40</div></div><div><span><span>        </span></span><span>{</span></div></div><div><div><div>41</div></div><div><span>          </span><span>username</span><span>:</span><span> </span><span>'LiSi'</span><span>,</span></div></div><div><div><div>42</div></div><div><span>          </span><span>age</span><span>:</span><span> </span><span>20</span><span>,</span></div></div><div><div><div>43</div></div><div><span>          </span><span>sex</span><span>:</span><span> </span><span>'female'</span><span>,</span></div></div><div><div><div>44</div></div><div><span><span>        </span></span><span>},</span></div></div><div><div><div>45</div></div><div><span><span>      </span></span><span>];</span></div></div><div><div><div>46</div></div><div>
</div></div><div><div><div>47</div></div><div><span>      </span><span>const</span><span> </span><span>list</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>'list'</span><span>);</span></div></div><div><div><div>48</div></div><div>
</div></div><div><div><div>49</div></div><div><span>      </span><span>let</span><span><span> </span><span>html</span><span> </span></span><span>=</span><span> </span><span>''</span><span>;</span></div></div><div><div><div>50</div></div><div>
</div></div><div><div><div>51</div></div><div><span>      </span><span>for</span><span> (</span><span>let</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>students</span><span>.</span></span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>52</div></div><div><span><span>        </span></span><span>html</span><span> </span><span>+=</span><span> </span><span>`&lt;li&gt;我的名字是：</span><span>${</span><span><span>students</span><span>[</span><span>i</span><span>]</span></span><span>.</span><span>username</span><span>}</span><span>,</span><span>${</span><span><span>students</span><span>[</span><span>i</span><span>]</span></span><span>.</span><span>sex</span><span>}</span><span>,</span><span>${</span><span><span>students</span><span>[</span><span>i</span><span>]</span></span><span>.</span><span>age</span><span>}</span><span>&lt;/li&gt;`</span><span>;</span></div></div><div><div><div>53</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>54</div></div><div>
</div></div><div><div><div>55</div></div><div><span>      </span><span>// console.log(html);</span></div></div><div><div><div>56</div></div><div><span><span>      </span></span><span>list</span><span>.</span><span>innerHTML</span><span> </span><span>=</span><span><span> </span><span>html</span><span>;</span></span></div></div><div><div><div>57</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>58</div></div><div><span><span>  </span></span><span>&lt;/</span><span>body</span><span>&gt;</span></div></div><div><div><div>59</div></div><div><span>&lt;/</span><span>html</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102101es6-chu-shi-he-es6-bian-liang/</id>
      <title type="text">ES6初识和ES6变量</title>
      <published>2026-10-21T00:41:19.000Z</published>
      <updated>2026-10-21T00:41:19.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102101es6-chu-shi-he-es6-bian-liang/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>ES6 简介<a href="#es6-简介"><span>#</span></a></h1><p>ECMAScript 是语言的标准；6 是版本号；ES6 = ECMAScript 这门语言的第 6 代标准</p><p><strong>什么是ECMAScript</strong></p><p>是欧洲计算机制造商协会，一个标准化组织，ECMAScript 是 由 ECMA 这个标准化组织制定的一个语言标准</p><p><strong>具体是什么</strong></p><p>ECMAScript规定了语法和API，ECMAScript = 语法 + API</p><p><strong>历史版本</strong></p><ul>
<li>ES1 ~ 3、ES5 ~ 6</li>
<li>ES4 被废弃了（太激进）</li>
<li>ES3：do while、switch、正则表达式等</li>
<li>ES5：forEach、map、filter、Object.create、Object.defineProperty 等</li>
</ul><p><strong>命名方式</strong></p><ul>
<li>ES6-&gt;ES7-&gt;ES8-&gt;… = ES6+</li>
<li>ES2015-&gt;ES2016-&gt;ES2017-&gt;…</li>
</ul><p><strong>ES 与 JavaScript 的关系</strong></p><ul>
<li>JavaScript(浏览器端) = ECMAScript(语法+API) + DOM + BOM</li>
<li>主流浏览器的最新版本几乎全部支持 ES6</li>
<li>IE 老版本等不支持的浏览器，可以用 Babel 转码</li>
</ul></section>
<section><h1>ES6新增变量let 和 const<a href="#es6新增变量let-和-const"><span>#</span></a></h1><p><strong>let 和 const 是什么</strong></p><ul>
<li><code>let</code> 用来声明<strong>可变变量</strong>。代替var</li>
<li><code>const</code> 用来声明<strong>常量（不可重新赋值的变量）</strong>。</li>
</ul><p><strong>let 和 const 的用法</strong></p><p>let基本用法</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>name</span><span> </span></span><span>=</span><span> </span><span>"Alice"</span><span>;</span></div></div><div><div><div>2</div></div><div><span><span>name</span><span> </span></span><span>=</span><span> </span><span>"Bob"</span><span>; </span><span>// 可以重新赋值</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>const基本用法</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>PI</span><span> </span><span>=</span><span> </span><span>3.14</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>什么是变量，什么是常量</strong></p><ul>
<li>var、let声明的就是变量，变量一旦初始化之后，还可以重新赋值</li>
<li>const声明的就是常量，一旦初始化，就不能重新赋值</li>
</ul><section><h2>const<a href="#const"><span>#</span></a></h2><p><strong>为什么需要 const</strong></p><p>避免变量被误修改（防止 bug）；如果只用 <code>let</code> / <code>var</code>，变量很容易被不小心改掉：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span> </span><span>PI</span><span> </span><span>=</span><span> </span><span>3.14</span><span>;</span></div></div><div><div><div>2</div></div><div><span>PI</span><span> </span><span>=</span><span> </span><span>100</span><span>; </span><span>// ❌ 可能是误操作，但不会报错</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>const</span><span> </span><span>PI</span><span> </span><span>=</span><span> </span><span>3.14</span><span>;</span></div></div><div><div><div>5</div></div><div><span>PI</span><span> </span><span>=</span><span> </span><span>100</span><span>; </span><span>// ❌ 直接报错，防止 bug</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>让代码语义更清晰（可读性更强）；看到 <code>const</code>，别人就能立刻理解：这个值不会变</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>API_URL</span><span> </span><span>=</span><span> </span><span>"https://api.example.com"</span><span>;</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>MAX_COUNT</span><span> </span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>3</div></div><div><span>//相比let</span></div></div><div><div><div>4</div></div><div><span>let</span><span> </span><span>API_URL</span><span> </span><span>=</span><span> </span><span>"..."</span><span>; </span><span>// 不确定会不会变</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>降低维护成本（大型项目很重要）；在大项目中：一个变量被多处引用，如果可以随意修改，很容易出错</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>config</span><span> </span><span>=</span><span> {</span><span>...</span><span>};</span><span>// 防止重新赋值</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>let</span><span><span> </span><span>config</span><span> </span></span><span>=</span><span> {</span><span>...</span><span>};</span><span>// 多个地方可能修改 config</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>符合函数式编程思想；现代前端（React / Vue）倾向：数据尽量不可变（Immutable）</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//不直接修改原数据，更安全</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>list</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];</span></div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>newList</span><span> </span><span>=</span><span> [</span><span>...</span><span><span>list</span><span>, </span></span><span>4</span><span>];</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>提升性能优化空间：虽然 JS 引擎会优化很多情况，但不可变数据更容易优化，更少副作用</p><p><strong>关键误区</strong></p><p>const ≠ “完全不可变”；const 只限制：不能重新赋值（引用不能变）</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>obj</span><span> </span><span>=</span><span> { </span><span>name</span><span>:</span><span> </span><span>"Tom"</span><span> };</span></div></div><div><div><div>2</div></div><div><span><span>obj</span><span>.</span></span><span>name</span><span> </span><span>=</span><span> </span><span>"Jerry"</span><span>; </span><span>// ✔ 可以</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>const 的注意事项</strong></p><ul>
<li>一旦声明，就必须立即初始化，不能留到后面复制；</li>
<li>使用const声明的常量允许在不重新赋值的情况下修改他的值（关键误区）</li>
</ul><p><strong>什么时候用let，什么时候需要使用const</strong></p><ul>
<li><code>let</code> 和 <code>const</code> 的选择核心原则其实很简单：<strong>默认用 const，需要“重新赋值”时才用 let</strong></li>
<li>不会重新赋值的变量用const；引用类型（对象/数组）通常用 const，因为可以修改对象内容，不能整体重新赋值；配置、常量、固定数据用const； 函数 / 导入模块用const</li>
<li>什么时候用 let（必须会变才用）：值会变化的变量；循环变量；需要重新赋值的状态；条件赋值</li>
</ul></section><section><h2>let、const 与 var 的区别<a href="#letconst-与-var-的区别"><span>#</span></a></h2><p><strong>重复声明</strong></p><p>var可以重复声明； let、const不允许重复声明</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>2</span><span>; </span><span>// ✔ 不报错；容易出 bug</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 2</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>let</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>6</div></div><div><span>let</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>2</span><span>; </span><span>// ❌ 报错</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>const</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>9</div></div><div><span>const</span><span> </span><span>a</span><span> </span><span>=</span><span> </span><span>2</span><span>; </span><span>// ❌ 报错</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>function</span><span> </span><span>fun</span><span><span>(</span><span>a</span><span>){</span></span></div></div><div><div><div>12</div></div><div><span>    </span><span>let</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span><span>//❌ 报错</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>变量提升</strong></p><p>var存在变量提升，但值是 undefined；</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// undefined</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>3</div></div><div><span>//等价于</span></div></div><div><div><div>4</div></div><div><span>var</span><span><span> </span><span>a</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>);</span></span></div></div><div><div><div>6</div></div><div><span><span>a</span><span> </span></span><span>=</span><span> </span><span>10</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>let / const：也会提升，但不能访问;暂时性死区</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>console.log(a); // ❌ 报错</span></div></div><div><div><div>2</div></div><div><span>let a = 10;</span></div></div><div><div><div>3</div></div><div><span>console.log(b); // ❌ 报错</span></div></div><div><div><div>4</div></div><div><span>const b = 20;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这里的a已经被提升，但是未被初始化，此时处于暂时性死区，变量已经存在，但不能访问它的值，访问这些变量会导致<code>ReferenceError</code>错误</p><p>变量的声明周期：声明（在作用域内声明这个变量，此时变量已被标记为存在。）——- 初始化（在内存中为这个变量开辟一块空间，此时由于没有赋值，所以会初始化为undefined。） ——— 赋值（将值赋给这个变量。）</p><blockquote><p><strong>var:</strong> 在执行上下文执行之前的预解析阶段，会有<strong>声明提升</strong>，和<strong>初始化提升</strong>，这时js会把var存放在变量环境中(你可以简单理解为一个存放变量的地方，函数声明也会放在这个地方)，且值为undefined，因此我们可以提前访问，结果为undefined。</p><p><strong>let:</strong> 在执行上下文执行之前的预解析阶段，仅有<strong>声明提升</strong>，不会给它初始化，更不会给他赋值，此时存储中有这个变量，但我们无法访问。（let和const存放在词法环境中，你可以简单理解为另一个地方）这也就是所说的<strong>暂时性死区</strong>当执行到真正的赋值语句的时候，才会执行初始化操作并赋值。</p><p><strong>const：</strong> 与<strong>let</strong>的创建顺序基本一致，仅有 <strong>声明提升</strong>，但非常重要的区别是const本身不存在赋值这一个概念，当执行到 <code>const a = 2</code>时，是直接将const初始化为2。也就是我们所说的<strong>const是常量</strong>。因为它根本无法赋值，也因此在声明时必须给它一个值。（相当于Promise内部状态只能修改一次，因为Promise源码里后续也没有为状态赋值的操作。） 而对于引用数据类型来说，const初始化的是一个栈内存里分配的指针。你虽然无法修改指针的指向，但可以修改指针指向的堆里面的内容，也就是我们所说的<strong>cosnt声明的引用数据类型可以更改</strong>。</p><p>作者：孙泓旻
链接：<a href="https://juejin.cn/post/7209939789808812093" target="_blank">https://juejin.cn/post/7209939789808812093</a>
来源：稀土掘金
著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。</p></blockquote><p><strong>暂时性死区</strong></p><p>只要作用域内存在let、const，它们所声明的变量或常量就自动”绑定”这个区域，不再受到外部作用域的影响</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>2</div></div><div><span>let</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span> </span><span>4</span><span>;</span></div></div><div><div><div>3</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>4</div></div><div><span>  </span><span>//console.log(a);//应为函数作用域绑定了a，所以没法往外找，报错</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>b</span><span>); </span></span><span>//相反，函数作用域内没找到b，就往外找</span></div></div><div><div><div>6</div></div><div><span>  </span><span>//let a = 1;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div><span>fun</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>window 对象的属性和方法（全局作用域中）</strong></p><p>var会挂到 window 上，全局污染问题</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>window</span><span>.</span></span><span>a</span><span>); </span><span>// 10</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>let / const：不会挂到 window， 更安全，不污染全局对象</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>b</span><span> </span><span>=</span><span> </span><span>20</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>window</span><span>.</span></span><span>a</span><span>); </span><span>// undefined</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>window</span><span>.</span></span><span>b</span><span>); </span><span>// undefined</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>块级作用域</strong></p><p>var没有块级作用域（只有函数作用域）</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>if</span><span> (</span><span>true</span><span>) {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 10，if / for 里的变量“泄露”到外面</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>for</span><span> (</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span> </span><span>3</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>i</span><span>);</span></span></div></div><div><div><div>8</div></div><div><span>}</span></div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>i</span><span>); </span></span><span>//3</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>let / const：有块级作用域</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>if</span><span> (</span><span>true</span><span>) {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>let</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>3</div></div><div><span>  </span><span>const</span><span> </span><span>b</span><span> </span><span>=</span><span> </span><span>20</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// ❌ 报错</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>b</span><span>); </span></span><span>// ❌ 报错</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>for</span><span> (</span><span>let</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>a</span><span> </span></span><span>&lt;</span><span> </span><span>3</span><span><span>; </span><span>a</span></span><span>++</span><span>) {</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>a</span><span>);</span></span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>//❌ 报错</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>作用域链</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>2</div></div><div><span>function</span><span> </span><span>foo</span><span>() {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>let</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>4</div></div><div><span>  </span><span>function</span><span> </span><span>bar</span><span>() {</span></div></div><div><div><div>5</div></div><div><span>    </span><span>let</span><span><span> </span><span>c</span><span> </span></span><span>=</span><span> </span><span>3</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// ?1</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>b</span><span>); </span></span><span>// ?2</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>c</span><span>); </span></span><span>// ?3</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span>  </span><span>bar</span><span>();</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>foo</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>查找过程（关键）</p><p>1️⃣ 找 c</p><p>在 bar 内部 → 直接找到</p><p>2️⃣ 找 b</p><p>bar 没有 → 去上一层 foo → 找到</p><p>3️⃣ 找 a</p><p>bar 没有 → foo 没有 → 去全局 → 找到</p><p>总结：函数定义时的作用域嵌套关系，而不是调用时决定的，访问变量时：先在当前作用域找，找不到 → 去上一级作用域，一直找到全局作用域，还找不到 → 报错 <code>ReferenceError</code></p><p>常见误区：</p><ul>
<li>作用域链是运行时决定的；错！作用域链在<strong>函数定义时就已经确定</strong></li>
<li>跟 this 是一回事；完全不同：作用域链作用是找变量；this作用指向对象</li>
</ul><p><strong>总结</strong></p>

<table><thead><tr><th>特性</th><th>var</th><th>let</th><th>const</th></tr></thead><tbody><tr><td>重复声明</td><td>✔ 可以</td><td>❌ 不可以</td><td>❌ 不可以</td></tr><tr><td>变量提升</td><td>✔ 有（undefined）</td><td>✔ 有（TDZ）</td><td>✔ 有（TDZ）</td></tr><tr><td>暂时性死区</td><td>❌ 没有</td><td>✔ 有</td><td>✔ 有</td></tr><tr><td>块级作用域</td><td>❌ 没有</td><td>✔ 有</td><td>✔ 有</td></tr><tr><td>window属性</td><td>✔ 会挂载</td><td>❌ 不会</td><td>❌ 不会</td></tr></tbody></table></section><section><h2>let 和 const 的应用<a href="#let-和-const-的应用"><span>#</span></a></h2><p>示例：点击按钮1打印1，点击按钮2打印2，点击按钮3打印3</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>  </span></span><span>&lt;</span><span>button</span><span> </span><span>class</span><span>=</span><span>"btn"</span><span>&gt;1&lt;/</span><span>button</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>button</span><span> </span><span>class</span><span>=</span><span>"btn"</span><span>&gt;2&lt;/</span><span>button</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>button</span><span> </span><span>class</span><span>=</span><span>"btn"</span><span>&gt;3&lt;/</span><span>button</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>    </span><span>var</span><span><span> </span><span>btns</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelectorAll</span><span>(</span><span>'.btn'</span><span>);</span></div></div><div><div><div>6</div></div><div><span>    </span><span>for</span><span> (</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>btns</span><span>.</span></span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>7</div></div><div><span><span>      </span></span><span>btns</span><span>[</span><span>i</span><span>].</span><span>addEventListener</span><span>(</span><span>'click'</span><span>, </span><span>function</span><span> () {</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>i</span><span>); </span></span><span>//都是3</span></div></div><div><div><div>9</div></div><div><span><span>      </span></span><span>});</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>为什么打印出来都是3？</strong></p><p>因为点击的时候：for 循环已经执行完了，i 早就变成 3 了</p><p>拆解：</p><p>1️⃣ var 没有块级作用域</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for (var i = 0; i &lt; 3; i++) {}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>等价于：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var i; // 只有一个 i</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>👉 只有一个共享的 i</p><p>2️⃣ addEventListener 里的函数“没有立即执行”</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> () {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>i</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>👉 它只是“注册”，不是执行</p><p>3️⃣ 点击发生时才执行函数</p><p>当你真正点击时：</p><p>👉 for 循环早就结束了</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>i === 3</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>4️⃣ 作用域链在找 i</p><p>点击时执行函数：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>console.log(i);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>查找过程：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>当前函数作用域 → 没有 i</span></div></div><div><div><div>2</div></div><div><span>外层作用域（for 所在函数 / 全局）→ i = 3</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>👉 所以打印 3</p><p>闭包方式解决：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>  </span></span><span>&lt;</span><span>button</span><span> </span><span>class</span><span>=</span><span>"btn"</span><span>&gt;1&lt;/</span><span>button</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>button</span><span> </span><span>class</span><span>=</span><span>"btn"</span><span>&gt;2&lt;/</span><span>button</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>button</span><span> </span><span>class</span><span>=</span><span>"btn"</span><span>&gt;3&lt;/</span><span>button</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>    </span><span>var</span><span><span> </span><span>btns</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelectorAll</span><span>(</span><span>'.btn'</span><span>);</span></div></div><div><div><div>6</div></div><div><span>    </span><span>for</span><span> (</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>btns</span><span>.</span></span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>7</div></div><div><span><span>      </span></span><span>(</span><span>function</span><span><span> (</span><span>index</span><span>) {</span></span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>btns</span><span>[</span><span>index</span><span>].</span><span>addEventListener</span><span>(</span><span>'click'</span><span>, </span><span>function</span><span> () {</span></div></div><div><div><div>9</div></div><div><span><span>          </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>index</span><span> </span></span><span>+</span><span> </span><span>1</span><span>);</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>});</span></div></div><div><div><div>11</div></div><div><span><span>      </span></span><span>})(</span><span>i</span><span>);</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li>立即执行函数形成了函数作用域，这个函数作用域会保存这个index，当点击的时候触发点击事件，向外找这个index</li>
</ul><p>正确示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>  </span></span><span>&lt;</span><span>button</span><span> </span><span>class</span><span>=</span><span>"btn"</span><span>&gt;1&lt;/</span><span>button</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>button</span><span> </span><span>class</span><span>=</span><span>"btn"</span><span>&gt;2&lt;/</span><span>button</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>button</span><span> </span><span>class</span><span>=</span><span>"btn"</span><span>&gt;3&lt;/</span><span>button</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>    </span><span>var</span><span><span> </span><span>btns</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelectorAll</span><span>(</span><span>'.btn'</span><span>);</span></div></div><div><div><div>6</div></div><div><span>    </span><span>for</span><span> (</span><span>let</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>btns</span><span>.</span></span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>7</div></div><div><span><span>      </span></span><span>btns</span><span>[</span><span>i</span><span>].</span><span>addEventListener</span><span>(</span><span>'click'</span><span>, </span><span>function</span><span> () {</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>i</span><span> </span></span><span>+</span><span> </span><span>1</span><span>);</span></div></div><div><div><div>9</div></div><div><span><span>      </span></span><span>});</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li>let 在 for 循环中有一个特殊机制：每一轮循环，都会创建一个<strong>新的 i 绑定</strong></li>
<li>let 的本质：形成多个闭包环境；每个循环</li>
</ul></section></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102009javascript-zheng-ze-biao-da-shin/</id>
      <title type="text">JavaScript正则表达式</title>
      <published>2026-10-20T10:37:18.000Z</published>
      <updated>2026-10-20T10:37:18.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102009javascript-zheng-ze-biao-da-shin/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>本文学习JavaScript正则表达式，内容很复杂，但是现在AI流行的情况下，完全可以让AI写，但是作为开发人员，还是必须懂这些内容的</p>
<section><h1>什么是正则表达式<a href="#什么是正则表达式"><span>#</span></a></h1><ul>
<li>正则表达式（regular expression）描述了字符串的“构 成模式”，经常被用于检查字符串是否符合预定的格式要求</li>
</ul><p><strong>快速感知正则表达式</strong></p><ul>
<li>
<p>用一个例子快速演示正则表达式基本使用方法：检查某个字 符串是否是6位数字</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 要检查的字符串</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>str</span><span> </span></span><span>=</span><span> </span><span>'456789'</span><span>;</span></div></div><div><div><div>3</div></div><div><span>// 正则表达式规则</span></div></div><div><div><div>4</div></div><div><span>var</span><span><span> </span><span>regexp</span><span> </span></span><span>=</span><span> /</span><span>^</span><span>\d</span><span>{6}</span><span>$</span><span>/</span><span>;</span><span>///^\d{6}$/就是正则表达式，，它描述了字符串必须是“6位数字”的构成规则</span></div></div><div><div><div>5</div></div><div><span>// 检查</span></div></div><div><div><div>6</div></div><div><span>if</span><span><span> (</span><span>regexp</span><span>.</span></span><span>test</span><span><span>(</span><span>str</span><span>)) {</span></span><span>//正则表达式可以调用test()方法，检查某字符串是否符合正则表达式规定的规则</span></div></div><div><div><div>7</div></div><div><span>  </span><span>//alert('符合规则');</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'符合规则'</span><span>);</span></div></div><div><div><div>9</div></div><div><span>} </span><span>else</span><span> {</span></div></div><div><div><div>10</div></div><div><span>  </span><span>//alert('不符合规则');</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'不符合规则'</span><span>);</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>正则表达式“按位”描述规则</strong></p><ul>
<li>
<p>正则表达式“按位”描述规则，是指它是一位一位的描述字 符串的构成形式</p>
</li>
<li>
<p>比如检查字符串是不是这样的：以字母m开头，然后是3个数 字，最后以字母n结尾</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/</span><span>^</span><span>m</span><span>\d\d\d</span><span>n</span><span>$</span><span>/</span><span>   </span><span>//^表示开头，$表示结尾，\d表示数字\d\d\d也可以写作\d{3}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h1>正则表达式的创建<a href="#正则表达式的创建"><span>#</span></a></h1><ul>
<li>
<p>使用/内容/的语法形式，可以快速创建正则表达式</p>
</li>
<li>
<p>也可以使用new RegExp(‘内容’)的形式，创建正则表达式</p>
</li>
<li>
<p>使用typeof运算符检查正则表达式的类型，结果是object</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>regexp1</span><span> </span></span><span>=</span><span> /</span><span>^</span><span>\d</span><span>{6}</span><span>$</span><span>/</span><span>;</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>regexp2</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>RegExp</span><span>(</span><span>'^</span><span>\\</span><span>d{6}$'</span><span>);</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>var</span><span><span> </span><span>str</span><span> </span></span><span>=</span><span> </span><span>'123456'</span><span>;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>regexp1</span><span>.</span></span><span>test</span><span><span>(</span><span>str</span><span>));</span></span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>regexp2</span><span>.</span></span><span>test</span><span><span>(</span><span>str</span><span>));</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h1>元字符<a href="#元字符"><span>#</span></a></h1><p>元字符”是指一位指定类型的字符</p>

<table><thead><tr><th>元字符</th><th>功能</th></tr></thead><tbody><tr><td>\d</td><td>匹配一个数字</td></tr><tr><td>\D</td><td>匹配一个非数字字符</td></tr><tr><td>\w</td><td>匹配一个单字字符（字母、数字或者下划线）</td></tr><tr><td>\W</td><td>匹配一个非单字字符</td></tr><tr><td>\s</td><td>匹配一个空白字符，包括空格、制表符和换行符</td></tr><tr><td>.</td><td>任意字符</td></tr></tbody></table><p>开头和结尾</p>

<table><thead><tr><th>元字符</th><th>功能</th></tr></thead><tbody><tr><td>^</td><td>匹配开头</td></tr><tr><td>$</td><td>匹配结尾</td></tr></tbody></table><p><strong>元字符注意事项</strong></p><ul>
<li>如果使用new RegExp()写法，反斜杠需要多写一个</li>
<li>比如<code>/^\d$</code>/和<code>new RegExp('^\\d$')</code>是相同的意思</li>
</ul><p><strong>元字符使用举例</strong></p><ul>
<li>
<p>某快递公司运单号形式是这样的：123-4567-890，请使用 正则表达式检查某字符串是否符合此格式</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>reg</span><span> </span><span>=</span><span> /</span><span>^</span><span>\d</span><span><span>{3}</span><span>-</span></span><span>\d</span><span><span>{4}</span><span>-</span></span><span>\d</span><span>{3}</span><span>$</span><span>/</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"123-4567-890"</span><span>)); </span><span>// true</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"12-4567-890"</span><span>));   </span><span>// false</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"123-456-890"</span><span>));   </span><span>// false</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"123-4567-8901"</span><span>)); </span><span>// false</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>某产品的验证秘钥形式是这样的：□□□-□□□□-□□□，其中□ 表示字母数字或者下划线，请使用正则表达式检查某字符串 是否符合此格式</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>reg</span><span> </span><span>=</span><span> /</span><span>^</span><span>[A-Za-z0-9_]</span><span><span>{3}</span><span>-</span></span><span>[A-Za-z0-9_]</span><span><span>{4}</span><span>-</span></span><span>[A-Za-z0-9_]</span><span>{3}</span><span>$</span><span>/</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"a1_-B2c3-9Zx"</span><span>));   </span><span>// true</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abc-1234-xyz"</span><span>));   </span><span>// true</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"ab-1234-xyz"</span><span>));    </span><span>// false（第一段少1位）</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abc-123-xyz"</span><span>));    </span><span>// false（第二段少1位）</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abc1234xyz"</span><span>));     </span><span>// false（缺少 -）</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>字符的转义</strong></p><ul>
<li>在特殊字符之前的反斜杠\表示下一个字符不是特殊字符，应 该按照字面理解</li>
</ul><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/</span><span>^</span><span>.</span><span>$</span><span>/</span><span><span> </span><span>检查字符串是不是任意字符</span></span></div></div><div><div><div>2</div></div><div><span>/</span><span>^</span><span>\.</span><span>$</span><span>/</span><span>检查字符串是不是一个点</span></div></div><div><div><div>3</div></div><div><span>/</span><span>^</span><span>\\</span><span>$</span><span>/</span><span>检查字符串是不是一个反斜杠</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li>
<p>不管一个符号有没有特殊意义，都可以在其之前加上一个\以 确保它表达的是这个符号本身</p>
</li>
<li>
<p>举例：某产品批号形式为：123.45^67#89，请使用正则表 达式检查某字符串是否符合此格式</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>reg</span><span> </span><span>=</span><span> /</span><span>^</span><span>\d</span><span><span>{3}</span><span>\.</span></span><span>\d</span><span><span>{2}</span><span>\^</span></span><span>\d</span><span><span>{2}</span><span>#</span></span><span>\d</span><span>{2}</span><span>$</span><span>/</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"123.45^67#89"</span><span>)); </span><span>// true</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"12.45^67#89"</span><span>));  </span><span>// false</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"123.4^67#89"</span><span>));  </span><span>// false</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"123.45^67#890"</span><span>)); </span><span>// false</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abc.45^67#89"</span><span>));  </span><span>// false</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h1>方括号表示法<a href="#方括号表示法"><span>#</span></a></h1><ul>
<li>
<p>使用方括号，比如[xyz]，可以创建一个字符集合，表示匹 配方括号中的任意字符</p>
</li>
<li>
<p>比如某学校的学号规定：第1位是一个字母，b表示本科生， y表示研究生，后面是7位数字，用正则表示为：</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/</span><span>^</span><span><span>[by]</span><span>\d</span></span><span>{7}</span><span>$</span><span>/</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>可以使用短横-来指定一个字符范围，^表示否定</p>
</li>
</ul>

<table><thead><tr><th>元字符</th><th>等价的方括号表示法</th></tr></thead><tbody><tr><td>\d</td><td>[0-9]</td></tr><tr><td>\D</td><td><a href="https://blog.youzi177.cn/posts/4e85250a#fn_0-9" target="_blank">0-9</a></td></tr><tr><td>\w</td><td>[A-Za-z0-9_]</td></tr><tr><td>\W</td><td><a href="https://blog.youzi177.cn/posts/4e85250a#fn_A-Za-z0-9_" target="_blank">A-Za-z0-9_</a></td></tr></tbody></table><ul>
<li>
<p>请验证某字符串是否是5位字母，大小写均可</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>reg</span><span> </span><span>=</span><span> /</span><span>^</span><span>[A-Za-z]</span><span>{5}</span><span>$</span><span>/</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abcde"</span><span>)); </span><span>// true</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"ABCDE"</span><span>)); </span><span>// true</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"AbCdE"</span><span>)); </span><span>// true</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abcd"</span><span>));   </span><span>// false（少1位）</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abcdef"</span><span>));  </span><span>// false（多1位）</span></div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abc12"</span><span>));   </span><span>// false（含数字）</span></div></div><div><div><div>10</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abc_d"</span><span>));   </span><span>// false（含下划线）</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>请验证某字符串是否是5位，且仅有小写字母、点构 成</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>reg</span><span> </span><span>=</span><span> /</span><span>^</span><span><span>[a-z</span><span>.</span><span>]</span></span><span>{5}</span><span>$</span><span>/</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abcde"</span><span>)); </span><span>// true</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"a.b.c"</span><span>));  </span><span>// true</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"ab.cd"</span><span>));  </span><span>// true</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"ABcde"</span><span>));  </span><span>// false（有大写）</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abc12"</span><span>));  </span><span>// false（有数字）</span></div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abcd"</span><span>));    </span><span>// false（少1位）</span></div></div><div><div><div>10</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abcdef"</span><span>));  </span><span>// false（多1位）</span></div></div><div><div><div>11</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abc_d"</span><span>));   </span><span>// false（有下划线）</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>请验证某字符串是否是4位小写字母，且最后一位不 能是m字母</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>reg</span><span> </span><span>=</span><span> /</span><span>^</span><span>[a-z]</span><span>{3}</span><span>[a-ln-z]</span><span>$</span><span>/</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abcd"</span><span>)); </span><span>// true</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abcz"</span><span>)); </span><span>// true</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abcm"</span><span>)); </span><span>// false ❌（最后是m）</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abc"</span><span>));  </span><span>// false（少1位）</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"abcde"</span><span>)); </span><span>// false（多1位）</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h1>量词<a href="#量词"><span>#</span></a></h1>

<table><thead><tr><th>量词</th><th>意义</th></tr></thead><tbody><tr><td>*</td><td>匹配前一个表达式0次或多次。等价于{0,}</td></tr><tr><td>+</td><td>匹配前面一个表达式1次或者多次。等价于{1,}</td></tr><tr><td>?</td><td>匹配前面一个表达式0次或者1次。等价于{0,1}</td></tr><tr><td>{n}</td><td>n是一个正整数，匹配了前面一个字符刚好出现了n次</td></tr><tr><td>{n,}</td><td>n是一个正整数，匹配前一个字符至少出现了n次</td></tr><tr><td>.{n,m}</td><td>n和m都是整数。匹配前面的字符至少n次，最多m次</td></tr></tbody></table><ul>
<li>
<p>请验证字符串是否符合手机号码的规则：11位数字 ，并且肯定以1开头</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>reg</span><span> </span><span>=</span><span> /</span><span>^</span><span>1</span><span>\d</span><span>{10}</span><span>$</span><span>/</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"13812345678"</span><span>)); </span><span>// true</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"19876543210"</span><span>)); </span><span>// true</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"23812345678"</span><span>)); </span><span>// false（不是1开头）</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"1381234567"</span><span>));  </span><span>// false（少1位）</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"138123456789"</span><span>)); </span><span>// false（多1位）</span></div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"1a812345678"</span><span>));  </span><span>// false（含字母）</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>请验证某字符串是否是这样的：以字母开头，中间是 任意位数字（最少1位）构成，并以字母结尾</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>reg</span><span> </span><span>=</span><span> /</span><span>^</span><span><span>[A-Za-z]</span><span>\d</span></span><span>+</span><span>[A-Za-z]</span><span>$</span><span>/</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"a123b"</span><span>));   </span><span>// true</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"Z9x"</span><span>));     </span><span>// true</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"a1"</span><span>));      </span><span>// false（结尾不是字母）</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"123a"</span><span>));    </span><span>// false（开头不是字母）</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"a12b3"</span><span>));   </span><span>// false（结尾不是字母）</span></div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"ab"</span><span>));      </span><span>// false（中间没有数字）</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>请验证某字符串是否符合网址规则：以www.开头， 中间是任意位的字符（字母数字下划线），最后以.com结尾 ，也可以以.com.cn结尾</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>reg</span><span> </span><span>=</span><span> /</span><span>^</span><span><span>www</span><span>\.</span></span><span>\w</span><span><span>+</span><span>(?:</span><span>\.</span><span>com</span><span>|</span><span>\.</span><span>com</span><span>\.</span><span>cn)</span></span><span>$</span><span>/</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"www.baidu.com"</span><span>));      </span><span>// true</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"www_baidu.com.cn"</span><span>));   </span><span>// true</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"www_abc123.com"</span><span>));     </span><span>// true</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"http://www.baidu.com"</span><span>));</span><span>// false（多了http）</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"www.baidu.net"</span><span>));       </span><span>// false（不支持.net）</span></div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"www..com"</span><span>));            </span><span>// false（中间为空）</span></div></div><div><div><div>10</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>reg</span><span>.</span></span><span>test</span><span>(</span><span>"ww.baidu.com"</span><span>));        </span><span>// false（不是www开头）</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h1>修饰符<a href="#修饰符"><span>#</span></a></h1><ul>
<li>修饰符也叫作标志（flags），用于使用正则表达式实现高级搜索</li>
</ul>

<table><thead><tr><th>修饰符</th><th>意义</th></tr></thead><tbody><tr><td>i</td><td>不区分大小写搜索</td></tr><tr><td>g</td><td>全局搜索</td></tr></tbody></table><p><strong>修饰符的使用：</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>re</span><span> </span></span><span>=</span><span> /m/</span><span>gi</span><span>; </span><span>//在正则表达式的第二个/后面写修饰符，可以多个连写</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>re</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>RegExp</span><span>(</span><span>'m'</span><span>,</span><span>'gi'</span><span>);</span><span>//new RegExp()形式的正则表达式，以字符串形式写在第二个参数</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>正则表达式的相关方法<a href="#正则表达式的相关方法"><span>#</span></a></h1><p><strong>正则表达式可以“打点”调用哪些方法呢？</strong></p>

<table><thead><tr><th>方法</th><th>简介</th></tr></thead><tbody><tr><td>test()</td><td>测试某字符串是否匹配正则表达式，返 回布尔值</td></tr><tr><td>exec()</td><td>根据正则表达式，在字符串中进行查找， 返回结果数组或者null</td></tr></tbody></table><p><strong>test()方法</strong></p><ul>
<li>
<p>正则表达式的test()方法用来测试某字符串是否匹配此正则 表达式，它返回true或false</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/</span><span>^</span><span>[a-z]</span><span>{3}</span><span>[a-ln-z]</span><span>$</span><span>/</span><span>.</span><span>test</span><span>(</span><span>'abcd'</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>exec()</strong></p><ul>
<li>
<p>exec()方法功能是：在一个指定字符串中执行一个搜索匹配 查找，返回一个结果数组或null</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>str</span><span> </span></span><span>=</span><span>'abc123def456ghi789'</span><span>;</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>regexp</span><span> </span></span><span>=</span><span> /</span><span>\d</span><span><span>+</span><span>/</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>result1</span><span> </span></span><span>=</span><span><span> </span><span>regexp</span><span>.</span></span><span>exec</span><span><span>(</span><span>str</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>exec()方法的逐条遍历</strong></p><ul>
<li>
<p>exec()方法最有趣的是，有“g”修饰符的正则表达式将自 动成为“有状态”的，这意味着可以对单个字符串中的多次 匹配结果进行逐条的遍历</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>str</span><span> </span></span><span>=</span><span>'abc123def456ghi789'</span><span>;</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>regexp</span><span> </span></span><span>=</span><span> /</span><span>\d</span><span><span>+</span><span>/</span></span><span>g</span><span>; </span><span>// 有g修饰符</span></div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>result1</span><span> </span></span><span>=</span><span><span> </span><span>regexp</span><span>.</span></span><span>exec</span><span><span>(</span><span>str</span><span>);</span></span></div></div><div><div><div>4</div></div><div><span>var</span><span><span> </span><span>result2</span><span> </span></span><span>=</span><span><span> </span><span>regexp</span><span>.</span></span><span>exec</span><span><span>(</span><span>str</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span>var</span><span><span> </span><span>result3</span><span> </span></span><span>=</span><span><span> </span><span>regexp</span><span>.</span></span><span>exec</span><span><span>(</span><span>str</span><span>);</span></span></div></div><div><div><div>6</div></div><div><span>var</span><span><span> </span><span>result4</span><span> </span></span><span>=</span><span><span> </span><span>regexp</span><span>.</span></span><span>exec</span><span><span>(</span><span>str</span><span>);</span></span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result1</span><span>);</span></span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result2</span><span>);</span></span></div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result3</span><span>);</span></span></div></div><div><div><div>10</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result4</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>str</span><span> </span></span><span>=</span><span>'abc123def456ghi789'</span><span>;</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>regexp</span><span> </span></span><span>=</span><span> /</span><span>\d</span><span><span>+</span><span>/</span></span><span>g</span><span>; </span><span>// 有g修饰符</span></div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>result</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>while</span><span><span> (</span><span>result</span><span> </span></span><span>=</span><span><span> </span><span>regexp</span><span>.</span></span><span>exec</span><span><span>(</span><span>str</span><span>)) {</span></span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>result</span><span>);</span></span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h1>字符串的相关正则方法<a href="#字符串的相关正则方法"><span>#</span></a></h1><p><strong>字符串有哪些方法可以使用正则表达式呢？</strong></p>

<table><thead><tr><th>方法</th><th>简介</th></tr></thead><tbody><tr><td>search()</td><td>在字符串中根据正则表达式进行查找匹配，返 回首次匹配到的位置索引，测试不到则返回-1</td></tr><tr><td>match()</td><td>在字符串中根据正则表达式进行查找匹配，返 回一个数组，找不到则返回null</td></tr><tr><td>replace()</td><td>使用替换字符串替换掉匹配到的子字符串，可 以使用正则表达式</td></tr><tr><td>split()</td><td>分隔字符串为数组，可以使用正则表达式</td></tr></tbody></table></section>
<section><h1>正则表达式的应用<a href="#正则表达式的应用"><span>#</span></a></h1><p><strong>用正则表达式进行表单验证</strong></p><ul>
<li>用正则表达式进行表单验证是正则表达式最重要的实际应用</li>
<li>实际上，很多正则表达式不需要我们自己写，可以通过搜索 引擎和AI查找，可以拿来即用</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102008javascript-bao-zhuang-lei/</id>
      <title type="text">JavaScript包装类</title>
      <published>2026-10-20T10:37:03.000Z</published>
      <updated>2026-10-20T10:37:03.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102008javascript-bao-zhuang-lei/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>本文主要学习JavaScript包装类和Math、Date对象</p>
<section><h1>包装类<a href="#包装类"><span>#</span></a></h1><p><strong>什么是包装类</strong></p><ul>
<li>
<p>Number()、String()和Boolean()分别是数字、字符串、 布尔值的“包装类”</p>
</li>
<li>
<p>很多编程语言都有“包装类”的设计，包装类的目的就是为 了让基本类型值可以从它们的构造函数的prototype上获得 方法</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>Number</span><span>(</span><span>123</span><span>);</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>String</span><span>(</span><span>'柚子177'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>c</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>Boolean</span><span>(</span><span>true</span><span>);</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>typeof</span><span><span> </span><span>a</span><span>); </span></span><span>//object</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>typeof</span><span><span> </span><span>b</span><span>); </span></span><span>//object</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>typeof</span><span><span> </span><span>c</span><span>); </span></span><span>//object</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>5</span><span> </span><span>+</span><span><span> </span><span>a</span><span>); </span></span><span>//可以参与运算</span></div></div><div><div><div>10</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>b</span><span>.</span></span><span>slice</span><span>(</span><span>0</span><span>, </span><span>2</span><span>));</span></div></div><div><div><div>11</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>c</span><span> </span></span><span>&amp;&amp;</span><span> </span><span>true</span><span>);</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>var</span><span><span> </span><span>d</span><span> </span></span><span>=</span><span> </span><span>1234</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>d</span><span>.</span></span><span>__proto__</span><span> </span><span>==</span><span> </span><span>Number</span><span>.</span><span>prototype</span><span>); </span><span>//true</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>a、b、c是基本类型值么？它们和普通的数字、字符串、布 尔值有什么区别么？</p>
</li>
<li>
<p>Number()、String()和Boolean()的实例都是object类型 ，它们的PrimitiveValue属性存储它们的本身值</p>
</li>
<li>
<p>new出来的基本类型值可以正常参与运算</p>
</li>
<li>
<p>包装类的目的就是为了让基本类型值可以从它们的构造函数 的prototype上获得方法</p>
</li>
</ul></section>
<section><h1>Math（数学）对象<a href="#math数学对象"><span>#</span></a></h1><p><strong>已经学习过的Math对象的方法</strong></p><ul>
<li>幂和开方：Math.pow()、Math.sqrt()</li>
<li>向上取整和向下取整：Math.ceil()、Math.floor()</li>
</ul><p><strong>四舍五入Math.round()</strong></p><ul>
<li>
<p>Math.round()可以将一个数字四舍五入为整数</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>Math</span><span>.</span></span><span>round</span><span>(</span><span>3.4</span><span>)); </span><span>// 3</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>Math</span><span>.</span></span><span>round</span><span>(</span><span>3.5</span><span>)); </span><span>// 4</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>Math</span><span>.</span></span><span>round</span><span>(</span><span>3.98</span><span>)); </span><span>// 4</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>Math</span><span>.</span></span><span>round</span><span>(</span><span>3.49</span><span>)); </span><span>// 3</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>四舍五入到小数点后某位</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>roundTo</span><span><span>(</span><span>num</span><span>, </span><span>digits</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>const</span><span> </span><span>factor</span><span> </span><span>=</span><span><span> </span><span>Math</span><span>.</span></span><span>pow</span><span>(</span><span>10</span><span><span>, </span><span>digits</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>  </span><span>return</span><span><span> </span><span>Math</span><span>.</span></span><span>round</span><span><span>(</span><span>num</span><span> </span></span><span>*</span><span><span> </span><span>factor</span><span>) </span></span><span>/</span><span><span> </span><span>factor</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>roundTo</span><span>(</span><span>3.14159</span><span>, </span><span>2</span><span>); </span><span>// 3.14</span></div></div><div><div><div>7</div></div><div><span>roundTo</span><span>(</span><span>3.145</span><span>, </span><span>2</span><span>);   </span><span>// 3.15</span></div></div><div><div><div>8</div></div><div><span>roundTo</span><span>(</span><span>3.1</span><span>, </span><span>3</span><span>);     </span><span>// 3.100</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>Math.max()和Math.min()</strong></p><ul>
<li>
<p>Math.max()可以得到参数列表的最大值</p>
</li>
<li>
<p>Math.min()可以得到参数列表的最小值</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>Math</span><span>.</span></span><span>max</span><span>(</span><span>6</span><span>, </span><span>2</span><span>, </span><span>9</span><span>, </span><span>4</span><span>)); </span><span>// 9</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>Math</span><span>.</span></span><span>min</span><span>(</span><span>6</span><span>, </span><span>2</span><span>, </span><span>9</span><span>, </span><span>4</span><span>)); </span><span>// 2</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>如何利用Math.max()求数组最大值</strong></p><ul>
<li>
<p>Math.max()要求参数必须是“罗列出来”，而不能是数组</p>
</li>
<li>
<p>还记得apply方法么？它可以指定函数的上下文，并且以数组的 形式传入“零散值”当做函数的参数</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>3</span><span>, </span><span>6</span><span>, </span><span>9</span><span>, </span><span>2</span><span>];</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>max</span><span> </span></span><span>=</span><span><span> </span><span>Math</span><span>.</span></span><span>max</span><span>.</span><span>apply</span><span>(</span><span>null</span><span><span>, </span><span>arr</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>max</span><span>); </span></span><span>// 9</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>随机数Math.random()</strong></p><ul>
<li>
<p>Math.random()可以得到0~1之间的小数</p>
</li>
<li>
<p>为了得到[a, b]区间内的整数，可以使用这个公式：</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>parseInt</span><span><span>(</span><span>Math</span><span>.</span></span><span>random</span><span>() </span><span>*</span><span><span> (</span><span>b</span><span> </span></span><span>-</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span> </span><span>1</span><span>)) </span><span>+</span><span><span> </span><span>a</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h1>Date（日期）对象<a href="#date日期对象"><span>#</span></a></h1><ul>
<li>使用new Date()即可得到当前时间的日期对象，它是object类 型值</li>
<li>使用new Date(2020, 11, 1)即可得到指定日期的日期对象， 注意第二个参数表示月份，从0开始算，11表示12月</li>
<li>也可以是new Date(‘2026-06-16’)这样的写法</li>
</ul><p><strong>日期对象的常见的方法</strong></p>

<table><thead><tr><th>方法</th><th>功能</th></tr></thead><tbody><tr><td>getDate()</td><td>得到日期1~31</td></tr><tr><td>getDay()</td><td>得到星期0~6</td></tr><tr><td>getMonth()</td><td>得到月份0~11</td></tr><tr><td>getFullYear()</td><td>得到年份</td></tr><tr><td>getHours()</td><td>得到小时数0~23</td></tr><tr><td>getMinutes()</td><td>得到分钟数0~59</td></tr><tr><td>getSeconds()</td><td>得到秒数0~59</td></tr></tbody></table><p><strong>时间戳</strong></p><ul>
<li>时间戳表示1970年1月1日零点整距离某时刻的毫秒数</li>
<li>通过getTime()方法或者Date.parse()函数可以将日期对象变 为时间戳</li>
<li>通过new Date(时间戳)的写法，可以将时间戳变为日期对象</li>
</ul><p><strong>小案例：倒计时小程序</strong></p><p>在页面上实时显示距离2027年高考还有多少天、多少时 、多少分、多少秒</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>距离2027年高考还有：</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>span</span><span> </span><span>id</span><span>=</span><span>"days"</span><span>&gt;0&lt;/</span><span>span</span><span>&gt; 天</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>&lt;</span><span>span</span><span> </span><span>id</span><span>=</span><span>"hours"</span><span>&gt;0&lt;/</span><span>span</span><span>&gt; 时</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>&lt;</span><span>span</span><span> </span><span>id</span><span>=</span><span>"minutes"</span><span>&gt;0&lt;/</span><span>span</span><span>&gt; 分</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>&lt;</span><span>span</span><span> </span><span>id</span><span>=</span><span>"seconds"</span><span>&gt;0&lt;/</span><span>span</span><span>&gt; 秒</span></div></div><div><div><div>7</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>10</div></div><div><span>  </span><span>// 🎯 目标时间（2027高考）</span></div></div><div><div><div>11</div></div><div><span>  </span><span>const</span><span> </span><span>targetDate</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Date</span><span>(</span><span>"2027-06-07 00:00:00"</span><span>).</span><span>getTime</span><span>();</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>  </span><span>function</span><span> </span><span>updateCountdown</span><span>() {</span></div></div><div><div><div>14</div></div><div><span>    </span><span>const</span><span> </span><span>now</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>Date</span><span>().</span><span>getTime</span><span>();</span></div></div><div><div><div>15</div></div><div><span>    </span><span>const</span><span> </span><span>diff</span><span> </span><span>=</span><span><span> </span><span>targetDate</span><span> </span></span><span>-</span><span><span> </span><span>now</span><span>;</span></span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>    </span><span>// 如果已经过了</span></div></div><div><div><div>18</div></div><div><span>    </span><span>if</span><span><span> (</span><span>diff</span><span> </span></span><span>&lt;=</span><span> </span><span>0</span><span>) {</span></div></div><div><div><div>19</div></div><div><span><span>      </span></span><span>document</span><span>.</span><span>body</span><span>.</span><span>innerHTML</span><span> </span><span>=</span><span> </span><span>"⏰ 高考时间已到！"</span><span>;</span></div></div><div><div><div>20</div></div><div><span>      </span><span>clearInterval</span><span><span>(</span><span>timer</span><span>);</span></span></div></div><div><div><div>21</div></div><div><span>      </span><span>return</span><span>;</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>    </span><span>// 计算时间</span></div></div><div><div><div>25</div></div><div><span>    </span><span>const</span><span> </span><span>seconds</span><span> </span><span>=</span><span><span> </span><span>Math</span><span>.</span></span><span>floor</span><span><span>(</span><span>diff</span><span> </span></span><span>/</span><span> </span><span>1000</span><span>);</span></div></div><div><div><div>26</div></div><div><span>    </span><span>const</span><span> </span><span>days</span><span> </span><span>=</span><span><span> </span><span>Math</span><span>.</span></span><span>floor</span><span><span>(</span><span>seconds</span><span> </span></span><span>/</span><span> (</span><span>60</span><span> </span><span>*</span><span> </span><span>60</span><span> </span><span>*</span><span> </span><span>24</span><span>));</span></div></div><div><div><div>27</div></div><div><span>    </span><span>const</span><span> </span><span>hours</span><span> </span><span>=</span><span><span> </span><span>Math</span><span>.</span></span><span>floor</span><span><span>((</span><span>seconds</span><span> </span></span><span>%</span><span> (</span><span>60</span><span> </span><span>*</span><span> </span><span>60</span><span> </span><span>*</span><span> </span><span>24</span><span>)) </span><span>/</span><span> (</span><span>60</span><span> </span><span>*</span><span> </span><span>60</span><span>));</span></div></div><div><div><div>28</div></div><div><span>    </span><span>const</span><span> </span><span>minutes</span><span> </span><span>=</span><span><span> </span><span>Math</span><span>.</span></span><span>floor</span><span><span>((</span><span>seconds</span><span> </span></span><span>%</span><span> (</span><span>60</span><span> </span><span>*</span><span> </span><span>60</span><span>)) </span><span>/</span><span> </span><span>60</span><span>);</span></div></div><div><div><div>29</div></div><div><span>    </span><span>const</span><span> </span><span>secs</span><span> </span><span>=</span><span><span> </span><span>seconds</span><span> </span></span><span>%</span><span> </span><span>60</span><span>;</span></div></div><div><div><div>30</div></div><div>
</div></div><div><div><div>31</div></div><div><span>    </span><span>// 写入页面</span></div></div><div><div><div>32</div></div><div><span><span>    </span></span><span>document</span><span>.</span><span>getElementById</span><span>(</span><span>"days"</span><span>).</span><span>textContent</span><span> </span><span>=</span><span><span> </span><span>days</span><span>;</span></span></div></div><div><div><div>33</div></div><div><span><span>    </span></span><span>document</span><span>.</span><span>getElementById</span><span>(</span><span>"hours"</span><span>).</span><span>textContent</span><span> </span><span>=</span><span><span> </span><span>hours</span><span>;</span></span></div></div><div><div><div>34</div></div><div><span><span>    </span></span><span>document</span><span>.</span><span>getElementById</span><span>(</span><span>"minutes"</span><span>).</span><span>textContent</span><span> </span><span>=</span><span><span> </span><span>minutes</span><span>;</span></span></div></div><div><div><div>35</div></div><div><span><span>    </span></span><span>document</span><span>.</span><span>getElementById</span><span>(</span><span>"seconds"</span><span>).</span><span>textContent</span><span> </span><span>=</span><span><span> </span><span>secs</span><span>;</span></span></div></div><div><div><div>36</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>37</div></div><div>
</div></div><div><div><div>38</div></div><div><span>  </span><span>// 先执行一次（避免1秒空白）</span></div></div><div><div><div>39</div></div><div><span>  </span><span>updateCountdown</span><span>();</span></div></div><div><div><div>40</div></div><div>
</div></div><div><div><div>41</div></div><div><span>  </span><span>// 每秒更新</span></div></div><div><div><div>42</div></div><div><span>  </span><span>const</span><span> </span><span>timer</span><span> </span><span>=</span><span> </span><span>setInterval</span><span><span>(</span><span>updateCountdown</span><span>, </span></span><span>1000</span><span>);</span></div></div><div><div><div>43</div></div><div><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>44</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>45</div></div><div><span><span>  </span></span><span>&lt;</span><span>h1</span><span>&gt;2027年高考倒计时&lt;/</span><span>h1</span><span>&gt;</span></div></div><div><div><div>46</div></div><div><span><span>  </span></span><span>&lt;</span><span>h2</span><span> </span><span>id</span><span>=</span><span>"info"</span><span>&gt;&lt;/</span><span>h2</span><span>&gt;</span></div></div><div><div><div>47</div></div><div><span><span>  </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>48</div></div><div><span>    </span><span>var</span><span><span> </span><span>info</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>'info'</span><span>);</span></div></div><div><div><div>49</div></div><div><span>    </span><span>function</span><span> </span><span>updateCountdown</span><span>() {</span></div></div><div><div><div>50</div></div><div><span>      </span><span>// 现在的日期</span></div></div><div><div><div>51</div></div><div><span>      </span><span>var</span><span><span> </span><span>nd</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>Date</span><span>();</span></div></div><div><div><div>52</div></div><div><span>      </span><span>// 目标的日期，5表示六月</span></div></div><div><div><div>53</div></div><div><span>      </span><span>var</span><span><span> </span><span>td</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>Date</span><span>(</span><span>2027</span><span>, </span><span>5</span><span>, </span><span>7</span><span>);</span></div></div><div><div><div>54</div></div><div>
</div></div><div><div><div>55</div></div><div><span>      </span><span>// 毫秒差</span></div></div><div><div><div>56</div></div><div><span>      </span><span>var</span><span><span> </span><span>diff</span><span> </span></span><span>=</span><span><span> </span><span>td</span><span> </span></span><span>-</span><span><span> </span><span>nd</span><span>;</span></span></div></div><div><div><div>57</div></div><div>
</div></div><div><div><div>58</div></div><div><span>      </span><span>// 任务很简单，就是把diff换算为天、小时、分钟、秒</span></div></div><div><div><div>59</div></div><div><span>      </span><span>// 换算为多少天，除以一天的总毫秒数，不就是换算为多少天么</span></div></div><div><div><div>60</div></div><div><span>      </span><span>var</span><span><span> </span><span>day</span><span> </span></span><span>=</span><span> </span><span>parseInt</span><span><span>(</span><span>diff</span><span> </span></span><span>/</span><span> (</span><span>1000</span><span> </span><span>*</span><span> </span><span>60</span><span> </span><span>*</span><span> </span><span>60</span><span> </span><span>*</span><span> </span><span>24</span><span>));</span></div></div><div><div><div>61</div></div><div><span>      </span><span>// 零多少小时呢？？差的总毫秒数与1天的毫秒数的相除的余数，就是零头的毫秒数</span></div></div><div><div><div>62</div></div><div><span>      </span><span>var</span><span><span> </span><span>hours</span><span> </span></span><span>=</span><span> </span><span>parseInt</span><span><span>((</span><span>diff</span><span> </span></span><span>%</span><span> (</span><span>1000</span><span> </span><span>*</span><span> </span><span>60</span><span> </span><span>*</span><span> </span><span>60</span><span> </span><span>*</span><span> </span><span>24</span><span>)) </span><span>/</span><span> (</span><span>1000</span><span> </span><span>*</span><span> </span><span>60</span><span> </span><span>*</span><span> </span><span>60</span><span>));</span></div></div><div><div><div>63</div></div><div><span>      </span><span>// 零多少分钟呢？？</span></div></div><div><div><div>64</div></div><div><span>      </span><span>var</span><span><span> </span><span>minutes</span><span> </span></span><span>=</span><span> </span><span>parseInt</span><span><span>((</span><span>diff</span><span> </span></span><span>%</span><span> (</span><span>1000</span><span> </span><span>*</span><span> </span><span>60</span><span> </span><span>*</span><span> </span><span>60</span><span>)) </span><span>/</span><span> (</span><span>1000</span><span> </span><span>*</span><span> </span><span>60</span><span>));</span></div></div><div><div><div>65</div></div><div><span>      </span><span>// 零多少秒呢？？</span></div></div><div><div><div>66</div></div><div><span>      </span><span>var</span><span><span> </span><span>seconds</span><span> </span></span><span>=</span><span> </span><span>parseInt</span><span>(</span></div></div><div><div><div>67</div></div><div><span><span>        </span></span><span>((</span><span>diff</span><span> </span><span>%</span><span> (</span><span>1000</span><span> </span><span>*</span><span> </span><span>60</span><span> </span><span>*</span><span> </span><span>60</span><span>)) </span><span>%</span><span> (</span><span>1000</span><span> </span><span>*</span><span> </span><span>60</span><span>)) </span><span>/</span><span> </span><span>1000</span><span>,</span></div></div><div><div><div>68</div></div><div><span><span>      </span></span><span>);</span></div></div><div><div><div>69</div></div><div><span><span>      </span></span><span>info</span><span>.</span><span>innerText</span><span> </span><span>=</span></div></div><div><div><div>70</div></div><div><span><span>        </span></span><span>day</span><span> </span><span>+</span><span> </span><span>'天'</span><span> </span><span>+</span><span><span> </span><span>hours</span><span> </span></span><span>+</span><span> </span><span>'时'</span><span> </span><span>+</span><span><span> </span><span>minutes</span><span> </span></span><span>+</span><span> </span><span>'分'</span><span> </span><span>+</span><span><span> </span><span>seconds</span><span> </span></span><span>+</span><span> </span><span>'秒'</span><span>;</span></div></div><div><div><div>71</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>72</div></div><div><span>    </span><span>updateCountdown</span><span>(); </span><span>//// 先执行一次（避免1秒空白）</span></div></div><div><div><div>73</div></div><div><span>    </span><span>setInterval</span><span><span>(</span><span>updateCountdown</span><span>, </span></span><span>1000</span><span>);</span></div></div><div><div><div>74</div></div><div><span><span>  </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>75</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102007javascript-mian-xiang-dui-xiang-zhi-lei-he-shi-li/</id>
      <title type="text">JavaScript面向对象之类和实例</title>
      <published>2026-10-20T07:26:44.000Z</published>
      <updated>2026-10-20T07:26:44.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102007javascript-mian-xiang-dui-xiang-zhi-lei-he-shi-li/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>本文学习JavaScript的构造函数、类和实例、了解原型链和继承</p>
<section><h1>构造函数<a href="#构造函数"><span>#</span></a></h1><p><strong>什么是构造函数</strong></p><ul>
<li>用new调用一个函数，这个函数就被称为“构造函数”，任何函数都可以是构造函数，只需要用new调用它</li>
<li>顾名思义，构造函数用来“构造新对象”，它内部的语句将 为新对象添加若干属性和方法，完成对象的初始化</li>
<li>构造函数必须用new关键字调用，否则不能正常工作，正因 如此，开发者约定构造函数命名时首字母要大写</li>
</ul><p><strong>构造函数名称首字母约定大写</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>People</span><span><span>(</span><span>name</span><span>, </span><span>age</span><span>, </span><span>sex</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>  </span><span>this</span><span>.</span><span>age</span><span> </span><span>=</span><span><span> </span><span>age</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>  </span><span>this</span><span>.</span><span>sex</span><span> </span><span>=</span><span><span> </span><span>sex</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>var</span><span><span> </span><span>xiaoming</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>People</span><span>(</span><span>'小明'</span><span>, </span><span>12</span><span>, </span><span>'男'</span><span>);</span></div></div><div><div><div>7</div></div><div><span>var</span><span><span> </span><span>xiaohong</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>People</span><span>(</span><span>'小红'</span><span>, </span><span>10</span><span>, </span><span>'女'</span><span>);</span></div></div><div><div><div>8</div></div><div><span>var</span><span><span> </span><span>xiaogang</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>People</span><span>(</span><span>'小刚'</span><span>, </span><span>13</span><span>, </span><span>'男'</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>一定要记住：一个函数是不是构造函数，要看它是否用new 调用，而至于名称首字母大写，完全是开发者的习惯约定</p><p><strong>如果不用new调用构造函数</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>People</span><span><span>(</span><span>name</span><span>, </span><span>age</span><span>, </span><span>sex</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>  </span><span>this</span><span>.</span><span>age</span><span> </span><span>=</span><span><span> </span><span>age</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>  </span><span>this</span><span>.</span><span>sex</span><span> </span><span>=</span><span><span> </span><span>sex</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>People</span><span>(</span><span>'小明'</span><span>, </span><span>12</span><span>, </span><span>'男'</span><span>);</span></div></div><div><div><div>7</div></div><div><span>People</span><span>(</span><span>'小红'</span><span>, </span><span>10</span><span>, </span><span>'女'</span><span>);</span></div></div><div><div><div>8</div></div><div><span>People</span><span>(</span><span>'小刚'</span><span>, </span><span>13</span><span>, </span><span>'男'</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这个时候会变成一个全局变量name，这个name的值为小刚</p><p><strong>构造函数中的this不是函数本身</strong></p><p>构造函数的this指向的是空对象，具体参考函数四步走</p><p><strong>尝试为对象添加方法</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>People</span><span><span>(</span><span>name</span><span>, </span><span>age</span><span>, </span><span>sex</span><span>) {</span></span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>  </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>  </span><span>this</span><span>.</span><span>age</span><span> </span><span>=</span><span><span> </span><span>age</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>  </span><span>this</span><span>.</span><span>sex</span><span> </span><span>=</span><span><span> </span><span>sex</span><span>;</span></span></div></div><div><div><div>6</div></div><div><span>  </span><span>this</span><span>.</span><span>sayHello</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'我是'</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>name</span><span> </span><span>+</span><span> </span><span>'，我'</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>age</span><span> </span><span>+</span><span> </span><span>'岁了'</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>};</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div><span>var</span><span><span> </span><span>xiaoming</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>People</span><span>(</span><span>'小明'</span><span>, </span><span>12</span><span>, </span><span>'男'</span><span>);</span></div></div><div><div><div>11</div></div><div><span>var</span><span><span> </span><span>xiaohong</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>People</span><span>(</span><span>'小红'</span><span>, </span><span>10</span><span>, </span><span>'女'</span><span>);</span></div></div><div><div><div>12</div></div><div><span>var</span><span><span> </span><span>xiaogang</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>People</span><span>(</span><span>'小刚'</span><span>, </span><span>13</span><span>, </span><span>'男'</span><span>);</span></div></div><div><div><div>13</div></div><div><span><span>xiaoming</span><span>.</span></span><span>sayHello</span><span>(); </span><span>//我是小明，我12岁了  规则1 this指向这个对象xiaoming</span></div></div><div><div><div>14</div></div><div><span><span>xiaohong</span><span>.</span></span><span>sayHello</span><span>(); </span><span>//我是小红，我10岁了</span></div></div><div><div><div>15</div></div><div><span><span>xiaogang</span><span>.</span></span><span>sayHello</span><span>(); </span><span>//我是小刚，我13岁了</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>这种方式并不推荐：</p><ul>
<li>每次 <code>new People()</code>，都会重新创建一个 <code>sayHello</code> 函数并挂到实例上，它们是<strong>不同的函数对象</strong></li>
<li>浪费内存，建了 3 个对象，就有 3 份完全一样的函数</li>
<li>无法共享方法，方法本质应该是“行为”，不是“每个对象独有数据”。现在写法是：每个对象都“自带一份行为副本”</li>
</ul><p>更推荐的方式：放到 prototype</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>People</span><span><span>(</span><span>name</span><span>, </span><span>age</span><span>, </span><span>sex</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>  </span><span>this</span><span>.</span><span>age</span><span> </span><span>=</span><span><span> </span><span>age</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>  </span><span>this</span><span>.</span><span>sex</span><span> </span><span>=</span><span><span> </span><span>sex</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>People</span><span>.</span><span>prototype</span><span>.</span><span>sayHello</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'我是'</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>name</span><span> </span><span>+</span><span> </span><span>'，我'</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>age</span><span> </span><span>+</span><span> </span><span>'岁了'</span><span>);</span></div></div><div><div><div>9</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>类和实例<a href="#类和实例"><span>#</span></a></h1><p><strong>类好比是“蓝图”</strong></p><ul>
<li>如同“蓝图”一样，类只描述对象会拥有哪些属性和方法， 但是并不具体指明属性的值</li>
</ul><p><strong>构造函数和“类”</strong></p><ul>
<li>可以把构造函数看作是类，把new出来看作是实例</li>
<li>Java、C++等是“面向对象”（object-oriented）语言</li>
<li>JavaScript是“基于对象”（object-based）语言</li>
<li>JavaScript中的构造函数可以类比于OOP语言中的“类”， 写法的确类似，但和真正OO语言还是有本质不同，在后续 课程还将看见JS和其他OO语言完全不同的、特有的原型特性</li>
</ul><p>关于更多class。再后续ES6会有更多讲解。</p></section>
<section><h1>prototype和原型链查找<a href="#prototype和原型链查找"><span>#</span></a></h1><p><strong>什么是prototype</strong></p><ul>
<li>
<p>任何函数都有prototype属性，prototype是英语“原型” 的意思</p>
</li>
<li>
<p>prototype属性值是个对象，它默认拥有constructor属性 指回函数</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>函数</span><span>  </span></span><span>-</span><span>》  </span><span>函数</span><span>.</span><span>prototype</span></div></div><div><div><div>2</div></div><div><span>函数</span><span>.</span><span>prototype</span><span> </span><span>-&gt;</span><span><span> </span><span>函数</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>function sum(a, b) </span><span>{</span></div></div><div><div><div>4</div></div><div><span><span>      </span></span><span>return</span><span> </span><span>a</span><span> </span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>}</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>console.log(sum.prototype);</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>console.log(typeof sum.prototype);</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>console.log(sum.prototype.constructor === sum);</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>10</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>普通函数来说的prototype属性没有任何用处，<strong>而构造函数 的prototype属性非常有用</strong></p>
</li>
<li>
<p>构造函数的 <code>prototype</code> 对象，会成为“由它 new 出来的实例的原型对象”</p>
</li>
<li>
<p><strong>实例没有 prototype 属性！！实例有的是 *<em>proto*</em></strong></p>
</li>
<li>
<p>构造函数的 prototype 是“未来实例共享方法的公共原型对象”</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>                </span></span><span>┌─────────────────────┐</span></div></div><div><div><div>2</div></div><div><span><span>                </span></span><span>│   Function 构造器    │</span></div></div><div><div><div>3</div></div><div><span><span>                </span></span><span>│   (Person函数本身)   │</span></div></div><div><div><div>4</div></div><div><span><span>                </span></span><span>└─────────┬───────────┘</span></div></div><div><div><div>5</div></div><div><span><span>                          </span></span><span>│ prototype</span></div></div><div><div><div>6</div></div><div><span><span>                          </span></span><span>↓</span></div></div><div><div><div>7</div></div><div><span><span>        </span></span><span>┌────────────────────────────────┐</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>│      Person.prototype         │  ←── 公共方法区</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>│   sayHello() 等共享方法       │</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>└─────────┬──────────────────────┘</span></div></div><div><div><div>11</div></div><div><span><span>                  </span></span><span>│ __proto__</span></div></div><div><div><div>12</div></div><div><span><span>                  </span></span><span>↓</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>┌────────────────────────────────┐</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>│      Object.prototype         │  ←── JS顶层原型</span></div></div><div><div><div>15</div></div><div><span><span>        </span></span><span>│  toString() / valueOf() 等    │</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>└─────────┬──────────────────────┘</span></div></div><div><div><div>17</div></div><div><span><span>                  </span></span><span>│ __proto__</span></div></div><div><div><div>18</div></div><div><span><span>                  </span></span><span>↓</span></div></div><div><div><div>19</div></div><div><span><span>               </span></span><span>null（原型链终点）</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>────────────────────────────────────────────</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span><span>                </span></span><span>实例对象层</span></div></div><div><div><div>25</div></div><div>
</div></div><div><div><div>26</div></div><div><span><span>        </span></span><span>┌─────────────────────┐</span></div></div><div><div><div>27</div></div><div><span><span>        </span></span><span>│   const p = new     │</span></div></div><div><div><div>28</div></div><div><span><span>        </span></span><span>│   Person("小明")    │</span></div></div><div><div><div>29</div></div><div><span><span>        </span></span><span>└─────────┬───────────┘</span></div></div><div><div><div>30</div></div><div><span><span>                  </span></span><span>│ __proto__</span></div></div><div><div><div>31</div></div><div><span><span>                  </span></span><span>↓</span></div></div><div><div><div>32</div></div><div><span><span>        </span></span><span>┌────────────────────────────────┐</span></div></div><div><div><div>33</div></div><div><span><span>        </span></span><span>│      Person.prototype         │</span></div></div><div><div><div>34</div></div><div><span><span>        </span></span><span>└────────────────────────────────┘</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
</li>
</ul><p>一张图解释：</p><p><a href="https://img.youzi177.cn/2026061501.webp" target="_blank"></a></p><figure><a href="https://img.youzi177.cn/2026061501.webp" target="_blank"><img src="https://img.youzi177.cn/2026061501.webp" alt="img" /><figcaption>img</figcaption></a></figure><p></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>People</span><span><span>(</span><span>name</span><span>, </span><span>age</span><span>, </span><span>sex</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>  </span><span>this</span><span>.</span><span>age</span><span> </span><span>=</span><span><span> </span><span>age</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>  </span><span>this</span><span>.</span><span>sex</span><span> </span><span>=</span><span><span> </span><span>sex</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>var</span><span><span> </span><span>xiaoming</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>People</span><span>(</span><span>'小名'</span><span>, </span><span>12</span><span>, </span><span>'男'</span><span>);</span></div></div><div><div><div>7</div></div><div><span>//证明xiaoming的__proto__是People.prototype</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>xiaoming</span><span>.</span></span><span>__proto__</span><span> </span><span>===</span><span> </span><span>People</span><span>.</span><span>prototype</span><span>);</span><span>//true</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>原型链的查找</strong></p><p>JavaScript规定：实例可以打点访问它的原型的属性和方法，这被称为“原型链查找</p><p><strong>当访问一个对象的属性/方法时，如果对象本身没有，就会沿着 <code>__proto__</code> 一层一层往上找，直到找到或到 null 为止。</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>People</span><span><span>(</span><span>name</span><span>, </span><span>age</span><span>, </span><span>sex</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>  </span><span>this</span><span>.</span><span>age</span><span> </span><span>=</span><span><span> </span><span>age</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>  </span><span>this</span><span>.</span><span>sex</span><span> </span><span>=</span><span><span> </span><span>sex</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>People</span><span>.</span><span>prototype</span><span>.</span><span>nationality</span><span> </span><span>=</span><span> </span><span>'中国'</span><span>;</span><span>//在构造函数的prototype上添加nationality属性</span></div></div><div><div><div>7</div></div><div><span>var</span><span><span> </span><span>xiaoming</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>People</span><span>(</span><span>'小明'</span><span>, </span><span>12</span><span>, </span><span>'男'</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>xiaoming</span><span>.</span></span><span>nationality</span><span>);</span><span>//中国；实例可以打点访问原型的属性和方法</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>原型链会有遮蔽效应</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>People</span><span><span>(</span><span>name</span><span>, </span><span>age</span><span>, </span><span>sex</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>  </span><span>this</span><span>.</span><span>age</span><span> </span><span>=</span><span><span> </span><span>age</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>  </span><span>this</span><span>.</span><span>sex</span><span> </span><span>=</span><span><span> </span><span>sex</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>People</span><span>.</span><span>prototype</span><span>.</span><span>nationality</span><span> </span><span>=</span><span> </span><span>'中国'</span><span>;</span></div></div><div><div><div>7</div></div><div><span>var</span><span><span> </span><span>xiaoming</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>People</span><span>(</span><span>'小明'</span><span>, </span><span>12</span><span>, </span><span>'男'</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>xiaoming</span><span>.</span></span><span>nationality</span><span>);</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>var</span><span><span> </span><span>tom</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>People</span><span>(</span><span>'汤姆'</span><span>, </span><span>10</span><span>, </span><span>'男'</span><span>);</span></div></div><div><div><div>11</div></div><div><span><span>tom</span><span>.</span></span><span>nationality</span><span> </span><span>=</span><span> </span><span>'美国'</span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>tom</span><span>.</span></span><span>nationality</span><span>);</span><span>//美国</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>hasOwnProperty</strong></p><ul>
<li>
<p>hasOwnProperty方法可以检查对象是否真正“自己拥有” 某属性或者方法</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xiaoming</span><span>.</span></span><span>hasOwnProperty</span><span>(</span><span>'name'</span><span>); </span><span>// true</span></div></div><div><div><div>2</div></div><div><span><span>xiaoming</span><span>.</span></span><span>hasOwnProperty</span><span>(</span><span>'age'</span><span>); </span><span>// true</span></div></div><div><div><div>3</div></div><div><span><span>xiaoming</span><span>.</span></span><span>hasOwnProperty</span><span>(</span><span>'sex'</span><span>); </span><span>// true</span></div></div><div><div><div>4</div></div><div><span><span>xiaoming</span><span>.</span></span><span>hasOwnProperty</span><span>(</span><span>'nationality'</span><span>);</span><span>// false</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>in</strong></p><ul>
<li>
<p>in运算符只能检查某个属性或方法是否可以被对象访问，不 能检查是否是自己的属性或方法</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'name'</span><span> </span><span>in</span><span><span> </span><span>xiaoming</span><span> </span></span><span>// true</span></div></div><div><div><div>2</div></div><div><span>'age'</span><span> </span><span>in</span><span><span> </span><span>xiaoming</span><span> </span></span><span>// true</span></div></div><div><div><div>3</div></div><div><span>'sex'</span><span> </span><span>in</span><span><span> </span><span>xiaoming</span><span> </span></span><span>// true</span></div></div><div><div><div>4</div></div><div><span>'nationality'</span><span> </span><span>in</span><span><span> </span><span>xiaoming</span><span> </span></span><span>// true</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>提前预习</strong></p><p>prototype 是“公共区域”，但只有“挂在同一条原型链上的对象”才能访问这个公共区域</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>A</span><span>() {}</span></div></div><div><div><div>2</div></div><div><span>A</span><span>.</span><span>prototype</span><span>.</span><span>a</span><span> </span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>3</div></div><div><span>function</span><span> </span><span>B</span><span>() {}</span></div></div><div><div><div>4</div></div><div><span>const</span><span> </span><span>b</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>B</span><span>();</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>b</span><span>.</span></span><span>a</span><span>); </span><span>// undefined</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>为什么是undefined，原型链是这样的：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>b</span></div></div><div><div><div>2</div></div><div><span><span> </span></span><span>↓ __proto__</span></div></div><div><div><div>3</div></div><div><span>B.prototype</span></div></div><div><div><div>4</div></div><div><span><span> </span></span><span>↓ __proto__</span></div></div><div><div><div>5</div></div><div><span>Object.prototype</span></div></div><div><div><div>6</div></div><div><span><span> </span></span><span>↓</span></div></div><div><div><div>7</div></div><div><span>null</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意：<strong>没有经过 A.prototype</strong>所以B 和 A 是两条“原型链分支”，默认互不相通</p><p>什么时候“可以访问到 A 的 a”？B 的原型链上包含 A.prototype，也是继承的相关</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>A</span><span>() {}</span></div></div><div><div><div>2</div></div><div><span>A</span><span>.</span><span>prototype</span><span>.</span><span>a</span><span> </span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>3</div></div><div><span>function</span><span> </span><span>B</span><span>() {}</span></div></div><div><div><div>4</div></div><div><span>B</span><span>.</span><span>prototype</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>A</span><span>();  </span><span>// 关键！！！b继承了A的原型链</span></div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>b</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>B</span><span>();</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>b</span><span>.</span></span><span>a</span><span>); </span><span>// 10</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>在prototype上添加方法<a href="#在prototype上添加方法"><span>#</span></a></h1><p>这在构造函数章节有提到过：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>People</span><span><span>(</span><span>name</span><span>, </span><span>age</span><span>, </span><span>sex</span><span>) {</span></span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>  </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>  </span><span>this</span><span>.</span><span>age</span><span> </span><span>=</span><span><span> </span><span>age</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>  </span><span>this</span><span>.</span><span>sex</span><span> </span><span>=</span><span><span> </span><span>sex</span><span>;</span></span></div></div><div><div><div>6</div></div><div><span>  </span><span>this</span><span>.</span><span>sayHello</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'我是'</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>name</span><span> </span><span>+</span><span> </span><span>'，我'</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>age</span><span> </span><span>+</span><span> </span><span>'岁了'</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>};</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div><span>var</span><span><span> </span><span>xiaoming</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>People</span><span>(</span><span>'小明'</span><span>, </span><span>12</span><span>, </span><span>'男'</span><span>);</span></div></div><div><div><div>11</div></div><div><span>var</span><span><span> </span><span>xiaohong</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>People</span><span>(</span><span>'小红'</span><span>, </span><span>10</span><span>, </span><span>'女'</span><span>);</span></div></div><div><div><div>12</div></div><div><span>var</span><span><span> </span><span>xiaogang</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>People</span><span>(</span><span>'小刚'</span><span>, </span><span>13</span><span>, </span><span>'男'</span><span>);</span></div></div><div><div><div>13</div></div><div><span><span>xiaoming</span><span>.</span></span><span>sayHello</span><span>(); </span><span>//我是小明，我12岁了  规则1 this指向这个对象xiaoming</span></div></div><div><div><div>14</div></div><div><span><span>xiaohong</span><span>.</span></span><span>sayHello</span><span>(); </span><span>//我是小红，我10岁了</span></div></div><div><div><div>15</div></div><div><span><span>xiaogang</span><span>.</span></span><span>sayHello</span><span>(); </span><span>//我是小刚，我13岁了</span></div></div><div><div><div>16</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>xiaoming</span><span>.</span></span><span>sayHello</span><span> </span><span>===</span><span><span> </span><span>xiaohong</span><span>.</span></span><span>sayHello</span><span>)</span><span>//false</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>把方法直接添加到实例身上的缺点：每个实例和每个实例的 方法函数都是内存中不同的函数，造成了内存的浪费</p><p>解决办法：将方法写到prototype上</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>People</span><span><span>(</span><span>name</span><span>, </span><span>age</span><span>, </span><span>sex</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>  </span><span>this</span><span>.</span><span>age</span><span> </span><span>=</span><span><span> </span><span>age</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>  </span><span>this</span><span>.</span><span>sex</span><span> </span><span>=</span><span><span> </span><span>sex</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>People</span><span>.</span><span>prototype</span><span>.</span><span>sayHello</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'我是'</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>name</span><span> </span><span>+</span><span> </span><span>'，我'</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>age</span><span> </span><span>+</span><span> </span><span>'岁了'</span><span>);</span></div></div><div><div><div>9</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>原型链的终点<a href="#原型链的终点"><span>#</span></a></h1><p>原型链的终点是 <code>null</code>，<code>null</code> 表示“没有原型”，是整个原型链的终点。</p><p>验证一下</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>Object</span><span>.</span><span>prototype</span><span>.</span><span>__proto__</span><span>); </span><span>// null</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>先来看下这图：</p><p><a href="https://img.youzi177.cn/2026061502.webp" target="_blank"></a></p><figure><a href="https://img.youzi177.cn/2026061502.webp" target="_blank"><img src="https://img.youzi177.cn/2026061502.webp" alt="img" /><figcaption>img</figcaption></a></figure><p></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>11</span><span>, </span><span>22</span><span>, </span><span>33</span><span>];</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>.</span></span><span>__proto__</span><span> </span><span>===</span><span> </span><span>Array</span><span>.</span><span>prototype</span><span>);</span><span>//true</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>.</span></span><span>__proto__</span><span>.</span><span>__proto__</span><span> </span><span>===</span><span> </span><span>Object</span><span>.</span><span>prototype</span><span>);</span><span>//true</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>继承<a href="#继承"><span>#</span></a></h1><p>先来看个例子：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>People</span><span><span>(</span><span>name</span><span>, </span><span>age</span><span>, </span><span>sex</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>  </span><span>this</span><span>.</span><span>age</span><span> </span><span>=</span><span><span> </span><span>age</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>  </span><span>this</span><span>.</span><span>sex</span><span> </span><span>=</span><span><span> </span><span>sex</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>People</span><span>.</span><span>prototype</span><span>.</span><span>sayHello</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'你好，我是'</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>name</span><span> </span><span>+</span><span> </span><span>'我今年'</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>age</span><span> </span><span>+</span><span> </span><span>'岁了'</span><span>);</span></div></div><div><div><div>9</div></div><div><span>};</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>People</span><span>.</span><span>prototype</span><span>.</span><span>sleep</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>name</span><span> </span><span>+</span><span> </span><span>'开始睡觉zzzz'</span><span>);</span></div></div><div><div><div>13</div></div><div><span>};</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>function</span><span> </span><span>Student</span><span><span>(</span><span>name</span><span>, </span><span>age</span><span>, </span><span>sex</span><span>, </span><span>scholl</span><span>, </span><span>studionumber</span><span>) {</span></span></div></div><div><div><div>16</div></div><div><span>  </span><span>this</span><span>.</span><span>name</span><span> </span><span>=</span><span><span> </span><span>name</span><span>;</span></span></div></div><div><div><div>17</div></div><div><span>  </span><span>this</span><span>.</span><span>age</span><span> </span><span>=</span><span><span> </span><span>age</span><span>;</span></span></div></div><div><div><div>18</div></div><div><span>  </span><span>this</span><span>.</span><span>sex</span><span> </span><span>=</span><span><span> </span><span>sex</span><span>;</span></span></div></div><div><div><div>19</div></div><div><span>  </span><span>this</span><span>.</span><span>scholl</span><span> </span><span>=</span><span><span> </span><span>scholl</span><span>;</span></span></div></div><div><div><div>20</div></div><div><span>  </span><span>this</span><span>.</span><span>studionumber</span><span> </span><span>=</span><span><span> </span><span>studionumber</span><span>;</span></span></div></div><div><div><div>21</div></div><div><span>}</span></div></div><div><div><div>22</div></div><div><span>Student</span><span>.</span><span>prototype</span><span>.</span><span>study</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>23</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>name</span><span> </span><span>+</span><span> </span><span>'在学习'</span><span>);</span></div></div><div><div><div>24</div></div><div><span>};</span></div></div><div><div><div>25</div></div><div><span>Student</span><span>.</span><span>prototype</span><span>.</span><span>exam</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>26</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>name</span><span> </span><span>+</span><span> </span><span>'在考试'</span><span>);</span></div></div><div><div><div>27</div></div><div><span>};</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>//关键语句实现继承,把People的原型链继承到Student上</span></div></div><div><div><div>30</div></div><div><span>Student</span><span>.</span><span>prototype</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>People</span><span>();</span></div></div><div><div><div>31</div></div><div><span>//constructor 是“告诉你这个对象是由哪个构造函数创建的标签”，使用上面的继承后console.log(s.constructor); // People这是错误的</span></div></div><div><div><div>32</div></div><div><span>Student</span><span>.</span><span>prototype</span><span>.</span><span>constructor</span><span> </span><span>=</span><span><span> </span><span>Student</span><span>;</span></span></div></div><div><div><div>33</div></div><div><span>// 重写&amp;复写 先继承后重写</span></div></div><div><div><div>34</div></div><div><span>Student</span><span>.</span><span>prototype</span><span>.</span><span>sayHello</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>35</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'敬礼，我是'</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>name</span><span> </span><span>+</span><span> </span><span>'我今年'</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>age</span><span> </span><span>+</span><span> </span><span>'岁了'</span><span>);</span></div></div><div><div><div>36</div></div><div><span>};</span></div></div><div><div><div>37</div></div><div>
</div></div><div><div><div>38</div></div><div><span>var</span><span><span> </span><span>lilei</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>Student</span><span>(</span><span>'李雷'</span><span>, </span><span>22</span><span>, </span><span>'初中'</span><span>, </span><span>10010</span><span>);</span></div></div><div><div><div>39</div></div><div><span>//调用People类的方法</span></div></div><div><div><div>40</div></div><div><span><span>lilei</span><span>.</span></span><span>sayHello</span><span>();</span></div></div><div><div><div>41</div></div><div><span><span>lilei</span><span>.</span></span><span>sleep</span><span>();</span></div></div><div><div><div>42</div></div><div><span><span>lilei</span><span>.</span></span><span>sayHello</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>People类和Student类的关系</p><ul>
<li>People类拥有的属性和方法Student类都有，Student类还扩展了一些属性和方法</li>
<li>Student“是一种”People，两类之间是“isakind of”关系</li>
<li>实现继承的关键在于&lt;子类必须拥有父类的全部属性和方法&gt;，同时子类还应该能定义自己特有的属性和方法</li>
<li>使用JavaScript特有的原型链特性来实现继承，是普遍的做法</li>
<li>ES6有新的继承方法</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102006javascript-mian-xiang-dui-xiang-zhi-shang-xia-wen-gui-ze/</id>
      <title type="text">JavaScript面向对象之上下文规则</title>
      <published>2026-10-20T06:56:47.000Z</published>
      <updated>2026-10-20T06:56:47.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102006javascript-mian-xiang-dui-xiang-zhi-shang-xia-wen-gui-ze/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>本文主要学习面向对象中的上下文规则，以及怎么改变上下文</p>
<section><h1>认识上下文<a href="#认识上下文"><span>#</span></a></h1><p><strong>函数的上下文</strong></p><ul>
<li>函数中可以使用this关键字，它表示函数的上下文</li>
<li>与中文中“这”类似，函数中的this具体指代什么必须通过调 用函数时的“前言后语”来判断</li>
</ul><p><strong>函数中的this</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>xiaoming</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>nickname </span><span>:</span><span> </span><span>'小明'</span><span>,</span></div></div><div><div><div>3</div></div><div><span>    </span><span>age </span><span>:</span><span> </span><span>12</span><span>,</span></div></div><div><div><div>4</div></div><div><span>    </span><span>sayHello</span><span> </span><span>:</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'我是'</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>nickname</span><span> </span><span>+</span><span> </span><span>'，我'</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>age</span><span> </span><span>+</span><span> </span><span>'岁了'</span><span>);</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span>};</span></div></div><div><div><div>8</div></div><div><span><span>xiaoming</span><span>.</span></span><span>sayHello</span><span>();</span><span>//我是小明，我12岁了</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>函数被提出到外面执行：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>xiaoming</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>nickname </span><span>:</span><span> </span><span>'小明'</span><span>,</span></div></div><div><div><div>3</div></div><div><span>    </span><span>age </span><span>:</span><span> </span><span>12</span><span>,</span></div></div><div><div><div>4</div></div><div><span>    </span><span>sayHello</span><span> </span><span>:</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'我是'</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>nickname</span><span> </span><span>+</span><span> </span><span>'，我'</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>age</span><span> </span><span>+</span><span> </span><span>'岁了'</span><span>);</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span>};</span></div></div><div><div><div>8</div></div><div><span>var</span><span><span> </span><span>sayHello</span><span> </span></span><span>=</span><span><span> </span><span>xiaoming</span><span>.</span></span><span>sayHello</span><span>;</span><span>//将函数“提”出来，单独存为变量</span></div></div><div><div><div>9</div></div><div><span>sayHello</span><span>();</span><span>//直接圆括号调用这个函数而不是对象打点调用了   我是undefined，我undefined岁了</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li>
<p>同一个函数，用不同的形式调用它，则函数的上下文不同</p>
</li>
<li>
<p>情形1：对象打点调用函数，函数中的this指代这个打点的对象</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>xiaoming.sayHello();</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>情形2：圆括号直接调用函数，函数中的this指代window对象</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var sayHello = xiaoming.sayHello;</span></div></div><div><div><div>2</div></div><div><span>sayHello();</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>函数的上下文由调用方式决定</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>obj</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>a</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>3</div></div><div><span>    </span><span>b</span><span>:</span><span> </span><span>2</span><span>,</span></div></div><div><div><div>4</div></div><div><span>    </span><span>function</span><span> () {</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>a</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>b</span><span>);</span><span>//不知道，因为没有调用，函数只有被调用，它的上下文才能被确定</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>例子1：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>obj</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>a</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>3</div></div><div><span>    </span><span>b</span><span>:</span><span> </span><span>2</span><span>,</span></div></div><div><div><div>4</div></div><div><span>    </span><span>fn</span><span>:</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>a</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>b</span><span>);</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span>};</span></div></div><div><div><div>8</div></div><div><span><span>obj</span><span>.</span></span><span>fn</span><span>();</span><span>//this指向obj</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>例子2：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>obj</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>a</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>3</div></div><div><span>    </span><span>b</span><span>:</span><span> </span><span>2</span><span>,</span></div></div><div><div><div>4</div></div><div><span>    </span><span>fn</span><span>:</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>a</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>b</span><span>);</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span>};</span></div></div><div><div><div>8</div></div><div><span>var</span><span><span> </span><span>fn</span><span> </span></span><span>=</span><span><span> </span><span>obj</span><span>.</span></span><span>fn</span><span>;</span></div></div><div><div><div>9</div></div><div><span>fn</span><span><span>();</span><span>this指向window</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>上下文规则<a href="#上下文规则"><span>#</span></a></h1><p><strong>函数的上下文由调用函数的方式决定</strong></p><ul>
<li>函数的上下文（this关键字）由调用函数的方式决定， function是“运行时上下文”策略</li>
<li>函数如果不调用，则不能确定函数的上下文</li>
</ul><p><strong>规则1</strong></p><ul>
<li>
<p>规则1：对象打点调用它的方法函数，则函数的上下文是这 个打点的对象</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>对象.方法()</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>fn</span><span>() {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>a</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>b</span><span>);</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>var</span><span><span> </span><span>obj</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>5</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>66</span><span>,</span></div></div><div><div><div>6</div></div><div><span>  </span><span>b</span><span>:</span><span> </span><span>33</span><span>,</span></div></div><div><div><div>7</div></div><div><span>  </span><span>fn</span><span>:</span><span><span> </span><span>fn</span><span>,</span></span></div></div><div><div><div>8</div></div><div><span>};</span></div></div><div><div><div>9</div></div><div><span><span>obj</span><span>.</span></span><span>fn</span><span>(); </span><span>//99</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>obj1</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>b</span><span>:</span><span> </span><span>2</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>fn</span><span>:</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>a</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>b</span><span>);</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>7</div></div><div><span>};</span></div></div><div><div><div>8</div></div><div><span>var</span><span><span> </span><span>obj2</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>9</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>3</span><span>,</span></div></div><div><div><div>10</div></div><div><span>  </span><span>b</span><span>:</span><span> </span><span>4</span><span>,</span></div></div><div><div><div>11</div></div><div><span>  </span><span>fn</span><span>:</span><span><span> </span><span>obj1</span><span>.</span></span><span>fn</span><span>,</span></div></div><div><div><div>12</div></div><div><span>};</span></div></div><div><div><div>13</div></div><div><span><span>obj2</span><span>.</span></span><span>fn</span><span>(); </span><span>//7</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>outer</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>11</span><span>;</span></div></div><div><div><div>3</div></div><div><span>  </span><span>var</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span> </span><span>22</span><span>;</span></div></div><div><div><div>4</div></div><div><span>  </span><span>return</span><span> {</span></div></div><div><div><div>5</div></div><div><span>    </span><span>a</span><span>:</span><span> </span><span>33</span><span>,</span></div></div><div><div><div>6</div></div><div><span>    </span><span>b</span><span>:</span><span> </span><span>44</span><span>,</span></div></div><div><div><div>7</div></div><div><span>    </span><span>fn</span><span>:</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>8</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>a</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>b</span><span>);</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>},</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>};</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div><span>outer</span><span>().</span><span>fn</span><span>(); </span><span>//77</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>a</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>b</span><span>);</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>var</span><span><span> </span><span>obj</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>5</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>6</div></div><div><span>  </span><span>b</span><span>:</span><span> </span><span>2</span><span>,</span></div></div><div><div><div>7</div></div><div><span>  </span><span>c</span><span>:</span><span> [</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>{</span></div></div><div><div><div>9</div></div><div><span>      </span><span>a</span><span>:</span><span> </span><span>3</span><span>,</span></div></div><div><div><div>10</div></div><div><span>      </span><span>b</span><span>:</span><span> </span><span>4</span><span>,</span></div></div><div><div><div>11</div></div><div><span>      </span><span>c</span><span>:</span><span><span> </span><span>fun</span><span>,</span></span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>},</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>],</span></div></div><div><div><div>14</div></div><div><span>};</span></div></div><div><div><div>15</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>5</span><span>;</span></div></div><div><div><div>16</div></div><div><span><span>obj</span><span>.</span></span><span>c</span><span>[</span><span>0</span><span>].</span><span>c</span><span>(); </span><span>//7</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
</li>
</ul><p><strong>规则2</strong></p><ul>
<li>
<p>圆括号直接调用函数，则函数的上下文是window对 象</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>函数</span><span>()</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>obj1</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>b</span><span>:</span><span> </span><span>2</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>fn</span><span>:</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>a</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>b</span><span>);</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>7</div></div><div><span>};</span></div></div><div><div><div>8</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>3</span><span>;</span></div></div><div><div><div>9</div></div><div><span>var</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span> </span><span>4</span><span>;</span></div></div><div><div><div>10</div></div><div><span>var</span><span><span> </span><span>fn</span><span> </span></span><span>=</span><span><span> </span><span>obj1</span><span>.</span></span><span>fn</span><span>;</span></div></div><div><div><div>11</div></div><div><span>fn</span><span>();</span><span>//7</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span> </span><span>this</span><span>.</span><span>a</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>b</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>5</div></div><div><span>var</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>6</div></div><div><span>var</span><span><span> </span><span>obj</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>7</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>3</span><span>,</span></div></div><div><div><div>8</div></div><div><span>  </span><span>b</span><span>:</span><span> </span><span>fun</span><span>(),</span><span>//3</span></div></div><div><div><div>9</div></div><div><span>  </span><span>fun</span><span>:</span><span><span> </span><span>fun</span><span>,</span></span><span>//obj.fun === window.fun true</span></div></div><div><div><div>10</div></div><div><span>};</span></div></div><div><div><div>11</div></div><div><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span><span> </span><span>obj</span><span>.</span></span><span>fun</span><span>();</span><span>//6，一个铁律：函数只有在调用的时候才能确定上下文  obj.a + obj.b 3+3</span></div></div><div><div><div>12</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>);</span></span><span>//6</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>规则3</strong></p><ul>
<li>
<p>数组（类数组对象）枚举出函数进行调用，上下文 是这个数组（类数组对象）</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>数组</span><span>[</span><span>下标</span><span>]()</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span></div></div><div><div><div>2</div></div><div><span>  </span><span>'A'</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>'B'</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>'C'</span><span>,</span></div></div><div><div><div>5</div></div><div><span>  </span><span>function</span><span> () {</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>[</span><span>0</span><span>]);</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>8</div></div><div><span>];</span></div></div><div><div><div>9</div></div><div><span><span>arr</span><span>[</span></span><span>3</span><span>]();</span><span>'A'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>类数组对象</strong></p><ul>
<li>
<p>什么是类数组对象：所有键名为自然数序列（从0开始）， 且有length属性的对象</p>
</li>
<li>
<p>arguments对象是最常见的类数组对象，它是函数的实参列 表</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>arguments</span><span>[</span><span>3</span><span>]();</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>fun</span><span>(</span><span>'A'</span><span>, </span><span>'B'</span><span>, </span><span>'C'</span><span>, </span><span>function</span><span> () {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>[</span><span>1</span><span>]);</span></div></div><div><div><div>6</div></div><div><span>});</span><span>//’B‘</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>规则4</strong></p><ul>
<li>
<p>IIFE中的函数，上下文是window对象</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>(</span><span>function</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>})();</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>obj</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>2</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>fun</span><span>:</span><span> (</span><span>function</span><span> () {</span></div></div><div><div><div>5</div></div><div><span>    </span><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>this</span><span>.</span><span>a</span><span>;</span><span>//1  IIFE中的函数，上下文是window对象所以这里this指向全局a 即1</span></div></div><div><div><div>6</div></div><div><span>    </span><span>return</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>7</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>a</span><span> </span></span><span>+</span><span> </span><span>this</span><span>.</span><span>a</span><span>);</span><span>//这里的this取决于调用，obj.fun()，所以this是obj，即a等于2 ，1+2=3</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>};</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>})(),</span></div></div><div><div><div>10</div></div><div><span>};</span></div></div><div><div><div>11</div></div><div><span><span>obj</span><span>.</span></span><span>fun</span><span>();</span><span>//3</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>规则5</strong></p><ul>
<li>
<p>定时器、延时器调用函数，上下文是window对象</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>setInterval</span><span><span>(</span><span>函数</span><span>, </span><span>时间</span><span>);</span></span></div></div><div><div><div>2</div></div><div><span>setTimeout</span><span><span>(</span><span>函数</span><span>, </span><span>时间</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>obj</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>b</span><span>:</span><span> </span><span>2</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>fun</span><span>:</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>a</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>b</span><span>);</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>7</div></div><div><span>};</span></div></div><div><div><div>8</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>3</span><span>;</span></div></div><div><div><div>9</div></div><div><span>var</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span> </span><span>4</span><span>;</span></div></div><div><div><div>10</div></div><div><span>setTimeout</span><span><span>(</span><span>obj</span><span>.</span></span><span>fun</span><span>, </span><span>2000</span><span>);</span><span>//定时器、延时器调用函数，上下文是window对象，所以这里指向的不是obj，虽然是obj调用，但是是setTimeout里面调用所以是window对象，所以是7，注意这里obj.fun并没有执行，而是2秒后执行</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>obj</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>b</span><span>:</span><span> </span><span>2</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>fun</span><span>:</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>a</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>b</span><span>);</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>},</span></div></div><div><div><div>7</div></div><div><span>};</span></div></div><div><div><div>8</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>3</span><span>;</span></div></div><div><div><div>9</div></div><div><span>var</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span> </span><span>4</span><span>;</span></div></div><div><div><div>10</div></div><div><span>setTimeout</span><span>(</span><span>function</span><span> () {</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>obj</span><span>.</span><span>fun</span><span>();</span><span>//这里已经执行，函数这里指向obj，所以是3，2秒后也是3</span></div></div><div><div><div>12</div></div><div><span>}, </span><span>2000</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>规则6</strong></p><ul>
<li>
<p>事件处理函数的上下文是绑定事件的DOM元素</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>DOM元素</span><span>.</span></span><span>onclick</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>2</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>请实现效果：点击哪个盒子，哪个盒子就变红，要求使用同 一个事件处理函数实现</p>
</li>
</ul><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>      </span></span><span>.box </span><span>{</span></div></div><div><div><div>3</div></div><div><span><span>        </span></span><span>width</span><span>: 100</span><span>px</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>        </span></span><span>height</span><span>: 100</span><span>px</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>border</span><span>: 1</span><span>px</span><span> </span><span>solid</span><span> #</span><span>000</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>        </span></span><span>margin</span><span>: 10</span><span>px</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>        </span></span><span>display</span><span>: </span><span>inline</span><span>-</span><span><span>block</span><span>;</span></span></div></div><div><div><div>8</div></div><div><span>      </span><span>}</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>10</div></div><div><span>  </span><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>17</div></div><div><span><span>      </span></span><span>var boxes = document.querySelectorAll('.box');</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span><span>      </span></span><span>for (var i = 0; i &lt; boxes.length; i++) </span><span>{</span></div></div><div><div><div>20</div></div><div><span><span>        </span></span><span>boxes</span><span>[</span><span>i</span><span>].</span><span>onclick</span><span> </span><span>=</span><span><span> </span><span>changeColor</span><span>;</span></span></div></div><div><div><div>21</div></div><div><span>      </span><span>}</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span><span>      </span></span><span>function changeColor() </span><span>{</span></div></div><div><div><div>24</div></div><div><span>        </span><span>this</span><span>.</span><span>style</span><span>.</span><span>backgroundColor</span><span> </span><span>=</span><span> </span><span>'red'</span><span>;</span></div></div><div><div><div>25</div></div><div><span>      </span><span>}</span></div></div><div><div><div>26</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>27</div></div><div><span><span>  </span></span><span>&lt;/</span><span>body</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><ul>
<li>
<p>请实现效果：点击哪个盒子，哪个盒子在2000毫秒后就变红 ，要求使用同一个事件处理函数实现</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>boxes</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelectorAll</span><span>(</span><span>'.box'</span><span>);</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>for</span><span> (</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>boxes</span><span>.</span></span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>boxes</span><span>[</span><span>i</span><span>].</span><span>onclick</span><span> </span><span>=</span><span><span> </span><span>changeColor</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>function</span><span> </span><span>changeColor</span><span>() {</span></div></div><div><div><div>8</div></div><div><span>  </span><span>var</span><span><span> </span><span>that</span><span> </span></span><span>=</span><span> </span><span>this</span><span>; </span><span>// 保存当前点击的盒子</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>  </span><span>setTimeout</span><span>(</span><span>function</span><span> () {</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>that</span><span>.</span><span>style</span><span>.</span><span>backgroundColor</span><span> </span><span>=</span><span> </span><span>'red'</span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>}, </span><span>2000</span><span>);</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h1>call和apply<a href="#call和apply"><span>#</span></a></h1><p><strong>call和apply能指定函数的上下文</strong></p><p>先来看个例子：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>sum</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>alert</span><span>(</span><span>this</span><span>.</span><span>chinese</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>math</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>english</span><span>);</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>var</span><span><span> </span><span>xiaoming</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>5</div></div><div><span>  </span><span>chinese</span><span>:</span><span> </span><span>80</span><span>,</span></div></div><div><div><div>6</div></div><div><span>  </span><span>math</span><span>:</span><span> </span><span>95</span><span>,</span></div></div><div><div><div>7</div></div><div><span>  </span><span>english</span><span>:</span><span> </span><span>93</span><span>,</span></div></div><div><div><div>8</div></div><div><span>};</span></div></div><div><div><div>9</div></div><div><span>//想用xiaoming调用sum，就需要sum成为xiaomin的上下文也就是下面</span></div></div><div><div><div>10</div></div><div><span>var</span><span><span> </span><span>xiaoming</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>11</div></div><div><span>  </span><span>chinese</span><span>:</span><span> </span><span>80</span><span>,</span></div></div><div><div><div>12</div></div><div><span>  </span><span>math</span><span>:</span><span> </span><span>95</span><span>,</span></div></div><div><div><div>13</div></div><div><span>  </span><span>english</span><span>:</span><span> </span><span>93</span><span>,</span></div></div><div><div><div>14</div></div><div><span>  </span><span>sum</span><span>:</span><span>sum</span></div></div><div><div><div>15</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>但是现在有更简单的方式：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>sum</span><span>.</span></span><span>call</span><span><span>(</span><span>xiaoming</span><span>);</span></span></div></div><div><div><div>2</div></div><div><span><span>sum</span><span>.</span></span><span>apply</span><span><span>(</span><span>xiaoming</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>就可以让sum的上下文成为xiaomin对象的上下文</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>sum</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>// alert(this.chinese + this.math + this.english);</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>this</span><span>.</span><span>chinese</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>math</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>english</span><span>);</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div><span>var</span><span><span> </span><span>xiaoming</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>6</div></div><div><span>  </span><span>chinese</span><span>:</span><span> </span><span>80</span><span>,</span></div></div><div><div><div>7</div></div><div><span>  </span><span>math</span><span>:</span><span> </span><span>95</span><span>,</span></div></div><div><div><div>8</div></div><div><span>  </span><span>english</span><span>:</span><span> </span><span>93</span><span>,</span></div></div><div><div><div>9</div></div><div><span>};</span></div></div><div><div><div>10</div></div><div><span><span>sum</span><span>.</span></span><span>call</span><span><span>(</span><span>xiaoming</span><span>);</span></span></div></div><div><div><div>11</div></div><div><span><span>sum</span><span>.</span></span><span>apply</span><span><span>(</span><span>xiaoming</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>call和apply的区别</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>sum</span><span><span>(</span><span>b1</span><span>, </span><span>b2</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>alert</span><span>(</span><span>this</span><span>.</span><span>c</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>m</span><span> </span><span>+</span><span> </span><span>this</span><span>.</span><span>e</span><span> </span><span>+</span><span><span> </span><span>b1</span><span> </span></span><span>+</span><span><span> </span><span>b2</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span><span>sum</span><span>.</span></span><span>call</span><span><span>(</span><span>xiaoming</span><span>, </span></span><span>5</span><span>, </span><span>3</span><span>);</span><span>//call要用逗号罗列参数</span></div></div><div><div><div>5</div></div><div><span><span>sum</span><span>.</span></span><span>apply</span><span><span>(</span><span>xiaoming</span><span>, [</span></span><span>5</span><span>, </span><span>3</span><span>]);</span><span>//apply要把参数写到数组中</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>到底使用call还是apply？</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>fun1</span><span>() {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>fun2</span><span>.</span><span>apply</span><span>(</span><span>this</span><span>, </span><span>arguments</span><span>);</span><span>//arguments是类数组，所以只能使用apply</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>function</span><span> </span><span>fun2</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>);</span></span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div><span>fun1</span><span>(</span><span>33</span><span>, </span><span>44</span><span>);</span><span>//77</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>上下文规则总结</strong></p>

<table><thead><tr><th>规则</th><th>上下文</th></tr></thead><tbody><tr><td>对象.函数()</td><td>对象</td></tr><tr><td>函数()</td><td>window</td></tr><tr><td>数组[ 下标 ] ()</td><td>数组</td></tr><tr><td>IIFE</td><td>window</td></tr><tr><td>定时器</td><td>window</td></tr><tr><td>DOM事件处理函数</td><td>绑定DOM的元素</td></tr><tr><td>call和apply</td><td>任意指定</td></tr></tbody></table></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102005javascript-mian-xiang-dui-xiang/</id>
      <title type="text">JavaScript面向对象</title>
      <published>2026-10-20T06:39:22.000Z</published>
      <updated>2026-10-20T06:39:22.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102005javascript-mian-xiang-dui-xiang/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>本文主要学习Javascript的对象，对象的方法，如何遍历以及如何实现对象的深克隆</p>
<section><h1>认识对象<a href="#认识对象"><span>#</span></a></h1><p>对象（object）是“键值对”的集合，表示属性和值的映射 关系</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//JS中，大括号表示对象</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>xiaoming</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>3</div></div><div><span>name</span><span>:</span><span> </span><span>'小明'</span><span>,</span><span>//属性名（键名，key）；属性值（value）</span></div></div><div><div><div>4</div></div><div><span>age</span><span>:</span><span> </span><span>12</span><span>,</span></div></div><div><div><div>5</div></div><div><span>sex</span><span>:</span><span> </span><span>'男'</span><span>,</span></div></div><div><div><div>6</div></div><div><span>hobbies</span><span>:</span><span> [</span><span>'足球'</span><span>,</span><span>'编程'</span><span>]</span></div></div><div><div><div>7</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>对象的语法</strong></p><p>k和v之间用冒号分隔，每组k，最后一个 k</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>obj</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>k</span><span>:</span><span><span> </span><span>v</span><span>,</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>k</span><span>:</span><span><span> </span><span>v</span><span>,</span></span></div></div><div><div><div>4</div></div><div><span>    </span><span>k</span><span>:</span><span><span> </span><span>v</span><span>,</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>k</span><span>:</span><span><span> </span><span>v</span></span></div></div><div><div><div>6</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>属性是否加引号</strong></p><p>如果对象的属性键名不符合JS标识符命名规范，则这个键名 必须用引号包裹</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>xiaoming</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>name</span><span>:</span><span> </span><span>'小明'</span><span>,</span></div></div><div><div><div>3</div></div><div><span>    </span><span>age</span><span>:</span><span> </span><span>12</span><span>,</span></div></div><div><div><div>4</div></div><div><span>    </span><span>sex</span><span>:</span><span> </span><span>'男'</span><span>,</span></div></div><div><div><div>5</div></div><div><span>    </span><span>hobbys</span><span>:</span><span> [</span><span>'足球'</span><span>,</span><span>'游泳'</span><span>,</span><span>'编程'</span><span>],</span></div></div><div><div><div>6</div></div><div><span>   </span><span>'favorite-book'</span><span>:</span><span> </span><span>'舒克和贝塔'</span><span>//属性名中有短横，不符合JS标识符命名规范，属性名必须用引号包裹</span></div></div><div><div><div>7</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>属性的访问</strong></p><p>可以用“点语法”访问对象中指定键的值</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xiaoming</span><span>.</span></span><span>name</span><span>; </span><span>// '小明'</span></div></div><div><div><div>2</div></div><div><span><span>xiaoming</span><span>.</span></span><span>age</span><span>; </span><span>// 12</span></div></div><div><div><div>3</div></div><div><span><span>xiaoming</span><span>.</span></span><span>hobbys</span><span>; </span><span>// ['足球','游泳','编程']</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果属性名不符合JS标识符命名规范，则必须用方括号的写 法来访问</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xiaoming</span><span>[</span></span><span>'favorite-book'</span><span>]; </span><span>// '舒克和贝塔'；不符合标识符命名规范，就必须用方括号访问属性</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果属性名以变量形式存储，则必须使用方括号形式</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>obj</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>a</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>3</div></div><div><span>    </span><span>b</span><span>:</span><span> </span><span>2</span><span>,</span></div></div><div><div><div>4</div></div><div><span>    </span><span>c</span><span>:</span><span> </span><span>3</span></div></div><div><div><div>5</div></div><div><span>};</span></div></div><div><div><div>6</div></div><div><span>var</span><span><span> </span><span>key</span><span> </span></span><span>=</span><span> </span><span>'b'</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj</span><span>.</span></span><span>key</span><span>);</span><span>// undefined</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj</span><span>[</span><span>key</span><span>]);</span></span><span>// 2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>解释一下：var key = ‘b’;其实这里很明显就是key就是b，obj[key]=obj[‘b’]；根据属性名不符合JS标识符命名规范，则必须用方括号的写 法来访问，这里就是2，因为<strong>符合JS标识符命名规范，也可以用方括号的写 法来访问</strong></p><p><strong>属性的更改</strong></p><p>直接使用赋值运算符重新对某属性赋值即可更改属性</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>obj</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>10</span></div></div><div><div><div>3</div></div><div><span>};</span></div></div><div><div><div>4</div></div><div><span><span>obj</span><span>.</span></span><span>a</span><span> </span><span>=</span><span> </span><span>30</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>obj</span><span>.</span></span><span>a</span><span>++</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>属性的创建</strong></p><p>如果对象本身没有某个属性值，则用点语法赋值时，这个属 性会被创建出来</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>obj</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>a</span><span>:</span><span> </span><span>10</span></div></div><div><div><div>3</div></div><div><span>};</span></div></div><div><div><div>4</div></div><div><span><span>obj</span><span>.</span></span><span>b</span><span> </span><span>=</span><span> </span><span>40</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>属性的删除</strong></p><p>如果要删除某个对象的属性，需要使用delete操作符</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>obj</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>a</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>3</div></div><div><span>    </span><span>b</span><span>:</span><span> </span><span>2</span></div></div><div><div><div>4</div></div><div><span>};</span></div></div><div><div><div>5</div></div><div><span>delete</span><span><span> </span><span>obj</span><span>.</span></span><span>a</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>对象的方法<a href="#对象的方法"><span>#</span></a></h1><p>如果某个属性值是函数，则它也被称为对象的“方法”</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>xiaoming</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>name</span><span>:</span><span> </span><span>'小明'</span><span>,</span></div></div><div><div><div>3</div></div><div><span>    </span><span>age</span><span>:</span><span> </span><span>12</span><span>,</span></div></div><div><div><div>4</div></div><div><span>    </span><span>sex</span><span>:</span><span> </span><span>'男'</span><span>,</span></div></div><div><div><div>5</div></div><div><span>    </span><span>hobbys</span><span>:</span><span> [</span><span>'足球'</span><span>, </span><span>'游泳'</span><span>, </span><span>'编程'</span><span>], </span><span>'favorite-book'</span><span>:</span><span> </span><span>'舒克和贝塔'</span><span>,</span></div></div><div><div><div>6</div></div><div><span>    </span><span>sayHello</span><span>:</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>7</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'你好，我是小明，今年12岁，我是个男生'</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>方法的调用</strong></p><p>使用“点语法”可以调用对象的方法</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>xiaoming</span><span>.</span></span><span>sayHello</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>方法也是函数，只不过方法是对象的“函数属性”，它需要 用对象打点调用</p><p>在正式学习了什么是“方法”之后，就能深入理解之前我们 学习的一些函数的书写形式了，比如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>();</span></div></div><div><div><div>2</div></div><div><span><span>Math</span><span>.</span></span><span>ceil</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>对象的遍历<a href="#对象的遍历"><span>#</span></a></h1><ul>
<li>和遍历数组类似，对象也可以被遍历，遍历对象需要使用 for…in…循环</li>
<li>使用for…in…循环可以遍历对象的每个键</li>
<li>在后续的ES6相关课程中，还会学习新的对象遍历的方式</li>
</ul><p><strong>for…in…循环</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//var k：循环变量，它会依次成为对象的每一个键；obj：要遍历的对象</span></div></div><div><div><div>2</div></div><div><span>for</span><span> (</span><span>var</span><span><span> </span><span>k</span><span> </span></span><span>in</span><span><span> </span><span>obj</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'属性'</span><span> </span><span>+</span><span><span> </span><span>k</span><span> </span></span><span>+</span><span> </span><span>'的值是'</span><span> </span><span>+</span><span><span> </span><span>obj</span><span>[</span><span>k</span><span>]);</span></span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>对象的深浅克隆<a href="#对象的深浅克隆"><span>#</span></a></h1><p>对象是引用类型值</p><p>对象是引用类型值，这意味着：</p><p>不能用var obj2 = obj1这样的语法克隆一个对象</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>obj3</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>10</span><span>,</span></div></div><div><div><div>3</div></div><div><span>};</span></div></div><div><div><div>4</div></div><div><span>//obj4指向obj3，完全一个东西</span></div></div><div><div><div>5</div></div><div><span>var</span><span><span> </span><span>obj4</span><span> </span></span><span>=</span><span><span> </span><span>obj3</span><span>;</span></span></div></div><div><div><div>6</div></div><div><span><span>obj3</span><span>.</span></span><span>a</span><span>++</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj4</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>使用==或者===进行对象的比较时，比较的是它们是否为内 存中的同一个对象，而不是比较值是否相同</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>obj1</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>3</div></div><div><span>  </span><span>b</span><span>:</span><span> </span><span>2</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>c</span><span>:</span><span> </span><span>3</span><span>,</span></div></div><div><div><div>5</div></div><div><span>};</span></div></div><div><div><div>6</div></div><div><span>var</span><span><span> </span><span>obj2</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>7</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>1</span><span>,</span></div></div><div><div><div>8</div></div><div><span>  </span><span>b</span><span>:</span><span> </span><span>2</span><span>,</span></div></div><div><div><div>9</div></div><div><span>  </span><span>c</span><span>:</span><span> </span><span>3</span><span>,</span></div></div><div><div><div>10</div></div><div><span>};</span></div></div><div><div><div>11</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj1</span><span> </span></span><span>==</span><span><span> </span><span>obj2</span><span>); </span></span><span>//false 不同内存</span></div></div><div><div><div>12</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj1</span><span> </span></span><span>===</span><span><span> </span><span>obj2</span><span>); </span></span><span>//false</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>对象的浅克隆</strong></p><p>复习什么是浅克隆：只克隆对象的“表层”，如果对象的某 些属性值又是引用类型值，则不进一步克隆它们，只是传递 它们的引用</p><p>使用for…in…循环即可实现对象的浅克隆</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 浅克隆</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>obj1</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>10</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>b</span><span>:</span><span> </span><span>2</span><span>,</span></div></div><div><div><div>5</div></div><div><span>  </span><span>c</span><span>:</span><span> [</span><span>11</span><span>, </span><span>22</span><span>, </span><span>33</span><span>],</span></div></div><div><div><div>6</div></div><div><span>};</span></div></div><div><div><div>7</div></div><div><span>// var obj2 = obj1; //不是克隆</span></div></div><div><div><div>8</div></div><div><span>var</span><span><span> </span><span>obj2</span><span> </span></span><span>=</span><span> {};</span></div></div><div><div><div>9</div></div><div><span>for</span><span> (</span><span>var</span><span><span> </span><span>k</span><span> </span></span><span>in</span><span><span> </span><span>obj1</span><span>) {</span></span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>obj2</span><span>[</span><span>k</span><span>] </span><span>=</span><span><span> </span><span>obj1</span><span>[</span><span>k</span><span>];</span></span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div><span><span>obj1</span><span>.</span></span><span>a</span><span>++</span><span>;</span></div></div><div><div><div>13</div></div><div><span><span>obj1</span><span>.</span></span><span>c</span><span>.</span><span>push</span><span>(</span><span>77</span><span>); </span><span>//obj2也会推入77，因为是浅克隆</span></div></div><div><div><div>14</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj1</span><span> </span></span><span>===</span><span><span> </span><span>obj2</span><span>);</span></span></div></div><div><div><div>15</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj1</span><span>);</span></span></div></div><div><div><div>16</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj2</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>对象的深克隆</strong></p><p>复习什么是深克隆：克隆对象的全貌，不论对象的属性值是 否又是引用类型值，都能将它们实现克隆</p><p>和数组的深克隆类似，对象的深克隆需要使用递归</p><p>面试时经常会考察深克隆算法，必须掌握</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 深克隆</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>obj1</span><span> </span></span><span>=</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>a</span><span>:</span><span> </span><span>10</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>b</span><span>:</span><span> </span><span>2</span><span>,</span></div></div><div><div><div>5</div></div><div><span>  </span><span>c</span><span>:</span><span> [</span></div></div><div><div><div>6</div></div><div><span>    </span><span>11</span><span>,</span></div></div><div><div><div>7</div></div><div><span>    </span><span>22</span><span>,</span></div></div><div><div><div>8</div></div><div><span>    </span><span>33</span><span>,</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>{</span></div></div><div><div><div>10</div></div><div><span>      </span><span>m</span><span>:</span><span> </span><span>55</span><span>,</span></div></div><div><div><div>11</div></div><div><span>      </span><span>n</span><span>:</span><span> </span><span>66</span><span>,</span></div></div><div><div><div>12</div></div><div><span>      </span><span>p</span><span>:</span><span> [</span><span>11</span><span>, </span><span>33</span><span>],</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>},</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>],</span></div></div><div><div><div>15</div></div><div><span>};</span></div></div><div><div><div>16</div></div><div><span>function</span><span> </span><span>deepClone</span><span><span>(</span><span>obj</span><span>) {</span></span></div></div><div><div><div>17</div></div><div><span>  </span><span>if</span><span><span> (</span><span>Array</span><span>.</span></span><span>isArray</span><span><span>(</span><span>obj</span><span>)) {</span></span></div></div><div><div><div>18</div></div><div><span>    </span><span>//数组的处理方式</span></div></div><div><div><div>19</div></div><div><span>    </span><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span> [];</span></div></div><div><div><div>20</div></div><div><span>    </span><span>for</span><span> (</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>obj</span><span>.</span></span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>21</div></div><div><span><span>      </span></span><span>result</span><span>.</span><span>push</span><span>(</span><span>deepClone</span><span><span>(</span><span>obj</span><span>[</span><span>i</span><span>]));</span></span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>23</div></div><div><span><span>  </span></span><span>} </span><span>else</span><span> </span><span>if</span><span> (</span><span>typeof</span><span><span> </span><span>obj</span><span> </span></span><span>==</span><span> </span><span>'object'</span><span>) {</span></div></div><div><div><div>24</div></div><div><span>    </span><span>//对象</span></div></div><div><div><div>25</div></div><div><span>    </span><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span> {};</span></div></div><div><div><div>26</div></div><div><span>    </span><span>for</span><span> (</span><span>var</span><span><span> </span><span>k</span><span> </span></span><span>in</span><span><span> </span><span>obj</span><span>) {</span></span></div></div><div><div><div>27</div></div><div><span><span>      </span></span><span>result</span><span>[</span><span>k</span><span>] </span><span>=</span><span> </span><span>deepClone</span><span><span>(</span><span>obj</span><span>[</span><span>k</span><span>]);</span></span></div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>29</div></div><div><span><span>  </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>30</div></div><div><span>    </span><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span><span> </span><span>obj</span><span>;</span></span></div></div><div><div><div>31</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>32</div></div><div><span>  </span><span>return</span><span><span> </span><span>result</span><span>;</span></span></div></div><div><div><div>33</div></div><div><span>}</span></div></div><div><div><div>34</div></div><div><span>var</span><span><span> </span><span>obj2</span><span> </span></span><span>=</span><span> </span><span>deepClone</span><span><span>(</span><span>obj1</span><span>);</span></span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span><span>obj1</span><span>.</span></span><span>a</span><span>++</span><span>;</span></div></div><div><div><div>37</div></div><div><span><span>obj1</span><span>.</span></span><span>c</span><span>.</span><span>push</span><span>(</span><span>77</span><span>); </span><span>//obj2不会推入77，因为是深克隆</span></div></div><div><div><div>38</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj1</span><span> </span></span><span>===</span><span><span> </span><span>obj2</span><span>);</span></span></div></div><div><div><div>39</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj1</span><span>);</span></span></div></div><div><div><div>40</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj2</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102004javascript-de-ding-shi-qi-he-yan-shi-qi/</id>
      <title type="text">JavaScript的定时器和延时器</title>
      <published>2026-10-20T06:00:23.000Z</published>
      <updated>2026-10-20T06:00:23.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102004javascript-de-ding-shi-qi-he-yan-shi-qi/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>定时器和延时器<a href="#定时器和延时器"><span>#</span></a></h1><p><strong>定时器</strong></p><ul>
<li>
<p>setInterval()函数可以重复调用一个函数，在每次调用之 间具有固定的时间间隔</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>setInterval</span><span>(</span><span>function</span><span> () {</span><span>//第一个参数是函数</span></div></div><div><div><div>2</div></div><div><span>// 这个函数将自动被以固定间隔时间调用</span></div></div><div><div><div>3</div></div><div><span>}, </span><span>2000</span><span>);</span><span>//第二个参数是间隔时间，以毫秒为单位，1000毫秒是1秒</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>函数的参数</strong></p><ul>
<li>
<p>setInterval()函数可以接收第3、4……个参数，它们将按顺 序传入函数</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>setInterval</span><span>(</span><span>function</span><span><span> (</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>// 形式参数a的值是88，形式参数b的值是66</span></div></div><div><div><div>3</div></div><div><span>}, </span><span>2000</span><span>, </span><span>88</span><span>, </span><span>66</span><span>);</span><span>//从第三个参数开始，表示传入函数内的参数</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>具名函数也可以传入setInterval</strong></p><ul>
<li>
<p>具名函数也可以传入setInterval</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>2</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>++</span><span><span>a</span><span>);</span></span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div><span>setInterval</span><span><span>(</span><span>fun</span><span>, </span></span><span>1000</span><span>);</span><span>//具名函数当做第一个参数，注意这里没有圆括号！</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>清除定时器</strong></p><ul>
<li>
<p>clearInterval()函数可以清除一个定时器</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 设置定时器，并且用timer变量接收这个定时器</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>timer</span><span> </span></span><span>=</span><span> </span><span>setInterval</span><span>(</span><span>function</span><span> () {</span></div></div><div><div><div>3</div></div><div><span>}, </span><span>2000</span><span>);</span><span>//用变量timer接收定时器</span></div></div><div><div><div>4</div></div><div><span>// 点击按钮时，清除定时器</span></div></div><div><div><div>5</div></div><div><span><span>oBtn</span><span>.</span></span><span>onclick</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>6</div></div><div><span>  </span><span>clearInterval</span><span><span>(</span><span>timer</span><span>);</span></span><span>//清除定时器的时候，要传入定时器变量</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>延时器</strong></p><ul>
<li>
<p>setTimeout()函数可以设置一个延时器，当指定时间到了 之后，会执行函数一次，不再重复执行。</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>setTimeout</span><span>(</span><span>function</span><span> () {</span></div></div><div><div><div>2</div></div><div><span>// 这个函数会在2秒后执行一次</span></div></div><div><div><div>3</div></div><div><span>}, </span><span>2000</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>清除延时器</strong></p><ul>
<li>clearTimeout()函数可以清除延时器，和clearInterval() 非常类似</li>
</ul><p><strong>初步认识异步语句</strong></p><ul>
<li>setInterval()和setTimeout()是两个异步语句</li>
<li>异步（asynchronous）：不会阻塞CPU继续执行其他语句， 当异步完成时，会执行“回调函数”（callback）</li>
</ul></section>
<section><h1>使用定时器实现动画<a href="#使用定时器实现动画"><span>#</span></a></h1><ul>
<li>
<p>动画是网页上非常常见的业务需求</p>
</li>
<li>
<p>使用定时器可以实现动画，利用的就是“视觉暂留”原理</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>&lt;</span><span>button</span><span> </span><span>id</span><span>=</span><span>"btn"</span><span>&gt;点击移动&lt;/</span><span>button</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>id</span><span>=</span><span>"box"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>        </span><span>var</span><span><span> </span><span>box</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"box"</span><span>);</span></div></div><div><div><div>6</div></div><div><span>        </span><span>var</span><span><span> </span><span>btn</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"btn"</span><span>);</span></div></div><div><div><div>7</div></div><div><span>        </span><span>var</span><span><span> </span><span>left</span><span> </span></span><span>=</span><span> </span><span>100</span><span>;</span></div></div><div><div><div>8</div></div><div><span>        </span><span>// 点击按钮,移动盒子</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>btn</span><span>.</span><span>onclick</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>10</div></div><div><span>            </span><span>setInterval</span><span>(</span><span>function</span><span> () {</span></div></div><div><div><div>11</div></div><div><span><span>                </span></span><span>left</span><span> </span><span>+=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>12</div></div><div><span>                </span><span>if</span><span><span>(</span><span>left</span><span> </span></span><span>&gt;=</span><span> </span><span>1000</span><span>){</span></div></div><div><div><div>13</div></div><div><span>                    </span><span>clearInterval</span><span><span>(</span><span>timer</span><span>);</span></span></div></div><div><div><div>14</div></div><div><span><span>                </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span><span>                </span></span><span>box</span><span>.</span><span>style</span><span>.</span><span>left</span><span> </span><span>=</span><span><span> </span><span>left</span></span><span>+</span><span>"px"</span><span>;</span></div></div><div><div><div>16</div></div><div><span><span>            </span></span><span>}, </span><span>20</span><span>);</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>20</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
</li>
<li>
<p>使用定时器实现动画较为不便：不方便根据动画总时间计算步长；运动方向要设置正负；多种运动进行叠加较为困难（比如一个方形一边移动 一边变为圆形）</p>
</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102003javascript-de-dom-zhi-shi-jian/</id>
      <title type="text">JavaScript的DOM之事件</title>
      <published>2026-10-20T05:46:32.000Z</published>
      <updated>2026-10-20T05:46:32.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102003javascript-de-dom-zhi-shi-jian/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>本章主要学习DOM里面的事件，包括事件监听、传播、对象和委托</p>
<section><h1>事件监听<a href="#事件监听"><span>#</span></a></h1><p><strong>什么是“事件监听”</strong></p><ul>
<li>DOM允许我们书写JavaScript代码以让HTML元素对事件作 出反应</li>
<li>什么是“事件”：用户与网页的交互动作</li>
<li>“监听”，顾名思义，就是让计算机随时能够发现这个事件 发生了，从而执行程序员预先编写的一些程序</li>
<li>设置事件监听的方法主要有onxxx和addEventListener() 两种，二者的区别将在“事件传播”一课中介绍</li>
</ul><p><strong>最简单的设置事件监听的方法</strong></p><p>最简单的给元素设置事件监听的方法就是设置它们的onxxx 属性，像这样：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>oBox</span><span>.</span></span><span>onclick</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>// 点击盒子时，将执行这里的语句</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>常见的鼠标事件监听</strong></p>

<table><thead><tr><th>事件名</th><th>事件描述</th></tr></thead><tbody><tr><td>onclick</td><td>当鼠标单击某个对象</td></tr><tr><td>ondblclick</td><td>当鼠标双击某个对象</td></tr><tr><td>onmousedown</td><td>当某个鼠标按键在某个对象上被按下</td></tr><tr><td>onmouseup</td><td>当某个鼠标按键在某个对象上被松开</td></tr><tr><td>onmousemove</td><td>当某个鼠标按键在某个对象上被移动</td></tr><tr><td>onmouseenter</td><td>当鼠标进入某个对象（相似事件onmouseover）</td></tr><tr><td>onmouseleave</td><td>当鼠标离开某个对象（相似事件onmouseout）</td></tr></tbody></table><p><strong>常见的键盘事件监听</strong></p>

<table><thead><tr><th>事件名</th><th>事件描述</th></tr></thead><tbody><tr><td>onkeypress</td><td>当某个键盘的键被按下（系统按钮如箭头键和 功能键无法得到识别）</td></tr><tr><td>onkeydown</td><td>当某个键盘的键被按下（系统按钮可以识别， 并且会先于onkeypress发生）</td></tr><tr><td>onkeyup</td><td>当某个键盘的键被松开</td></tr></tbody></table><p><strong>常见的表单事件监听</strong></p>

<table><thead><tr><th>事件名</th><th>事件描述</th></tr></thead><tbody><tr><td>onchange</td><td>当用户改变域的内容</td></tr><tr><td>onfocus</td><td>当某元素获得焦点（比如tab键或鼠标点击）</td></tr><tr><td>onblur</td><td>当某元素失去焦点</td></tr><tr><td>onsubmit</td><td>当表单被提交</td></tr><tr><td>onreset</td><td>当表单被重置</td></tr></tbody></table><p><strong>常见的页面事件监听</strong></p>

<table><thead><tr><th>事件名</th><th>事件描述</th></tr></thead><tbody><tr><td>onload</td><td>当页面或图像被完成加载</td></tr><tr><td>onunload</td><td>当用户退出页面</td></tr></tbody></table></section>
<section><h1>事件传播<a href="#事件传播"><span>#</span></a></h1><p><strong>思考一个问题</strong></p><ul>
<li>如果一个div里面嵌套div，这个div里边又嵌套div，当点击div的时候，点击的是哪个div呢</li>
</ul><p><strong>研究：当盒子嵌套时事件监听的执行顺序</strong></p><p>监听box1的 onclick事件；监听box2的 onclick事件；监听了box3的 onclick事件</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>    </span><span>#box1</span><span>{</span></div></div><div><div><div>3</div></div><div><span><span>        </span></span><span>width: </span><span><span>202</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>        </span></span><span>height: </span><span><span>202</span><span>px</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>padding: </span><span><span>50</span><span>px</span></span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>       </span></span><span>border: </span><span><span>1</span><span>px</span></span><span><span> </span><span>solid</span><span> </span></span><span>red</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>8</div></div><div><span>    </span><span>#box2</span><span>{</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>width: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>height: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>        </span></span><span>padding: </span><span><span>50</span><span>px</span></span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>       </span></span><span>border: </span><span><span>1</span><span>px</span></span><span><span> </span><span>solid</span><span> </span></span><span>red</span><span>;</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span>    </span><span>#box3</span><span>{</span></div></div><div><div><div>15</div></div><div><span><span>        </span></span><span>width: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>height: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>border: </span><span><span>1</span><span>px</span></span><span><span> </span><span>solid</span><span> </span></span><span>red</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>19</div></div><div><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>20</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>id</span><span>=</span><span>"box1"</span><span>&gt;</span></div></div><div><div><div>22</div></div><div><span><span>        </span></span><span>&lt;</span><span>div</span><span> </span><span>id</span><span>=</span><span>"box2"</span><span>&gt;</span></div></div><div><div><div>23</div></div><div><span><span>            </span></span><span>&lt;</span><span>div</span><span> </span><span>id</span><span>=</span><span>"box3"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>24</div></div><div><span><span>        </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>26</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>27</div></div><div><span>        </span><span>var</span><span><span> </span><span>box1</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"box1"</span><span>);</span></div></div><div><div><div>28</div></div><div><span>        </span><span>var</span><span><span> </span><span>box2</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"box2"</span><span>);</span></div></div><div><div><div>29</div></div><div><span>        </span><span>var</span><span><span> </span><span>box3</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"box3"</span><span>);</span></div></div><div><div><div>30</div></div><div><span><span>        </span></span><span>box1</span><span>.</span><span>onclick</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>31</div></div><div><span><span>            </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"点击了box1"</span><span>);</span></div></div><div><div><div>32</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>33</div></div><div><span><span>        </span></span><span>box2</span><span>.</span><span>onclick</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>34</div></div><div><span><span>            </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"点击了box2"</span><span>);</span></div></div><div><div><div>35</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>36</div></div><div><span><span>        </span></span><span>box3</span><span>.</span><span>onclick</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>37</div></div><div><span><span>            </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"点击了box3"</span><span>);</span></div></div><div><div><div>38</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>39</div></div><div><span><span>        </span></span><span>box1</span><span>.</span><span>addEventListener</span><span>(</span><span>"click"</span><span>,</span><span>function</span><span> () {</span></div></div><div><div><div>40</div></div><div><span><span>            </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"点击了box1"</span><span>);</span></div></div><div><div><div>41</div></div><div><span><span>        </span></span><span>},</span><span>true</span><span>)</span></div></div><div><div><div>42</div></div><div><span><span>        </span></span><span>box2</span><span>.</span><span>addEventListener</span><span>(</span><span>"click"</span><span>,</span><span>function</span><span> () {</span></div></div><div><div><div>43</div></div><div><span><span>            </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"点击了box2"</span><span>);</span></div></div><div><div><div>44</div></div><div><span><span>        </span></span><span>},</span><span>true</span><span>)</span></div></div><div><div><div>45</div></div><div><span><span>        </span></span><span>box3</span><span>.</span><span>addEventListener</span><span>(</span><span>"click"</span><span>,</span><span>function</span><span> () {</span></div></div><div><div><div>46</div></div><div><span><span>            </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"点击了box3"</span><span>);</span></div></div><div><div><div>47</div></div><div><span><span>        </span></span><span>},</span><span>true</span><span>)</span></div></div><div><div><div>48</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>49</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><ul>
<li>输出：点击了box3；点击了box2；点击了box1</li>
<li>通过测试：感觉事件的传播是从内到外的（不成熟）</li>
<li>实际上，事件的传播是：先从外到内，然后再从内到外</li>
<li>从外到内叫捕获阶段；从内到外叫冒泡阶段</li>
</ul><p><strong>onxxx写法只能监听冒泡阶段</strong></p><ul>
<li>onxxx这样的写法只能监听冒泡阶段（这样也证明了刚才为什么只监听到冒泡阶段）</li>
</ul><p><strong>addEventListener()方法</strong>（监听捕获阶段）</p><ul>
<li>
<p>DOM0级事件监听：只能监听冒泡阶段</p>
</li>
<li>
<p>DOM2级事件监听</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//click；事件名不加on</span></div></div><div><div><div>2</div></div><div><span><span>oBox</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'click'</span><span>, </span><span>function</span><span> () {</span></div></div><div><div><div>3</div></div><div><span>// 这是事件处理函数</span></div></div><div><div><div>4</div></div><div><span>}, </span><span>true</span><span>);</span><span>//true监听捕获阶段，false监听冒泡阶段</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>注意事项</strong></p><ul>
<li>最内部元素不再区分捕获和冒泡阶段，会先执行写在前面的 监听，然后执行后写的监听</li>
<li>如果给元素设置相同的两个或多个同名事件，则DOM0级写法 后面写的会覆盖先写的；而DOM2级会按顺序执行</li>
</ul></section>
<section><h1>事件对象<a href="#事件对象"><span>#</span></a></h1><p><strong>什么是事件对象</strong></p><ul>
<li>
<p>事件处理函数提供一个形式参数，它是一个对象，封装了本 次事件的细节</p>
</li>
<li>
<p>这个参数通常用单词event或字母e来表示</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>oBox.onmousemove = function (e) {</span></div></div><div><div><div>2</div></div><div><span>// 对象e就是这次事件的“事件对象”</span></div></div><div><div><div>3</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>鼠标位置</strong></p>

<table><thead><tr><th>属性</th><th>属性描述</th></tr></thead><tbody><tr><td>clientX</td><td>鼠标指针相对于浏览器的水平坐标</td></tr><tr><td>clientY</td><td>鼠标指针相对于浏览器的垂直坐标</td></tr><tr><td>pageX</td><td>鼠标指针相对于整张网页的水平坐标</td></tr><tr><td>pageY</td><td>鼠标指针相对于整张网页的垂直坐标</td></tr><tr><td>offsetX</td><td>鼠标指针相对于事件源元素的水平坐标</td></tr><tr><td>offsetY</td><td>鼠标指针相对于事件源元素的垂直坐标</td></tr></tbody></table><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>        </span><span>body</span><span>{</span></div></div><div><div><div>3</div></div><div><span><span>            </span></span><span>height: </span><span><span>1000</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>        </span><span>#app</span><span>{</span></div></div><div><div><div>6</div></div><div><span><span>            </span></span><span>width: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>            </span></span><span>height: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>            </span></span><span>background-color: </span><span>pink</span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span>        </span><span>#info</span><span>{</span></div></div><div><div><div>11</div></div><div><span><span>            </span></span><span>font-size: </span><span><span>30</span><span>px</span></span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>14</div></div><div><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>15</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>id</span><span>=</span><span>"app"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>id</span><span>=</span><span>"info"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>19</div></div><div><span>        </span><span>var</span><span><span> </span><span>info</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"info"</span><span>);</span></div></div><div><div><div>20</div></div><div><span>        </span><span>//事件对象</span></div></div><div><div><div>21</div></div><div><span><span>        </span></span><span>document</span><span>.</span><span>getElementById</span><span>(</span><span>"app"</span><span>).</span><span>onmousemove</span><span> </span><span>=</span><span> </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>22</div></div><div><span>            </span><span>//获取鼠标移动到的位置</span></div></div><div><div><div>23</div></div><div><span><span>            </span></span><span>info</span><span>.</span><span>innerHTML</span><span> </span><span>=</span><span> </span><span>"x相对于浏览器窗口:"</span><span> </span><span>+</span><span><span> </span><span>e</span><span>.</span></span><span>clientX</span><span> </span><span>+</span><span> </span><span>" y相对于浏览器窗口:"</span><span> </span><span>+</span><span><span> </span><span>e</span><span>.</span></span><span>clientY</span><span>+</span><span>"&lt;br&gt;"</span><span>;</span></div></div><div><div><div>24</div></div><div><span><span>            </span></span><span>info</span><span>.</span><span>innerHTML</span><span> </span><span>+=</span><span> </span><span>"x相对于元素:"</span><span> </span><span>+</span><span><span> </span><span>e</span><span>.</span></span><span>offsetX</span><span> </span><span>+</span><span> </span><span>" y相对于元素:"</span><span> </span><span>+</span><span><span> </span><span>e</span><span>.</span></span><span>offsetY</span><span>+</span><span>"&lt;br&gt;"</span><span>;</span></div></div><div><div><div>25</div></div><div><span><span>            </span></span><span>info</span><span>.</span><span>innerHTML</span><span> </span><span>+=</span><span> </span><span>"x相对于文档:"</span><span> </span><span>+</span><span><span> </span><span>e</span><span>.</span></span><span>pageX</span><span> </span><span>+</span><span> </span><span>" y相对于文档:"</span><span> </span><span>+</span><span><span> </span><span>e</span><span>.</span></span><span>pageY</span><span>;</span></div></div><div><div><div>26</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>27</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>28</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>e.charCode和e.keyCode属性</strong></p><ul>
<li>e.charCode属性通常用于onkeypress事件中，表示用户输 入的字符的“字符码”</li>
<li>e.keyCode属性通常用于onkeydown事件和onkeyup中，表 示用户按下的按键的“键码”</li>
</ul><p>charCode字符码</p>

<table><thead><tr><th>字符</th><th>字符码</th></tr></thead><tbody><tr><td>数字0 ~ 数字9</td><td>48 ~ 57</td></tr><tr><td>大写字母A ~ Z</td><td>65 ~ 90</td></tr><tr><td>小写字母a ~ z</td><td>97 ~ 122</td></tr></tbody></table><p>keyCode键码</p>

<table><thead><tr><th>按键</th><th>键码</th></tr></thead><tbody><tr><td>数字0 ~ 数字9</td><td>48 ~ 57（同charCode键码完全相同）</td></tr><tr><td>字母不分大小a ~ z</td><td>65 ~ 90（同charCode键码的大写字母A ~ Z，而 keyCode不分大小写，一律为65 ~ 90）</td></tr><tr><td>四个方向键← ↑ → ↓</td><td>37、38、39、40</td></tr><tr><td>回车键</td><td>13</td></tr><tr><td>空格键</td><td>32</td></tr></tbody></table><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"text"</span><span> </span><span>name</span><span>=</span><span>""</span><span> </span><span>id</span><span>=</span><span>"field"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>&lt;</span><span>h1</span><span> </span><span>id</span><span>=</span><span>"info"</span><span>&gt;&lt;/</span><span>h1</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"text"</span><span> </span><span>name</span><span>=</span><span>""</span><span> </span><span>id</span><span>=</span><span>"field1"</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>&lt;</span><span>h1</span><span> </span><span>id</span><span>=</span><span>"info1"</span><span>&gt;&lt;/</span><span>h1</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span>        </span><span>var</span><span><span> </span><span>field</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"field"</span><span>);</span></div></div><div><div><div>8</div></div><div><span>        </span><span>var</span><span><span> </span><span>info</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"info"</span><span>);</span></div></div><div><div><div>9</div></div><div><span>        </span><span>var</span><span><span> </span><span>field1</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"field1"</span><span>);</span></div></div><div><div><div>10</div></div><div><span>        </span><span>var</span><span><span> </span><span>info1</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"info1"</span><span>);</span></div></div><div><div><div>11</div></div><div><span>        </span><span>//事件对象</span></div></div><div><div><div>12</div></div><div><span><span>        </span></span><span>field</span><span>.</span><span>onkeydown</span><span> </span><span>=</span><span> </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>13</div></div><div><span><span>            </span></span><span>info</span><span>.</span><span>innerHTML</span><span> </span><span>+=</span><span> </span><span>"keyCode:"</span><span> </span><span>+</span><span><span> </span><span>e</span><span>.</span></span><span>keyCode</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span><span>        </span></span><span>field1</span><span>.</span><span>onkeypress</span><span> </span><span>=</span><span> </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>16</div></div><div><span><span>            </span></span><span>info1</span><span>.</span><span>innerHTML</span><span> </span><span>+=</span><span> </span><span>"charCode:"</span><span> </span><span>+</span><span><span> </span><span>e</span><span>.</span></span><span>charCode</span><span>;</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>19</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>小案例</strong></p><p>制作一个特效：按方向键可以控制页面上的盒子移动</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>        </span><span>#box</span><span>{</span></div></div><div><div><div>3</div></div><div><span><span>            </span></span><span>position: </span><span>absolute</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>            </span></span><span>width: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>            </span></span><span>height: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>            </span></span><span>top: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>            </span></span><span>left: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>            </span></span><span>background-color: </span><span>pink</span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>11</div></div><div><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>12</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>id</span><span>=</span><span>"box"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>15</div></div><div><span>        </span><span>var</span><span><span> </span><span>box</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"box"</span><span>);</span></div></div><div><div><div>16</div></div><div><span>        </span><span>var</span><span><span> </span><span>t</span><span> </span></span><span>=</span><span> </span><span>200</span><span>;</span></div></div><div><div><div>17</div></div><div><span>        </span><span>var</span><span><span> </span><span>l</span><span> </span></span><span>=</span><span> </span><span>200</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>        </span></span><span>document</span><span>.</span><span>onkeydown</span><span> </span><span>=</span><span> </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>19</div></div><div><span>            </span><span>switch</span><span><span> (</span><span>e</span><span>.</span></span><span>keyCode</span><span>) {</span></div></div><div><div><div>20</div></div><div><span>                </span><span>case</span><span> </span><span>38</span><span>:</span></div></div><div><div><div>21</div></div><div><span><span>                    </span></span><span>t</span><span> </span><span>-=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>22</div></div><div><span>                    </span><span>break</span><span>;</span></div></div><div><div><div>23</div></div><div><span>                </span><span>case</span><span> </span><span>40</span><span>:</span></div></div><div><div><div>24</div></div><div><span><span>                    </span></span><span>t</span><span> </span><span>+=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>25</div></div><div><span>                    </span><span>break</span><span>;</span></div></div><div><div><div>26</div></div><div><span>                </span><span>case</span><span> </span><span>37</span><span>:</span></div></div><div><div><div>27</div></div><div><span><span>                    </span></span><span>l</span><span> </span><span>-=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>28</div></div><div><span>                    </span><span>break</span><span>;</span></div></div><div><div><div>29</div></div><div><span>                </span><span>case</span><span> </span><span>39</span><span>:</span></div></div><div><div><div>30</div></div><div><span><span>                    </span></span><span>l</span><span> </span><span>+=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>31</div></div><div><span>                    </span><span>break</span><span>;</span></div></div><div><div><div>32</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>33</div></div><div><span><span>            </span></span><span>box</span><span>.</span><span>style</span><span>.</span><span>left</span><span> </span><span>=</span><span><span> </span><span>l</span><span> </span></span><span>+</span><span> </span><span>"px"</span><span>;</span></div></div><div><div><div>34</div></div><div><span><span>            </span></span><span>box</span><span>.</span><span>style</span><span>.</span><span>top</span><span> </span><span>=</span><span><span> </span><span>t</span><span> </span></span><span>+</span><span> </span><span>"px"</span><span>;</span></div></div><div><div><div>35</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>36</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>37</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>e.preventDefault()方法</strong></p><ul>
<li>e.preventDefault()方法用来阻止事件产生的“默认动作”</li>
<li>一些特殊的业务需求，需要阻止事件的“默认动作”</li>
</ul><p><strong>小案例1</strong></p><p>制作一个文本框，只能让用户在其中输入小写字母和数字，其他字符输入没有效果</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"text"</span><span> </span><span>id</span><span>=</span><span>"inp"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>        </span><span>var</span><span><span> </span><span>inp</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"inp"</span><span>);</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>inp</span><span>.</span><span>onkeypress</span><span> </span><span>=</span><span> </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>6</div></div><div><span><span>            </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>e</span><span>.</span></span><span>charCode</span><span>);</span></div></div><div><div><div>7</div></div><div><span>            </span><span>// 限制只能输入数字和字母</span></div></div><div><div><div>8</div></div><div><span>            </span><span>// 48-57 0-9</span></div></div><div><div><div>9</div></div><div><span>            </span><span>// 97-122 a-z</span></div></div><div><div><div>10</div></div><div><span>            </span><span>if</span><span>(</span><span>!</span><span><span>(</span><span>e</span><span>.</span></span><span>charCode</span><span> </span><span>&gt;=</span><span> </span><span>48</span><span> </span><span>&amp;&amp;</span><span><span> </span><span>e</span><span>.</span></span><span>charCode</span><span> </span><span>&lt;=</span><span> </span><span>57</span><span>||</span><span><span>e</span><span>.</span></span><span>charCode</span><span> </span><span>&gt;=</span><span> </span><span>97</span><span> </span><span>&amp;&amp;</span><span><span> </span><span>e</span><span>.</span></span><span>charCode</span><span> </span><span>&lt;=</span><span> </span><span>122</span><span>)){</span></div></div><div><div><div>11</div></div><div><span><span>                </span></span><span>e</span><span>.</span><span>preventDefault</span><span>();</span></div></div><div><div><div>12</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>15</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>小案例2</strong></p><p>制作鼠标滚轮事件：当鼠标在盒子中向下滚动时，数字加1； 反之，数字减1</p><p>鼠标滚轮事件是onmousewheel，它的事件对象e提供deltaY 属性表示鼠标滚动方向，向下滚动时返回正值，向上滚动时返 回负值</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>        </span><span>#box</span><span>{</span></div></div><div><div><div>3</div></div><div><span><span>            </span></span><span>width: </span><span><span>500</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>            </span></span><span>height: </span><span><span>500</span><span>px</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>            </span></span><span>background-color: </span><span>pink</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span>        </span><span>body</span><span>{</span></div></div><div><div><div>8</div></div><div><span><span>           </span></span><span>height: </span><span><span>1000</span><span>px</span></span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>11</div></div><div><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>12</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>id</span><span>=</span><span>"box"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>&lt;</span><span>h1</span><span> </span><span>id</span><span>=</span><span>"num"</span><span>&gt;0&lt;/</span><span>h1</span><span>&gt;</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>16</div></div><div><span>        </span><span>//制作鼠标滚轮事件：当鼠标在盒子中向下滚动时，数字加1； 反之，数字减1</span></div></div><div><div><div>17</div></div><div><span>        </span><span>var</span><span><span> </span><span>box</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"box"</span><span>);</span></div></div><div><div><div>18</div></div><div><span>        </span><span>var</span><span><span> </span><span>num</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"num"</span><span>);</span></div></div><div><div><div>19</div></div><div><span>        </span><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>20</div></div><div><span><span>        </span></span><span>box</span><span>.</span><span>onmousewheel</span><span> </span><span>=</span><span> </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>21</div></div><div><span><span>            </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>e</span><span>.</span></span><span>deltaY</span><span>);</span></div></div><div><div><div>22</div></div><div><span>            </span><span>// 阻止默认事件,当在盒子里面滚动的时候不会引发页面的滚动</span></div></div><div><div><div>23</div></div><div><span><span>            </span></span><span>e</span><span>.</span><span>preventDefault</span><span>();</span></div></div><div><div><div>24</div></div><div><span>            </span><span>if</span><span><span>(</span><span>e</span><span>.</span></span><span>deltaY</span><span> </span><span>&gt;</span><span> </span><span>0</span><span>){</span></div></div><div><div><div>25</div></div><div><span><span>               </span></span><span>a</span><span>--</span><span>;</span></div></div><div><div><div>26</div></div><div><span><span>            </span></span><span>}</span><span>else</span><span>{</span></div></div><div><div><div>27</div></div><div><span><span>                </span></span><span>a</span><span>++</span><span>;</span></div></div><div><div><div>28</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>29</div></div><div><span><span>            </span></span><span>num</span><span>.</span><span>innerText</span><span> </span><span>=</span><span><span> </span><span>a</span><span>;</span></span></div></div><div><div><div>30</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>31</div></div><div>
</div></div><div><div><div>32</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>33</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>e. stopPropagation()方法</strong></p><ul>
<li>e.stopPropagation()方法用来阻止事件继续传播</li>
<li>在一些场合，非常有必要切断事件继续传播，否则会造成页 面特效显示出bug</li>
</ul><p><strong>小案例：</strong></p><p>制作一个弹出层：点击按钮显示弹出层，点击网页任意地方， 弹出层关闭</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>        </span><span>#menu</span><span>{</span></div></div><div><div><div>3</div></div><div><span><span>            </span></span><span>width: </span><span><span>400</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>            </span></span><span>height: </span><span><span>140</span><span>px</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>            </span></span><span>background-color: </span><span>pink</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>            </span></span><span>position: </span><span>absolute</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>            </span></span><span>top:</span><span><span>50</span><span>%</span></span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>            </span></span><span>left:</span><span><span>50</span><span>%</span></span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>            </span></span><span>transform: </span><span>translate</span><span>(</span><span><span>-50</span><span>%</span></span><span>,</span><span><span>-50</span><span>%</span></span><span>);</span></div></div><div><div><div>10</div></div><div><span><span>            </span></span><span>margin: </span><span>0</span><span><span> </span><span>auto</span><span>;</span></span></div></div><div><div><div>11</div></div><div><span><span>            </span></span><span>display: </span><span>none</span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>14</div></div><div><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>15</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>&lt;</span><span>button</span><span> </span><span>id</span><span>=</span><span>"btn"</span><span>&gt;点击弹出菜单&lt;/</span><span>button</span><span>&gt;</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>id</span><span>=</span><span>"menu"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>19</div></div><div><span>        </span><span>var</span><span><span> </span><span>btn</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"btn"</span><span>);</span></div></div><div><div><div>20</div></div><div><span>        </span><span>var</span><span><span> </span><span>menu</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"menu"</span><span>);</span></div></div><div><div><div>21</div></div><div><span>        </span><span>// 点击按钮弹出菜单</span></div></div><div><div><div>22</div></div><div><span><span>        </span></span><span>btn</span><span>.</span><span>onclick</span><span> </span><span>=</span><span> </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>23</div></div><div><span>            </span><span>// 阻止事件冒泡，如果不阻止事件冒泡，点击按钮会触发点击其他地方隐藏菜单的事件，导致菜单显示后立即隐藏</span></div></div><div><div><div>24</div></div><div><span><span>            </span></span><span>e</span><span>.</span><span>stopPropagation</span><span>();</span></div></div><div><div><div>25</div></div><div><span><span>            </span></span><span>menu</span><span>.</span><span>style</span><span>.</span><span>display</span><span> </span><span>=</span><span> </span><span>"block"</span><span>;</span></div></div><div><div><div>26</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>27</div></div><div><span>        </span><span>// 点击其他地方隐藏菜单</span></div></div><div><div><div>28</div></div><div><span><span>        </span></span><span>document</span><span>.</span><span>onclick</span><span> </span><span>=</span><span> </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>29</div></div><div><span><span>            </span></span><span>menu</span><span>.</span><span>style</span><span>.</span><span>display</span><span> </span><span>=</span><span> </span><span>"none"</span><span>;</span></div></div><div><div><div>30</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>31</div></div><div><span>        </span><span>// 点击菜单不隐藏菜单</span></div></div><div><div><div>32</div></div><div><span><span>        </span></span><span>menu</span><span>.</span><span>onclick</span><span> </span><span>=</span><span> </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>33</div></div><div><span><span>            </span></span><span>e</span><span>.</span><span>stopPropagation</span><span>();</span></div></div><div><div><div>34</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>35</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>36</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h1>事件委托<a href="#事件委托"><span>#</span></a></h1><p><strong>批量添加事件监听</strong></p><ul>
<li>
<p>题目：页面上有一个无序列表ul，它内部共有20个li元素，请批量给它们添加点击事件监听，实现效果：点击 哪个li元素，哪个li元素就变红</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>&lt;</span><span>ul</span><span> </span><span>id</span><span>=</span><span>"list"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>&lt;/</span><span>ul</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>        </span><span>var</span><span><span> </span><span>list</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"list"</span><span>);</span></div></div><div><div><div>6</div></div><div><span>        </span><span>//创建20个li元素</span></div></div><div><div><div>7</div></div><div><span>        </span><span>for</span><span>(</span><span>var</span><span><span> </span><span>i</span></span><span>=</span><span>0</span><span><span>;</span><span>i</span></span><span>&lt;</span><span>20</span><span><span>;</span><span>i</span></span><span>++</span><span>){</span></div></div><div><div><div>8</div></div><div><span>            </span><span>var</span><span><span> </span><span>li</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>createElement</span><span>(</span><span>"li"</span><span>);</span></div></div><div><div><div>9</div></div><div><span><span>            </span></span><span>li</span><span>.</span><span>style</span><span>.</span><span>cursor</span><span> </span><span>=</span><span> </span><span>"pointer"</span><span>;</span><span>//小手指针</span></div></div><div><div><div>10</div></div><div><span><span>            </span></span><span>li</span><span>.</span><span>innerHTML</span><span> </span><span>=</span><span> </span><span>"列表项"</span><span>+</span><span><span>i</span><span>;</span></span></div></div><div><div><div>11</div></div><div><span><span>            </span></span><span>list</span><span>.</span><span>appendChild</span><span><span>(</span><span>li</span><span>);</span></span></div></div><div><div><div>12</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span>       </span><span>var</span><span><span> </span><span>lis</span><span> </span></span><span>=</span><span><span> </span><span>list</span><span>.</span></span><span>getElementsByTagName</span><span>(</span><span>"li"</span><span>);</span></div></div><div><div><div>14</div></div><div><span>       </span><span>// 给每个li添加点击事件监听</span></div></div><div><div><div>15</div></div><div><span>       </span><span>//再次点击列表项，背景颜色变回白色</span></div></div><div><div><div>16</div></div><div><span>       </span><span>for</span><span>(</span><span>var</span><span><span> </span><span>i</span></span><span>=</span><span>0</span><span><span>;</span><span>i</span></span><span>&lt;</span><span><span>lis</span><span>.</span></span><span>length</span><span><span>;</span><span>i</span></span><span>++</span><span>){</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>lis</span><span>[</span><span>i</span><span>].</span><span>onclick</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>            </span><span>if</span><span>(</span><span>this</span><span>.</span><span>style</span><span>.</span><span>backgroundColor</span><span> </span><span>==</span><span> </span><span>"red"</span><span>){</span></div></div><div><div><div>20</div></div><div><span>                </span><span>this</span><span>.</span><span>style</span><span>.</span><span>backgroundColor</span><span> </span><span>=</span><span> </span><span>"white"</span><span>;</span></div></div><div><div><div>21</div></div><div><span><span>            </span></span><span>}</span><span>else</span><span>{</span></div></div><div><div><div>22</div></div><div><span>                </span><span>this</span><span>.</span><span>style</span><span>.</span><span>backgroundColor</span><span> </span><span>=</span><span> </span><span>"red"</span><span>;</span></div></div><div><div><div>23</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>24</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>25</div></div><div><span><span>       </span></span><span>}</span></div></div><div><div><div>26</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>27</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
</li>
</ul><p><strong>批量添加事件监听的性能问题</strong></p><ul>
<li>每一个事件监听注册都会消耗一定的系统内存，而批量添 加事件会导致监听数量太多，内存消耗会非常大</li>
<li>实际上，每个li的事件处理函数都是不同的函数，这些 函数本身也会占用内存</li>
</ul><p><strong>新增元素动态绑定事件</strong></p><ul>
<li>
<p>题目：页面上有一个无序列表ul，它内部没有li元素， 请制作一个按钮，点击这个按钮就能增加一个li元素。并 且要求每个增加的li元素也要有点击事件监听，实现效果 点击哪个li元素，哪个li元素就变红</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>&lt;</span><span>button</span><span>&gt;点击添加li项&lt;/</span><span>button</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>&lt;</span><span>ul</span><span> </span><span>id</span><span>=</span><span>"list"</span><span>&gt;&lt;/</span><span>ul</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>        </span><span>var</span><span><span> </span><span>btn</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelector</span><span>(</span><span>"button"</span><span>);</span></div></div><div><div><div>6</div></div><div><span>        </span><span>var</span><span><span> </span><span>list</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"list"</span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>        </span></span><span>btn</span><span>.</span><span>onclick</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>8</div></div><div><span>            </span><span>var</span><span><span> </span><span>li</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>createElement</span><span>(</span><span>"li"</span><span>);</span></div></div><div><div><div>9</div></div><div><span><span>            </span></span><span>li</span><span>.</span><span>innerHTML</span><span> </span><span>=</span><span> </span><span>"列表项"</span><span>+</span><span><span>list</span><span>.</span></span><span>children</span><span>.</span><span>length</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>            </span></span><span>list</span><span>.</span><span>appendChild</span><span><span>(</span><span>li</span><span>);</span></span></div></div><div><div><div>11</div></div><div><span>            </span><span>// 给li添加点击事件监听 性能问题</span></div></div><div><div><div>12</div></div><div><span><span>            </span></span><span>li</span><span>.</span><span>onclick</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>13</div></div><div><span>                </span><span>this</span><span>.</span><span>style</span><span>.</span><span>backgroundColor</span><span> </span><span>=</span><span> </span><span>"red"</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>17</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
</li>
</ul><p><strong>动态绑定事件的问题</strong></p><ul>
<li>新增元素必须分别添加事件监听，不能自动获得事件监听</li>
<li>大量事件监听、大量事件处理函数都会产生大量消耗内存</li>
</ul><p><strong>什么是事件委托</strong></p><ul>
<li>利用事件冒泡机制，将后代元素事件委托给祖先元素</li>
</ul><p><strong>e.target和e.currentTarget属性</strong></p><p>事件委托通常需要结合使用e.target属性</p>

<table><thead><tr><th>属性</th><th>属性描述</th></tr></thead><tbody><tr><td><code>target</code></td><td>实际触发事件的元素，即事件源元素</td></tr><tr><td><code>currentTarget</code></td><td>当前正在执行事件处理程序的元素，即绑定该事件处理程序的元素</td></tr></tbody></table><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>&lt;</span><span>button</span><span>&gt;点击添加li项&lt;/</span><span>button</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>&lt;</span><span>ul</span><span> </span><span>id</span><span>=</span><span>"list"</span><span>&gt;&lt;/</span><span>ul</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>        </span><span>var</span><span><span> </span><span>btn</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelector</span><span>(</span><span>"button"</span><span>);</span></div></div><div><div><div>6</div></div><div><span>        </span><span>var</span><span><span> </span><span>list</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"list"</span><span>);</span></div></div><div><div><div>7</div></div><div><span>        </span><span>// 点击按钮,添加li项</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>btn</span><span>.</span><span>onclick</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>9</div></div><div><span>            </span><span>var</span><span><span> </span><span>li</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>createElement</span><span>(</span><span>"li"</span><span>);</span></div></div><div><div><div>10</div></div><div><span><span>            </span></span><span>li</span><span>.</span><span>innerHTML</span><span> </span><span>=</span><span> </span><span>"列表项"</span><span>+</span><span><span>list</span><span>.</span></span><span>children</span><span>.</span><span>length</span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>            </span></span><span>list</span><span>.</span><span>appendChild</span><span><span>(</span><span>li</span><span>);</span></span></div></div><div><div><div>12</div></div><div><span>            </span><span>// 给li添加点击事件监听 性能问题</span></div></div><div><div><div>13</div></div><div><span>            </span><span>// li.onclick = function () {</span></div></div><div><div><div>14</div></div><div><span>            </span><span>//     this.style.backgroundColor = "red";</span></div></div><div><div><div>15</div></div><div><span>            </span><span>// }</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>18</div></div><div><span>        </span><span>// 事件委托,给ul添加点击事件监听,点击li项,背景颜色变红</span></div></div><div><div><div>19</div></div><div><span><span>        </span></span><span>list</span><span>.</span><span>onclick</span><span> </span><span>=</span><span> </span><span>function</span><span><span> (</span><span>e</span><span>) {</span></span></div></div><div><div><div>20</div></div><div><span>            </span><span>////只有点击了li项,才变红</span></div></div><div><div><div>21</div></div><div><span>        </span><span>if</span><span><span>(</span><span>e</span><span>.</span></span><span>target</span><span>.</span><span>tagName</span><span> </span><span>===</span><span> </span><span>"LI"</span><span>){</span></div></div><div><div><div>22</div></div><div><span><span>            </span></span><span>e</span><span>.</span><span>target</span><span>.</span><span>style</span><span>.</span><span>backgroundColor</span><span> </span><span>=</span><span> </span><span>"red"</span><span>;</span></div></div><div><div><div>23</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>24</div></div><div><span><span>    </span></span><span>};</span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>26</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>事件委托的使用场景</strong></p><ul>
<li>当有大量类似元素需要批量添加事件监听时，使用事件委 托可以减少内存开销</li>
<li>当有动态元素节点上树时，使用事件委托可以让新上树的 元素具有事件监听</li>
</ul><p><strong>使用事件委托时需要注意的事项</strong></p><ul>
<li>
<p>onmouseenter和onmouseover都表示“鼠标进入”，它 们有什么区别呢？</p>
<p>onmouseenter不冒泡，onmouseover冒泡。</p>
</li>
<li>
<p>使用事件委托时要注意：不能委托不冒泡的事件给祖先元素</p>
</li>
<li>
<p>最内层元素不能再有额外的内层元素了，比如：</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>ul</span><span> </span><span>id</span><span>=</span><span>"list"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>li</span><span>&gt;&lt;</span><span>span</span><span>&gt;我是span&lt;/</span><span>span</span><span>&gt;列表项&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;</span><span>li</span><span>&gt;&lt;</span><span>span</span><span>&gt;我是span&lt;/</span><span>span</span><span>&gt;列表项&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>&lt;</span><span>li</span><span>&gt;&lt;</span><span>span</span><span>&gt;我是span&lt;/</span><span>span</span><span>&gt;列表项&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>&lt;/</span><span>ul</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102002javascript-de-dom-zhi-jie-dian/</id>
      <title type="text">JavaScript的DOM之节点</title>
      <published>2026-10-20T01:46:10.000Z</published>
      <updated>2026-10-20T01:46:10.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102002javascript-de-dom-zhi-jie-dian/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>关于JavaScript的DOM，其实vue和react这类框架已经帮我们解决了，学习本章的意义也是了解其原理，在一般开发中，很少直接操作dom，也不建议直接操作dmo</p>
<section><h1>DOM基本概念<a href="#dom基本概念"><span>#</span></a></h1><ul>
<li>DOM是JS操控HTML和CSS的桥梁</li>
<li>DOM使JS操作HTML变得优雅</li>
</ul><p><strong>DOM简介</strong></p><ul>
<li>DOM（Document Object Model，文档对象模型）是 JavaScript操作HTML文档的接口，使文档操作变得非常优 雅、简便</li>
<li>DOM最大的特点就是将文档表示为节点树</li>
</ul><p><strong>DOM节点树</strong></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!</span><span>DOCTYPE</span><span> </span><span>html</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>html</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>&lt;</span><span>head</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>        </span></span><span>&lt;</span><span>meta</span><span> </span><span>charset</span><span>=</span><span>"UTF-8"</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>&lt;</span><span>title</span><span>&gt;Document&lt;/</span><span>title</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>&lt;</span><span>h1</span><span>&gt;慕课网&lt;/</span><span>h1</span><span>&gt;</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>&lt;</span><span>div</span><span>&gt;</span></div></div><div><div><div>10</div></div><div><span><span>            </span></span><span>&lt;</span><span>h2</span><span>&gt;程序员的梦工厂&lt;/</span><span>h2</span><span>&gt;</span></div></div><div><div><div>11</div></div><div><span><span>            </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"logo.png"</span><span>&gt;</span></div></div><div><div><div>12</div></div><div><span><span>            </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box"</span><span>&gt;</span></div></div><div><div><div>13</div></div><div><span><span>                </span></span><span>慕课专栏</span></div></div><div><div><div>14</div></div><div><span><span>            </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>15</div></div><div><span><span>        </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>&lt;/</span><span>body</span><span>&gt;</span></div></div><div><div><div>17</div></div><div><span>&lt;/</span><span>html</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h1>NodeType<a href="#nodetype"><span>#</span></a></h1><p>节点的nodeType属性可以显示这个节点具体的类型</p>

<table><thead><tr><th><code>nodeType</code> 值</th><th>节点类型</th></tr></thead><tbody><tr><td><code>1</code></td><td>元素节点，例如 <code>p</code> 和 <code>div</code></td></tr><tr><td><code>3</code></td><td>文本节点</td></tr><tr><td><code>8</code></td><td>注释节点</td></tr><tr><td><code>9</code></td><td>Document 文档节点</td></tr><tr><td><code>10</code></td><td>DocumentType 文档类型节点（DTD）</td></tr></tbody></table><p><strong>访问元素节点</strong></p><ul>
<li>所谓“访问”元素节点，就是指“得到”、“获取”页面上 的元素节点</li>
<li>对节点进行操作，第一步就是要得到它</li>
<li>访问元素节点主要依靠document对象</li>
</ul></section>
<section><h1>Document<a href="#document"><span>#</span></a></h1><ul>
<li>
<p>document对象是DOM中最重要的东西，几乎所有DOM的 功能都封装在了document对象中</p>
</li>
<li>
<p>document对象也表示整个HTML文档，它是DOM节点树 的根</p>
</li>
<li>
<p>document对象的nodeType属性值是9</p>
</li>
<li>
<p>访问元素节点的常用方法</p>

<table><thead><tr><th>方法</th><th>功能</th><th>兼容性</th></tr></thead><tbody><tr><td><code>document.getElementById()</code></td><td>通过 ID 获取元素</td><td>IE6+</td></tr><tr><td><code>document.getElementsByTagName()</code></td><td>通过标签名获取元素集合</td><td>IE6+</td></tr><tr><td><code>document.getElementsByClassName()</code></td><td>通过类名获取元素集合</td><td>IE9+</td></tr><tr><td><code>document.querySelector()</code></td><td>通过 CSS 选择器获取第一个匹配的元素</td><td>IE8 部分兼容，IE9+ 完全兼容</td></tr><tr><td><code>document.querySelectorAll()</code></td><td>通过 CSS 选择器获取所有匹配的元素集合</td><td>IE8 部分兼容，IE9+ 完全兼容</td></tr></tbody></table>
</li>
</ul></section>
<section><h1>获取节点<a href="#获取节点"><span>#</span></a></h1><section><h2>getElementById()<a href="#getelementbyid"><span>#</span></a></h2><p>document.getElementById()功能是通过id得到元素节点</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>id</span><span>=</span><span>"box"</span><span>&gt;我是一个盒子&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>p</span><span> </span><span>id</span><span>=</span><span>"para"</span><span>&gt;我是一个段落&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>var</span><span><span> </span><span>box</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>'box'</span><span>);</span></div></div><div><div><div>5</div></div><div><span>var</span><span><span> </span><span>para</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>'para'</span><span>);</span></div></div><div><div><div>6</div></div><div><span>&lt;/</span><span>script</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>注意事项</strong></p><ul>
<li>如果页面上有相同id的元素，则只能得到第一个</li>
<li>不管元素藏的位置有多深，都能通过id把它找到</li>
</ul></section><section><h2>getElementsByTagName()<a href="#getelementsbytagname"><span>#</span></a></h2><p>getElementsByTagName()方法的功能是通过标签名得到 节点数组</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>p</span><span>&gt;我是段落&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>p</span><span>&gt;我是段落&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;</span><span>p</span><span>&gt;我是段落&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>&lt;</span><span>p</span><span>&gt;我是段落&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span>var</span><span><span> </span><span>ps</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementsByTagName</span><span>(</span><span>'p'</span><span>);</span><span>//数组</span></div></div><div><div><div>7</div></div><div><span>&lt;/</span><span>script</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>注意事项</strong></p><ul>
<li>数组方便遍历，从而可以批量操控元素节点</li>
<li>即使页面上只有一个指定标签名的节点，也将得到长度为1 的数组</li>
<li>任何一个节点元素也可以调用getElementsByTagName() 方法，从而得到其内部的某种类的元素节点</li>
</ul></section><section><h2>getElementsByClassName()<a href="#getelementsbyclassname"><span>#</span></a></h2><p>getElementsByClassName()方法的功能是通过类名得到节点数组</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"spec"</span><span>&gt;我是盒子&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>div</span><span>&gt;我是盒子&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"spec"</span><span>&gt;我是盒子&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"spec"</span><span>&gt;我是盒子&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span>var</span><span><span> </span><span>spec_divs</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementsByClassName</span><span>(</span><span>'spec'</span><span>);</span></div></div><div><div><div>7</div></div><div><span>&lt;/</span><span>script</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>注意事项</strong></p><ul>
<li>getElementsByClassName()方法从IE9开始兼容</li>
<li>某个节点元素也可以调用getElementsByClassName()方法 ，从而得到其内部的某类名的元素节点</li>
</ul></section><section><h2>querySelector()<a href="#queryselector"><span>#</span></a></h2><p>querySelector()方法的功能是通过选择器得到元素</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>id</span><span>=</span><span>"box1"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>p</span><span>&gt;我是段落&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"spec"</span><span>&gt;我是段落&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>&lt;</span><span>p</span><span>&gt;我是段落&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span>var</span><span><span> </span><span>the_p</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelector</span><span>(</span><span>'#box1 .spec'</span><span>);</span></div></div><div><div><div>8</div></div><div><span>&lt;/</span><span>script</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>注意事项</strong></p><ul>
<li>querySelector()方法只能得到页面上一个元素，如果有多 个元素符合条件，则只能得到第一个元素</li>
<li>querySelector()方法从IE8开始兼容，但从IE9开始支持 CSS3的选择器，如()、:[src^= ‘dog’]等CSS3选 择器形式都支持良好</li>
</ul></section><section><h2>querySelectorAll()<a href="#queryselectorall"><span>#</span></a></h2><ul>
<li>querySelectorAll()方法的功能是通过选择器得到元素数组</li>
<li>即使页面上只有一个符合选择器的节点，也将得到长度为1 的数组</li>
</ul></section></section>
<section><h1>节点的关系<a href="#节点的关系"><span>#</span></a></h1>

<table><thead><tr><th>关系</th><th>考虑所有节点</th></tr></thead><tbody><tr><td>子节点</td><td>childNodes</td></tr><tr><td>父节点</td><td>parentNode</td></tr><tr><td>第一个子节点</td><td>firstChild</td></tr><tr><td>最后一个子节点</td><td>lastChild</td></tr><tr><td>前一个兄弟节点</td><td>previousSibling</td></tr><tr><td>后一个兄弟节点</td><td>nextSibling</td></tr></tbody></table><p><strong>注意：文本节点也属于节点</strong></p><ul>
<li>DOM中，文本节点也属于节点，在使用节点的关系时一定 要注意</li>
<li>在标准的W3C规范中，空白文本节点也应该算作节点，但 是在IE8及以前的浏览器中会有一定的兼容问题，它们不把 空文本节点当做节点</li>
</ul><p><strong>排除文本节点的干扰</strong></p><ul>
<li>
<p>从IE9开始支持一些“只考虑元素节点”的属性</p>

<table><thead><tr><th>关系</th><th>考虑所有节点</th><th>只考虑元素节点</th></tr></thead><tbody><tr><td>子节点</td><td><code>childNodes</code></td><td><code>children</code></td></tr><tr><td>父节点</td><td><code>parentNode</code></td><td><code>parentElement</code></td></tr><tr><td>第一个子节点</td><td><code>firstChild</code></td><td><code>firstElementChild</code></td></tr><tr><td>最后一个子节点</td><td><code>lastChild</code></td><td><code>lastElementChild</code></td></tr><tr><td>前一个兄弟节点</td><td><code>previousSibling</code></td><td><code>previousElementSibling</code></td></tr><tr><td>后一个兄弟节点</td><td><code>nextSibling</code></td><td><code>nextElementSibling</code></td></tr></tbody></table>
</li>
</ul></section>
<section><h1>封装节点关系函数<a href="#封装节点关系函数"><span>#</span></a></h1><p><strong>书写常见的节点关系函数</strong></p><ul>
<li>
<p>书写IE6也能兼容的“寻找所有元素子节点”函数</p>
</li>
<li>
<p>书写IE6也能兼容的“寻找前一个元素兄弟节点”函数</p>
</li>
<li>
<p>如何编写函数，获得某元素的所有的兄弟节点？</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>id</span><span>=</span><span>"box"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>        </span></span><span>&lt;</span><span>p</span><span>&gt;我是段落A&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>        </span></span><span>&lt;</span><span>p</span><span> </span><span>id</span><span>=</span><span>"para"</span><span>&gt;我是段落B&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>         </span></span><span>&lt;</span><span>p</span><span>&gt;我是段落C&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span>        </span><span>var</span><span><span> </span><span>box</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"box"</span><span>);</span></div></div><div><div><div>9</div></div><div><span>        </span><span>var</span><span><span> </span><span>para</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"para"</span><span>);</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>        </span><span>function</span><span> </span><span>getChildren</span><span><span>(</span><span>node</span><span>) {</span></span></div></div><div><div><div>12</div></div><div><span>            </span><span>var</span><span><span> </span><span>children</span><span> </span></span><span>=</span><span> [];</span><span>//结果数组</span></div></div><div><div><div>13</div></div><div><span>            </span><span>//遍历node的所有子元素</span></div></div><div><div><div>14</div></div><div><span>            </span><span>for</span><span> (</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>node</span><span>.</span></span><span>childNodes</span><span>.</span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>15</div></div><div><span>                </span><span>//判断是否是元素节点</span></div></div><div><div><div>16</div></div><div><span>                </span><span>if</span><span><span> (</span><span>node</span><span>.</span></span><span>childNodes</span><span><span>[</span><span>i</span><span>].</span></span><span>nodeType</span><span> </span><span>===</span><span> </span><span>1</span><span>) {</span></div></div><div><div><div>17</div></div><div><span><span>                    </span></span><span>children</span><span>.</span><span>push</span><span><span>(</span><span>node</span><span>.</span></span><span>childNodes</span><span><span>[</span><span>i</span><span>]);</span></span></div></div><div><div><div>18</div></div><div><span><span>                </span></span><span>}</span></div></div><div><div><div>19</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>20</div></div><div><span>            </span><span>return</span><span><span> </span><span>children</span><span>;</span></span></div></div><div><div><div>21</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>22</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>getChildren</span><span><span>(</span><span>box</span><span>));</span></span></div></div><div><div><div>23</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>getChildren</span><span><span>(</span><span>para</span><span>));</span></span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span>        </span><span>function</span><span> </span><span>getElementPrevSibling</span><span><span>(</span><span>node</span><span>) {</span></span></div></div><div><div><div>26</div></div><div><span>        </span><span>var</span><span><span> </span><span>o</span><span> </span></span><span>=</span><span><span> </span><span>node</span><span>;</span></span></div></div><div><div><div>27</div></div><div><span>           </span><span>while</span><span><span>(</span><span>o</span><span>.</span></span><span>previousSibling</span><span> </span><span>!=</span><span> </span><span>null</span><span>){</span></div></div><div><div><div>28</div></div><div><span>            </span><span>if</span><span><span>(</span><span>o</span><span>.</span></span><span>previousSibling</span><span>.</span><span>nodeType</span><span> </span><span>===</span><span> </span><span>1</span><span>){</span></div></div><div><div><div>29</div></div><div><span>               </span><span>return</span><span><span> </span><span>o</span><span>.</span></span><span>previousSibling</span><span>;</span></div></div><div><div><div>30</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>31</div></div><div><span><span>            </span></span><span>o</span><span> </span><span>=</span><span><span> </span><span>o</span><span>.</span></span><span>previousSibling</span><span>;</span></div></div><div><div><div>32</div></div><div><span><span>           </span></span><span>}</span></div></div><div><div><div>33</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>34</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>getElementPrevSibling</span><span><span>(</span><span>para</span><span>));</span></span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span>        </span><span>function</span><span> </span><span>getAllElementSibling</span><span><span>(</span><span>node</span><span>) {</span></span></div></div><div><div><div>37</div></div><div><span>            </span><span>var</span><span><span> </span><span>prevs</span><span> </span></span><span>=</span><span> [];</span></div></div><div><div><div>38</div></div><div><span>            </span><span>var</span><span><span> </span><span>nexts</span><span> </span></span><span>=</span><span> [];</span></div></div><div><div><div>39</div></div><div><span>            </span><span>var</span><span><span> </span><span>o</span><span> </span></span><span>=</span><span><span> </span><span>node</span><span>;</span></span></div></div><div><div><div>40</div></div><div><span>            </span><span>while</span><span><span> (</span><span>o</span><span>.</span></span><span>previousSibling</span><span> </span><span>!=</span><span> </span><span>null</span><span>) {</span></div></div><div><div><div>41</div></div><div><span>                </span><span>if</span><span><span> (</span><span>o</span><span>.</span></span><span>previousSibling</span><span>.</span><span>nodeType</span><span> </span><span>===</span><span> </span><span>1</span><span>) {</span></div></div><div><div><div>42</div></div><div><span><span>                    </span></span><span>prevs</span><span>.</span><span>unshift</span><span><span>(</span><span>o</span><span>.</span></span><span>previousSibling</span><span>);</span></div></div><div><div><div>43</div></div><div><span><span>                </span></span><span>}</span></div></div><div><div><div>44</div></div><div><span><span>                </span></span><span>o</span><span> </span><span>=</span><span><span> </span><span>o</span><span>.</span></span><span>previousSibling</span><span>;</span></div></div><div><div><div>45</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>46</div></div><div><span><span>             </span></span><span>o</span><span> </span><span>=</span><span><span> </span><span>node</span><span>;</span></span></div></div><div><div><div>47</div></div><div><span>            </span><span>while</span><span><span> (</span><span>o</span><span>.</span></span><span>nextElementSibling</span><span> </span><span>!=</span><span> </span><span>null</span><span>) {</span></div></div><div><div><div>48</div></div><div><span>                </span><span>if</span><span><span> (</span><span>o</span><span>.</span></span><span>nextElementSibling</span><span>.</span><span>nodeType</span><span> </span><span>===</span><span> </span><span>1</span><span>) {</span></div></div><div><div><div>49</div></div><div><span><span>                    </span></span><span>nexts</span><span>.</span><span>push</span><span><span>(</span><span>o</span><span>.</span></span><span>nextElementSibling</span><span>);</span></div></div><div><div><div>50</div></div><div><span><span>                </span></span><span>}</span></div></div><div><div><div>51</div></div><div><span><span>                </span></span><span>o</span><span> </span><span>=</span><span><span> </span><span>o</span><span>.</span></span><span>nextElementSibling</span><span>;</span></div></div><div><div><div>52</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>53</div></div><div><span>            </span><span>return</span><span><span> </span><span>prevs</span><span>.</span></span><span>concat</span><span><span>(</span><span>nexts</span><span>);</span></span></div></div><div><div><div>54</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>55</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>getAllElementSibling</span><span><span>(</span><span>para</span><span>));</span></span></div></div><div><div><div>56</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>57</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
</li>
</ul><p>哪些情况需要封装？</p>

<table><thead><tr><th>场景</th><th>是否需要封装</th></tr></thead><tbody><tr><td>获取父元素</td><td>不需要</td></tr><tr><td>获取子元素</td><td>不需要</td></tr><tr><td>获取兄弟元素</td><td>不需要</td></tr><tr><td>获取第一个或最后一个子元素</td><td>不需要</td></tr><tr><td>查找符合条件的祖先元素</td><td>不需要</td></tr><tr><td>实现复杂的节点查找逻辑</td><td>可以封装</td></tr><tr><td>多处重复相同的 DOM 操作</td><td>可以封装</td></tr><tr><td>兼容 IE 等旧浏览器</td><td>视需求而定</td></tr></tbody></table></section>
<section><h1>节点操作<a href="#节点操作"><span>#</span></a></h1><p><strong>如何改变元素节点的CSS样式</strong></p><ul>
<li>
<p>改变元素节点的CSS样式需要使用这样的语句</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>oBox</span><span>.</span></span><span>style</span><span>.</span><span>backgroundColor</span><span> </span><span>=</span><span>'red'</span><span>;</span><span>//CSS属性要写成“驼峰”形式</span></div></div><div><div><div>2</div></div><div><span><span>oBox</span><span>.</span></span><span>style</span><span>.</span><span>backgroundImage</span><span> </span><span>=</span><span>'url(images/1.jpg)'</span><span>;</span><span>//CSS属性值要设置成完整形式</span></div></div><div><div><div>3</div></div><div><span><span>oBox</span><span>.</span></span><span>style</span><span>.</span><span>fontSize</span><span> </span><span>=</span><span>'32px'</span><span>;</span><span>//注意写单位</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>如何改变元素节点的HTML属性</strong></p><ul>
<li>
<p>标准W3C属性，如src、href等等，只需要直接打点进行更改即可</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>oImg</span><span>.</span></span><span>src</span><span> </span><span>=</span><span> </span><span>'images/2.jpg'</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>不符合W3C标准的属性，要使用setAttribute()和getAttribute() 来设置、读取</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>oBox</span><span>.</span></span><span>setAttribute</span><span>(</span><span>'data-n'</span><span>, </span><span>10</span><span>);</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>n</span><span> </span></span><span>=</span><span><span> </span><span>oBox</span><span>.</span></span><span>getAttribute</span><span>(</span><span>'data-n'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>alert</span><span><span>(</span><span>n</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><section><h2>innerHTML&amp;innerText<a href="#innerhtmlinnertext"><span>#</span></a></h2><p><strong>如何改变元素节点中的内容</strong></p><ul>
<li>改变元素节点中的内容可以使用两个相关属性：①innerHTML ② innerText</li>
<li>innerHTML属性能以HTML语法设置节点中的内容</li>
<li>innerText属性只能以纯文本的形式设置节点中的内容</li>
</ul></section><section><h2>节点的创建、移除和克隆<a href="#节点的创建移除和克隆"><span>#</span></a></h2><p><strong>节点的创建</strong></p><ul>
<li>
<p>document.createElement() 方法用于创建一个指定tag name的HTML元素</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>oDiv</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>createElement</span><span>(</span><span>'div'</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>孤儿节点</strong></p><ul>
<li>新创建出的节点是“孤儿节点”，这意味着它并没有被挂载 到DOM树上，我们无法看见它</li>
<li>必须继续使用appendChild()或insertBefore()方法将孤儿 节点插入到DOM树上</li>
</ul><p><strong>appendChild()</strong></p><ul>
<li>
<p>追加节点</p>
</li>
<li>
<p>任何已经在DOM树上的节点，都可以调用appendChild() 方法，它可以将孤儿节点挂载到它的内部，成为它的最后一 个子节点</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>父节点</span><span>.</span></span><span>appendChild</span><span><span>(</span><span>孤儿节点</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>insertBefore()</strong></p><ul>
<li>
<p>任何已经在DOM树上的节点，都可以调用insertBefore() 方法，它可以将孤儿节点挂载到它的内部，成为它的“标杆 子节点”之前的节点</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>父节点</span><span>.</span></span><span>insertBefore</span><span><span>(</span><span>孤儿节点</span><span>, </span><span>标杆节点</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>示例：</strong></p><p>请动态创建出一个20行12列的表格</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>createTable</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>var</span><span><span> </span><span>table</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>createElement</span><span>(</span><span>"table"</span><span>);</span></div></div><div><div><div>3</div></div><div><span>    </span><span>for</span><span> (</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span> </span><span>20</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>4</div></div><div><span>        </span><span>var</span><span><span> </span><span>row</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>createElement</span><span>(</span><span>"tr"</span><span>);</span></div></div><div><div><div>5</div></div><div><span>        </span><span>for</span><span> (</span><span>var</span><span><span> </span><span>j</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>j</span><span> </span></span><span>&lt;</span><span> </span><span>12</span><span><span>; </span><span>j</span></span><span>++</span><span>) {</span></div></div><div><div><div>6</div></div><div><span>            </span><span>var</span><span><span> </span><span>cell</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>createElement</span><span>(</span><span>"td"</span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>            </span></span><span>cell</span><span>.</span><span>innerHTML</span><span> </span><span>=</span><span><span> </span><span>i</span><span> </span></span><span>+</span><span> </span><span>"-"</span><span> </span><span>+</span><span><span> </span><span>j</span><span>;</span></span></div></div><div><div><div>8</div></div><div><span><span>            </span></span><span>row</span><span>.</span><span>appendChild</span><span><span>(</span><span>cell</span><span>);</span></span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>table</span><span>.</span><span>appendChild</span><span><span>(</span><span>row</span><span>);</span></span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>document</span><span>.</span><span>body</span><span>.</span><span>appendChild</span><span><span>(</span><span>table</span><span>);</span></span></div></div><div><div><div>13</div></div><div><span>}</span></div></div><div><div><div>14</div></div><div><span>createTable</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>请制作九九乘法表（可以在刚才代码基础上改动升级）</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//制作九九乘法表</span></div></div><div><div><div>2</div></div><div><span>function</span><span> </span><span>createTable1</span><span>() {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>var</span><span><span> </span><span>table</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>createElement</span><span>(</span><span>"table"</span><span>);</span></div></div><div><div><div>4</div></div><div><span>    </span><span>for</span><span> (</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>1</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;=</span><span> </span><span>9</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>5</div></div><div><span>        </span><span>var</span><span><span> </span><span>row</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>createElement</span><span>(</span><span>"tr"</span><span>);</span></div></div><div><div><div>6</div></div><div><span>        </span><span>for</span><span> (</span><span>var</span><span><span> </span><span>j</span><span> </span></span><span>=</span><span> </span><span>1</span><span><span>; </span><span>j</span><span> </span></span><span>&lt;=</span><span><span> </span><span>i</span><span>; </span><span>j</span></span><span>++</span><span>) {</span></div></div><div><div><div>7</div></div><div><span>            </span><span>var</span><span><span> </span><span>cell</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>createElement</span><span>(</span><span>"td"</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>            </span></span><span>cell</span><span>.</span><span>innerHTML</span><span> </span><span>=</span><span><span> </span><span>i</span><span> </span></span><span>+</span><span> </span><span>"x"</span><span> </span><span>+</span><span><span> </span><span>j</span><span> </span></span><span>+</span><span> </span><span>"="</span><span> </span><span>+</span><span><span> </span><span>i</span><span> </span></span><span>*</span><span><span> </span><span>j</span><span>;</span></span></div></div><div><div><div>9</div></div><div><span><span>            </span></span><span>row</span><span>.</span><span>appendChild</span><span><span>(</span><span>cell</span><span>);</span></span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span><span>        </span></span><span>table</span><span>.</span><span>appendChild</span><span><span>(</span><span>row</span><span>);</span></span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>document</span><span>.</span><span>body</span><span>.</span><span>appendChild</span><span><span>(</span><span>table</span><span>);</span></span></div></div><div><div><div>14</div></div><div><span>}</span></div></div><div><div><div>15</div></div><div><span>createTable1</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><strong>移动节点</strong></p><ul>
<li>
<p>如果将已经挂载到DOM树上的节点成为appendChild()或者 insertBefore()的参数，这个节点将会被移动</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>新父节点</span><span>.</span></span><span>appendChild</span><span><span>(</span><span>已经有父亲的节点</span><span>);</span></span></div></div><div><div><div>2</div></div><div><span><span>新父节点</span><span>.</span></span><span>insertBefore</span><span><span>(</span><span>已经有父亲的节点</span><span>, </span><span>标杆子节点</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>这意味着一个节点不能同时位于DOM树的两个位置</p>
</li>
</ul><p><strong>删除节点</strong></p><ul>
<li>
<p>removeChild() 方法从DOM中删除一个子节点</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>父节点</span><span>.</span></span><span>removeChild</span><span><span>(</span><span>要删除子节点</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>节点不能主动删除自己，必须由父节点删除它</p>
</li>
</ul><p><strong>克隆节点</strong></p><ul>
<li>
<p>cloneNode() 方法可以克隆节点，克隆出的节点是“孤儿节 点</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>孤儿节点</span><span> </span></span><span>=</span><span><span> </span><span>老节点</span><span>.</span></span><span>cloneNode</span><span>();</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>孤儿节点</span><span> </span></span><span>=</span><span><span> </span><span>老节点</span><span>.</span></span><span>cloneNode</span><span>(</span><span>true</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>参数是一个布尔值，表示是否采用深度克隆：如果为true，则 该节点的所有后代节点也都会被克隆，如果为false，则只克 隆该节点本身</p>
</li>
</ul></section></section>
<section><h1>拓展-延迟执行<a href="#拓展-延迟执行"><span>#</span></a></h1><ul>
<li>在测试DOM代码时，通常JS代码一定要写到HTML节点的 后面，否则JS无法找到相应HTML节点</li>
<li>可以使用window.onload = function(){} 事件，使页面加 载完毕后，再执行指定的代码</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026102001javascript-han-shu/</id>
      <title type="text">JavaScript函数</title>
      <published>2026-10-19T23:45:16.000Z</published>
      <updated>2026-10-19T23:45:16.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026102001javascript-han-shu/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>本章主要学习JavaScript的函数相关知识，包括递归和闭包，关于递归，其作用最主要就是实现深克隆，但现在<code>structuredClone()</code>可以实现，虽然有些情况不能使用，但是基本满足大多数情况了，这里学习递归是巩固基础知识，关于闭包，其作用最主要就是实现私有变量，现代开发中也有可以代替，#号关键词，但是其作用是在class，总之，这两个属于基础，有学习的必要，但是深入了解对现代开发意义不是很大</p>
<section><h1>什么是函数<a href="#什么是函数"><span>#</span></a></h1><p>先从一个问题说起：假如我们要分别计算1到10、5到12、14到35的整数和，不用函数的情况下代码是这样的：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>1</span><span><span>, </span><span>sum</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;=</span><span> </span><span>10</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>2</div></div><div><span><span>sum</span><span> </span></span><span>+=</span><span><span> </span><span>i</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>sum</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span>for</span><span> (</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>5</span><span><span>, </span><span>sum</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;=</span><span> </span><span>12</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>6</div></div><div><span><span>sum</span><span> </span></span><span>+=</span><span><span> </span><span>i</span><span>;</span></span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>sum</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这些代码高度重复，只是变量不同，使用函数就可以解决这个问题；函数可以理解为：一个神奇的机器，送入机器两 个数字，它将产生两个数字之 间所有整数的和。</p><p>总结：</p><ul>
<li>函数就是语句的封装，可以让这些代码方便地被复用</li>
<li>函数具有“一次定义，多次调用”的优点</li>
<li>使用函数，可以简化问题，让代码更具有可读性</li>
</ul></section>
<section><h1>函数的定义和调用<a href="#函数的定义和调用"><span>#</span></a></h1><p>这里的函数声明提升，是JavaScript的机制，但是在现代开发中应该避免这种写法，很容易引发bug</p><p><strong>函数的定义</strong></p><p>和变量类似，函数必须先定义然后才能使用，函数定义有两种，分别是使用function关键字定义和函数表达式匿名函数</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//使用function关键字定义函数</span></div></div><div><div><div>2</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>// 函数体语句</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>//函数表达式匿名函数</span></div></div><div><div><div>7</div></div><div><span>var</span><span> </span><span>fun</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>8</div></div><div><span>    </span><span>// 函数体语句</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>函数的调用</strong></p><p>执行函数体中的所有语句，就称为“调用函数”；调用函数非常简单，只需在函数名字后书写圆括号对即可</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>fun</span><span>() </span><span>// 调用函数；圆括号中是实参列表，如果没有实参，也要书写圆括号</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>语句执行顺序</strong></p><ol>
<li>函数不调用，内部语句就不会执行</li>
<li>函数调用后，函数体内所有语句执行完毕， 将语句执行权交还给主程序</li>
</ol><p><strong>函数声明的提升</strong></p><p>和变量声明提升类似，函数声明也可以被提升，这里需要注意，函数内部的变量也会提升，在函数内部提升</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>fun</span><span>();</span></div></div><div><div><div>2</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>alert</span><span>(</span><span>"函数被执行"</span><span>);</span></div></div><div><div><div>4</div></div><div><span>}</span><span>//在预解析阶段会被提升</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>函数表达式不能提升</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>fun(); // 引发错误</span></div></div><div><div><div>2</div></div><div><span>var fun = function () {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>alert("函数被执行");</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这个var fun会被当做一个变量提升，但是提升的是变量，不是提升函数，所以会引发错误</p><p><strong>函数优先提升</strong></p><p>这是一种比较极端的现象，表达式函数和普通函数同时存在 一个相同的函数名，结论是：第一次弹出 <code>B</code>，第二次弹出 <code>A</code>。函数声明先准备好，代码再从上往下执行；函数表达式的赋值要等执行到那一行才生效。 因此，第一次调用得到 <code>B</code>，赋值之后第二次调用得到 <code>A</code>。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//函数优先提升</span></div></div><div><div><div>2</div></div><div><span>//变量声明提升，无法覆盖提升的函数</span></div></div><div><div><div>3</div></div><div><span>fun</span><span>();</span><span>// 弹出B</span></div></div><div><div><div>4</div></div><div><span>var</span><span> </span><span>fun</span><span> </span><span>=</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>5</div></div><div><span>  </span><span>alert</span><span>(</span><span>'A'</span><span>);</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>8</div></div><div><span>  </span><span>alert</span><span>(</span><span>'B'</span><span>);</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div><span>fun</span><span>();</span><span>// 弹出A</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>函数的参数和返回值<a href="#函数的参数和返回值"><span>#</span></a></h1><p><strong>函数的参数</strong></p><p>参数是函数内的一些待定值，在调用函数时，必须传入这些 参数的具体值函数的参数可多可少，函数可以没有参数，也可以有多个参 数，多个参数之间需要用逗号隔开</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//圆括号中定义“形式参数”</span></div></div><div><div><div>2</div></div><div><span>function</span><span> </span><span>add</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>  </span><span>var</span><span><span> </span><span>sum</span><span> </span></span><span>=</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'两个数字的和是'</span><span> </span><span>+</span><span><span> </span><span>sum</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>add</span><span>(</span><span>3</span><span>, </span><span>5</span><span>);</span><span>//调用函数时传入“实际参数”</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>形实结合</strong></p><ul>
<li>在上面例子中，3对应a，5对应b</li>
<li>如果add(3, 5,6);而add(a, b)，此时6没有形参接受他，<strong>会被直接忽略</strong></li>
<li>如果add(3, 5);而add(a, b,c)，此时c没有实参传递他，<strong>c值为undefined</strong></li>
<li>以上两点中，被忽略或者undefined，开发中一般都不是我们想看到的，这也是JS松散语法容易导致bug的原因，在typescript中会得到解决</li>
</ul><p><strong>arguments</strong></p><ul>
<li>
<p>函数内arguments表示它接收到的实参列表，它是一个<strong>类数组对象</strong></p>
</li>
<li>
<p>类数组对象：所有属性均为从0开始的自然数序列，并且有 length属性，和数组类似可以用方括号书写下标访问对象的某个属性值，但是不能调用数组的方法</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//不管用户传递多少参数，都能计算它们和</span></div></div><div><div><div>2</div></div><div><span>function</span><span> </span><span>fun</span><span>(){</span></div></div><div><div><div>3</div></div><div><span>    </span><span>var</span><span><span> </span><span>sum</span><span> </span></span><span>=</span><span> </span><span>0</span></div></div><div><div><div>4</div></div><div><span>    </span><span>for</span><span>(</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>;</span><span>i</span></span><span>&lt;</span><span>arguments</span><span>.</span><span>length</span><span><span>;</span><span>i</span></span><span>++</span><span>){</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>sum</span><span> </span><span>+=</span><span> </span><span>arguments</span><span><span>[</span><span>i</span><span>]</span></span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'所有参数和'</span><span> </span><span>+</span><span><span> </span><span>sum</span><span>);</span></span></div></div><div><div><div>8</div></div><div><span>  </span><span>//console.log(arguments);</span></div></div><div><div><div>9</div></div><div><span>    </span><span>//console.log(arguments[0]);</span></div></div><div><div><div>10</div></div><div><span>   </span><span>// console.log(arguments[1]);</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div><span>fun</span><span>(</span><span>33</span><span>,</span><span>44</span><span>,</span><span>55</span><span>,</span><span>66</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>函数的返回值</strong></p><ul>
<li>
<p>函数体内可以使用return关键字表示“函数的返回值”</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>sum</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span> </span><span>sum</span><span>(</span><span>3</span><span>, </span><span>5</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>调用一个有返回值的函数，可以被当做一个普通值，从而可以出现在任何可以书写值的地方</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>sum</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span><span> </span><span>a</span><span> </span></span><span>+</span><span><span> </span><span>b</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span> </span><span>sum</span><span>(</span><span>3</span><span>, </span><span>sum</span><span>(</span><span>4</span><span>, </span><span>5</span><span>));</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>遇见return即退出函数</strong></p><ul>
<li>
<p>调用函数时，一旦遇见return语句则会立即退出函数，将执行权交还给调用者</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'A'</span><span>);</span></div></div><div><div><div>3</div></div><div><span>    </span><span>return</span><span> </span><span>'B'</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'C'</span><span>);</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>1</span><span>);</span></div></div><div><div><div>7</div></div><div><span>var</span><span><span> </span><span>char</span><span> </span></span><span>=</span><span> </span><span>fun</span><span>();</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>char</span><span>);</span></span></div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>2</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>结合if语句的时候，往往不需要写else分支了</p>
</li>
<li>
<p>比如题目：请编写一个函数，判断一个数字是否是偶数</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>checkEven</span><span><span>(</span><span>n</span><span>){</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>if</span><span><span>(</span><span>n</span><span> </span></span><span>%</span><span> </span><span>2</span><span> </span><span>==</span><span> </span><span>0</span><span>){</span></div></div><div><div><div>3</div></div><div><span>    </span><span>return</span><span> </span><span>true</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>  </span><span>return</span><span> </span><span>false</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span> </span><span>checkEven</span><span>(</span><span>7</span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h1>函数算法题<a href="#函数算法题"><span>#</span></a></h1><p><strong>寻找喇叭花数</strong></p><ul>
<li>
<p>题目：喇叭花数是这样的三位数：其每一位数字的阶乘之和 恰好等于它本身。即abc = a! + b！+ c！，其中abc表示一 个三位数。试寻找所有喇叭花数。</p>
</li>
<li>
<p>思路：将计算某个数字的阶乘封装成函数，这样可以让问题 简化。</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 求阶乘</span></div></div><div><div><div>2</div></div><div><span>//5! = 5 × 4 × 3 × 2 × 1 = 120</span></div></div><div><div><div>3</div></div><div><span>//3! = 3 × 2 × 1 = 6</span></div></div><div><div><div>4</div></div><div><span>//1! = 1</span></div></div><div><div><div>5</div></div><div><span>//0! = 1</span></div></div><div><div><div>6</div></div><div><span>function</span><span> </span><span>factorial</span><span><span>(</span><span>n</span><span>) {</span></span></div></div><div><div><div>7</div></div><div><span>    </span><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>8</div></div><div><span>    </span><span>for</span><span> (</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>1</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;=</span><span><span> </span><span>n</span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>result</span><span> </span><span>*=</span><span><span> </span><span>i</span><span>;</span></span><span>//result=1*1；result=1*2；result=2*3；result=6*4 等于1*2*3*4=24</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>    </span><span>return</span><span><span> </span><span>result</span><span>;</span></span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div><span>// 寻找喇叭花数</span></div></div><div><div><div>14</div></div><div><span>for</span><span> (</span><span>var</span><span><span> </span><span>num</span><span> </span></span><span>=</span><span> </span><span>100</span><span><span>; </span><span>num</span><span> </span></span><span>&lt;=</span><span> </span><span>999</span><span><span>; </span><span>num</span></span><span>++</span><span>) {</span></div></div><div><div><div>15</div></div><div><span>    </span><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>parseInt</span><span><span>(</span><span>num</span><span> </span></span><span>/</span><span> </span><span>100</span><span>, </span><span>10</span><span>);      </span><span>// 百位</span></div></div><div><div><div>16</div></div><div><span>    </span><span>var</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span> </span><span>parseInt</span><span><span>(</span><span>num</span><span> </span></span><span>/</span><span> </span><span>10</span><span>, </span><span>10</span><span>) </span><span>%</span><span> </span><span>10</span><span>;  </span><span>// 十位</span></div></div><div><div><div>17</div></div><div><span>    </span><span>var</span><span><span> </span><span>c</span><span> </span></span><span>=</span><span><span> </span><span>num</span><span> </span></span><span>%</span><span> </span><span>10</span><span>;                     </span><span>// 个位</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>    </span><span>var</span><span><span> </span><span>sum</span><span> </span></span><span>=</span><span> </span><span>factorial</span><span><span>(</span><span>a</span><span>) </span></span><span>+</span><span> </span><span>factorial</span><span><span>(</span><span>b</span><span>) </span></span><span>+</span><span> </span><span>factorial</span><span><span>(</span><span>c</span><span>);</span></span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>    </span><span>if</span><span><span> (</span><span>sum</span><span> </span></span><span>===</span><span><span> </span><span>num</span><span>) {</span></span></div></div><div><div><div>22</div></div><div><span><span>        </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>num</span><span>);</span></span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>24</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
</li>
</ul><p><strong>JavaScript内置sort()方法</strong></p><ul>
<li>
<p>数组排序可以使用sort()方法，这个方法的参数又是一个函 数。</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>33</span><span>, </span><span>22</span><span>, </span><span>55</span><span>, </span><span>11</span><span>];</span></div></div><div><div><div>2</div></div><div><span><span>arr</span><span>.</span></span><span>sort</span><span>(</span><span>function</span><span><span> (</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>这个函数中的a、b分别表示数组中靠前和靠后的项，如果 需要将它们交换位置，则返回任意正数；否则就返回负数。</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>33</span><span>, </span><span>22</span><span>, </span><span>55</span><span>, </span><span>11</span><span>];</span></div></div><div><div><div>2</div></div><div><span>//排序</span></div></div><div><div><div>3</div></div><div><span><span>arr</span><span>.</span></span><span>sort</span><span>(</span><span>function</span><span><span> (</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>4</div></div><div><span>if</span><span><span> (</span><span>a</span><span> </span></span><span>&gt;</span><span><span> </span><span>b</span><span>) {</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>return</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>6</div></div><div><span>} </span><span>else</span><span> {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>return</span><span> </span><span>-</span><span>1</span><span>;</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div><div><div><div>9</div></div><div><span>});</span></div></div><div><div><div>10</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>);</span></span></div></div><div><div><div>11</div></div><div><span>// 方式2</span></div></div><div><div><div>12</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>33</span><span>, </span><span>22</span><span>, </span><span>55</span><span>, </span><span>11</span><span>];</span></div></div><div><div><div>13</div></div><div><span><span>arr</span><span>.</span></span><span>sort</span><span>(</span><span>function</span><span><span> (</span><span>a</span><span>, </span><span>b</span><span>) {</span></span></div></div><div><div><div>14</div></div><div><span>    </span><span>return</span><span><span> </span><span>a</span></span><span>-</span><span><span>b</span><span>;</span></span></div></div><div><div><div>15</div></div><div><span>});</span></div></div><div><div><div>16</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
</li>
</ul></section>
<section><h1>递归<a href="#递归"><span>#</span></a></h1><section><h2>什么是递归<a href="#什么是递归"><span>#</span></a></h2><ul>
<li>函数的内部语句可以调用这个函数自身，从而发起对函数的一次迭 代。在新的迭代中，又会执行调用函数自身的语句，从而又产生一 次迭代。当函数执行到某一次时，不再进行新的迭代，函数被一层 一层返回，函数被递归。</li>
<li>递归是一种较为高级的编程技巧，它把一个大型复杂的问题层层转 化为一个与原问题相似的规模较小的问题来求解。</li>
</ul><p><strong>用求4的阶乘举例</strong></p><p><img src="https://img.youzi177.cn/2026060901.webp" alt="" /></p><ul>
<li>
<p>最开始求4的阶乘，只需知道3的阶乘 <em>4；3的阶乘等于2的阶乘</em> 3；2的阶乘等于1的阶乘 * 2；1的阶乘等于1；</p>
</li>
<li>
<p>1的阶乘等于1；那2的阶乘等于1 * 2就是2；3的阶乘等于3 * 2就是6；4的阶乘等于4 * 6就是24，最终等于24</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>factorial</span><span><span>(</span><span>n</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>    </span><span>// 递归出口</span></div></div><div><div><div>3</div></div><div><span>    </span><span>if</span><span><span> (</span><span>n</span><span> </span></span><span>===</span><span> </span><span>0</span><span>) </span><span>return</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>4</div></div><div><span>    </span><span>// 递归调用</span></div></div><div><div><div>5</div></div><div><span>    </span><span>return</span><span><span> </span><span>n</span><span> </span></span><span>*</span><span> </span><span>factorial</span><span><span>(</span><span>n</span><span> </span></span><span>-</span><span> </span><span>1</span><span>);</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>factorial</span><span>(</span><span>4</span><span>));</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p><strong>递归的要素</strong>：边界条件：确定递归到何时终止，也称为递归出口；递归模式：大问题是如何分解为小问题的，也称为递归体</p>
</li>
</ul></section><section><h2>递归常见算法题<a href="#递归常见算法题"><span>#</span></a></h2><p><strong>斐波那契数列</strong></p><ul>
<li>
<p>斐波那契数列是这样的数列：1、1、2、3、5、8、13、21</p>
</li>
<li>
<p>规律：数列下标为0和1的项的值都是1，从下标为2的项开始，每项等于 前面两项的和</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//编写一个函数，返回斐波那契数列中下标为n的那项的值</span></div></div><div><div><div>2</div></div><div><span>function</span><span> </span><span>fibonacci</span><span><span>(</span><span>n</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>// 递归出口</span></div></div><div><div><div>4</div></div><div><span>    </span><span>if</span><span><span>(</span><span>n</span><span> </span></span><span>==</span><span> </span><span>0</span><span> </span><span>||</span><span><span> </span><span>n</span><span> </span></span><span>==</span><span>1</span><span>) </span><span>return</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>5</div></div><div><span>    </span><span>// 递归调用</span></div></div><div><div><div>6</div></div><div><span>    </span><span>return</span><span> </span><span>fibonacci</span><span><span>(</span><span>n</span><span> </span></span><span>-</span><span> </span><span>1</span><span>) </span><span>+</span><span> </span><span>fibonacci</span><span><span>(</span><span>n</span><span> </span></span><span>-</span><span> </span><span>2</span><span>);</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div><span>// console.log(fibonacci(6));</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>function</span><span> </span><span>fun</span><span><span>(</span><span>n</span><span>){</span></span></div></div><div><div><div>11</div></div><div><span> </span><span>for</span><span>(</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>n</span><span>; </span><span>i</span></span><span>++</span><span>){</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>fibonacci</span><span><span>(</span><span>i</span><span>));</span></span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div><div><div><div>15</div></div><div><span>//计算前15项斐波那契数列</span></div></div><div><div><div>16</div></div><div><span>fun</span><span>(</span><span>15</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
</li>
</ul></section><section><h2>递归实现深克隆<a href="#递归实现深克隆"><span>#</span></a></h2><p><strong>复习引用类型值的相关知识</strong></p>

<table><thead><tr><th>类型</th><th>举例</th><th>当 var a = b 变量传值时</th><th>当用 == 比较时</th></tr></thead><tbody><tr><td>基本类型值</td><td>数字型、字符串型、布尔型、undefined 型</td><td>内存中产生新的副本</td><td>比较值是否相等</td></tr><tr><td>引用类型值</td><td>对象、数组</td><td>内存中不产生新的副本，而是让新变量指向同一个对象</td><td>比较内存地址是否相同，即比较是否是同一个对象</td></tr></tbody></table><p><strong>复习浅克隆</strong></p><ul>
<li>
<p>使用var arr2 = arr1这样的语句不能实现数组的克隆</p>
</li>
<li>
<p>浅克隆：准备一个空的结果数组，然后使用for循环遍历原 数组，将遍历到的项都推入结果数组</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr1</span><span> </span></span><span>=</span><span> [</span><span>33</span><span>,</span><span>44</span><span>,</span><span>55</span><span>,</span><span>66</span><span>,</span><span>77</span><span>,</span><span>88</span><span>,</span><span>99</span><span>,</span><span>100</span><span>];</span></div></div><div><div><div>2</div></div><div><span>//var arr2 = arr1;</span></div></div><div><div><div>3</div></div><div><span>//arr1.push(111);</span></div></div><div><div><div>4</div></div><div><span>// arr2 也会被改变</span></div></div><div><div><div>5</div></div><div><span>//console.log(arr2);</span></div></div><div><div><div>6</div></div><div><span>// arr1 和 arr2 是同一个数组</span></div></div><div><div><div>7</div></div><div><span>// console.log(arr1 === arr2);</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>//准备一个结果数组</span></div></div><div><div><div>10</div></div><div><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span> [];</span></div></div><div><div><div>11</div></div><div><span>for</span><span>(</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>arr1</span><span>.</span></span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>){</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>result</span><span>.</span><span>push</span><span><span>(</span><span>arr1</span><span>[</span><span>i</span><span>]);</span></span></div></div><div><div><div>13</div></div><div><span>}</span></div></div><div><div><div>14</div></div><div><span><span>arr1</span><span>.</span></span><span>push</span><span>(</span><span>222</span><span>);</span></div></div><div><div><div>15</div></div><div><span>// result 不会被改变</span></div></div><div><div><div>16</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>);</span></span></div></div><div><div><div>17</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr1</span><span>);</span></span></div></div><div><div><div>18</div></div><div><span>// arr1 和 result 是不同的数组</span></div></div><div><div><div>19</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr1</span><span> </span></span><span>===</span><span><span> </span><span>result</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
</li>
<li>
<p>浅克隆只克隆数组的一层，如果数组是多维数组，则克隆的 项会“藕断丝连”。</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr1</span><span> </span></span><span>=</span><span> [</span><span>33</span><span>,</span><span>44</span><span>,</span><span>55</span><span>,</span><span>66</span><span>,[</span><span>77</span><span>,</span><span>88</span><span>]];</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span> [];</span></div></div><div><div><div>3</div></div><div><span>for</span><span>(</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>arr1</span><span>.</span></span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>){</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>result</span><span>.</span><span>push</span><span><span>(</span><span>arr1</span><span>[</span><span>i</span><span>]);</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span><span>arr1</span><span>[</span></span><span>4</span><span>].</span><span>push</span><span>(</span><span>222</span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>);</span></span><span>//[33,44,55,66,[77,88,222]] 浅克隆</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>实现深克隆</strong></p><ul>
<li>
<p>使用递归思想，整体思路和浅克隆类似，但稍微进行一些改 动：如果遍历到项是基本类型值，则直接推入结果数组；如 果遍历到的项是又是数组，则重复执行浅克隆的操作。</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr1</span><span> </span></span><span>=</span><span> [</span><span>33</span><span>,</span><span>44</span><span>,</span><span>55</span><span>,</span><span>66</span><span>,[</span><span>77</span><span>,</span><span>88</span><span>]];</span></div></div><div><div><div>2</div></div><div><span>//实现深度拷贝</span></div></div><div><div><div>3</div></div><div><span>function</span><span> </span><span>deepCopy</span><span><span>(</span><span>arr</span><span>){</span></span></div></div><div><div><div>4</div></div><div><span>    </span><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span> [];</span></div></div><div><div><div>5</div></div><div><span>    </span><span>for</span><span>(</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>arr</span><span>.</span></span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>){</span></div></div><div><div><div>6</div></div><div><span>        </span><span>// 递归调用</span></div></div><div><div><div>7</div></div><div><span>        </span><span>// 递归调用的条件：当前元素是数组</span></div></div><div><div><div>8</div></div><div><span>        </span><span>if</span><span><span>(</span><span>Array</span><span>.</span></span><span>isArray</span><span><span>(</span><span>arr</span><span>[</span><span>i</span><span>])){</span></span></div></div><div><div><div>9</div></div><div><span><span>            </span></span><span>result</span><span>.</span><span>push</span><span>(</span><span>deepCopy</span><span><span>(</span><span>arr</span><span>[</span><span>i</span><span>]));</span></span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>}</span><span>else</span><span>{</span></div></div><div><div><div>11</div></div><div><span>            </span><span>// 非数组元素，直接添加到结果数组</span></div></div><div><div><div>12</div></div><div><span><span>            </span></span><span>result</span><span>.</span><span>push</span><span><span>(</span><span>arr</span><span>[</span><span>i</span><span>]);</span></span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span>    </span><span>return</span><span><span> </span><span>result</span><span>;</span></span></div></div><div><div><div>16</div></div><div><span>}</span></div></div><div><div><div>17</div></div><div><span><span>arr2</span><span> </span></span><span>=</span><span> </span><span>deepCopy</span><span><span>(</span><span>arr1</span><span>)</span></span></div></div><div><div><div>18</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'arr2的数组:'</span><span><span>,</span><span>arr2</span><span>);</span></span><span>//[33,44,55,66,[77,88]]</span></div></div><div><div><div>19</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>( </span><span>arr1</span><span> </span></span><span>===</span><span><span> </span><span>arr2</span><span>);</span></span><span>//false</span></div></div><div><div><div>20</div></div><div><span><span>arr1</span><span>[</span></span><span>4</span><span>].</span><span>push</span><span>(</span><span>222</span><span>);</span></div></div><div><div><div>21</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'arr2的数组:'</span><span><span>,</span><span>arr2</span><span>);</span></span><span>//[33,44,55,66,[77,88]]</span></div></div><div><div><div>22</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>'arr1的数组:'</span><span><span>,</span><span>arr1</span><span>);</span></span><span>//[33,44,55,66,[77,88,222]]</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
</li>
</ul></section></section>
<section><h1>全局变量和局部变量<a href="#全局变量和局部变量"><span>#</span></a></h1><p><strong>变量作用域</strong></p><ul>
<li>
<p>JavaScript是函数级作用域编程语言：变量只在其定义时所 在的function内部有意义。</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>fun</span><span>();</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 报错</span></div></div><div><div><div>6</div></div><div><span>//变量a是在fun函数中被定义的，所以变量a只在fun函数内部有定义，fun函数就是a的“作用域”，变量a被称为局部变量。</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>全局变量</strong></p><ul>
<li>
<p>如果不将变量定义在任何函数的内部，此时这个变量就是全 局变量，它在任何函数内都可以被访问和更改。</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>2</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>a</span><span>++</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 输出11</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>fun</span><span>();</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 输出11变量a没有定义在任何函数内部，它是“全局变量”</span></div></div><div><div><div>8</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>9</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>10</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>5</span><span>;</span></div></div><div><div><div>11</div></div><div><span>a</span><span>++</span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 输出6</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div><div><div><div>14</div></div><div><span>fun</span><span>();</span></div></div><div><div><div>15</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 输出10</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
</li>
</ul><p><strong>遮蔽效应</strong></p><ul>
<li>
<p>如果不将变量定义在任何函数的内部，此时这个变量就是全 局变量，它在任何函数内都可以被访问和更改</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>10</span><span>;</span><span>//变量a没有定义在任何函数内部，它是“全局变量</span></div></div><div><div><div>2</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>a</span><span>++</span><span>;</span><span>//这是全局变量a</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 输出11</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>fun</span><span>();</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 输出11</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>如果函数中也定义了和全局同名的变量，则函数内的变量会 将全局的变量“遮蔽”</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>2</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>5</span><span>;</span><span>//局部变量a将全局变量a“遮蔽”了</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>a</span><span>++</span><span>;</span><span>//改变的是局部变量a的值，不影响全局变量</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 输出6</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div><span>fun</span><span>();</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 输出10</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>注意考虑变量声明提升的情况</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>2</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>//变量提升 var a</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>a</span><span>++</span><span>; </span><span>//局部变量a被自增1，a此时是undefined，自增1结果是NaN</span></div></div><div><div><div>5</div></div><div><span>  </span><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>5</span><span>;</span><span>//重新将a赋值为5</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>a</span><span>);</span></span><span>// 输出5</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div><span>fun</span><span>();</span></div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>);</span></span><span>// 输出10</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>形参也是局部变量</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>2</div></div><div><span>function</span><span> </span><span>fun</span><span><span>(</span><span>a</span><span>) {</span></span><span>//形参a也是函数内部的局部变量</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>a</span><span>++</span><span>;</span><span>//8</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>a</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>fun</span><span>(</span><span>7</span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>);</span></span><span>//10</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>作用域链</strong></p><ul>
<li>
<p>先来认识函数的嵌套：一个函数内部也可以定义一个函数。 和局部变量类似，定义在一个函数内部的函数是局部函数。</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>function</span><span> </span><span>inner</span><span>() {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'你好'</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>inner</span><span>();</span><span>// 调用内部函数</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div><span>fun</span><span>();</span><span>// 调用外部函数</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>在函数嵌套中，变量会从内到外逐层寻找它的定义。</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span> </span><span>20</span><span>;</span></div></div><div><div><div>3</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>4</div></div><div><span>  </span><span>var</span><span><span> </span><span>c</span><span> </span></span><span>=</span><span> </span><span>30</span><span>;</span></div></div><div><div><div>5</div></div><div><span>  </span><span>function</span><span> </span><span>inner</span><span>() {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>40</span><span>;</span></div></div><div><div><div>7</div></div><div><span>    </span><span>var</span><span><span> </span><span>d</span><span> </span></span><span>=</span><span> </span><span>50</span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span>, </span><span>c</span><span>, </span><span>d</span><span>);</span></span><span>//使用变量时，JS会从当前层开始，逐层向上寻找定义  [40 20 30 50]</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span>inner</span><span>();</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div><span>fun</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>不加var将定义全局变量</strong></p><ul>
<li>
<p>在初次给变量赋值时，如果没有加var，则将定义全局变量。</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>a</span><span> </span><span>=</span><span> </span><span>3</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span>fun</span><span>();</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 3</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>8</div></div><div><span>  </span><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>3</span><span>;</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div><span>fun</span><span>();</span></div></div><div><div><div>11</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>);</span></span><span>//报错 a is not defined</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h1>闭包<a href="#闭包"><span>#</span></a></h1><section><h2>什么是闭包<a href="#什么是闭包"><span>#</span></a></h2><p><strong>从一个题目开始</strong></p><p>这个程序的运行结果是什么呢？</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>fun</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>var</span><span><span> </span><span>name</span><span> </span></span><span>=</span><span> </span><span>'慕课网'</span><span>;</span></div></div><div><div><div>3</div></div><div><span>  </span><span>function</span><span> </span><span>innerFun</span><span>() {</span></div></div><div><div><div>4</div></div><div><span>    </span><span>alert</span><span><span>(</span><span>name</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>  </span><span>return</span><span><span> </span><span>innerFun</span><span>;</span></span><span>//返回了内部函数</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div><span>var</span><span><span> </span><span>inn</span><span> </span></span><span>=</span><span> </span><span>fun</span><span>();</span><span>//内部函数被移动到了外部执行</span></div></div><div><div><div>9</div></div><div><span>inn</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li>fun函数里面定义变量name是慕课网，并且定义一个函数innerFun，innerFun弹出name，也就是慕课网，fun函数返回innerFun函数，执行fun函数，inn变量接受，inn接受的是fun返回的innerFun函数，innerFun执行，弹出name，也就是慕课网</li>
</ul><p><strong>什么是闭包</strong></p><ul>
<li>JavaScript中函数会产生闭包（closure）。闭包是函数本身和该函数声明时所处的环境状态的组合。</li>
<li>函数能够“记忆住”其定义时所处的环境，即使函数不在其 定义的环境中被调用，也能访问定义时所处环境的变量</li>
</ul><p><strong>观察闭包现象</strong></p><ul>
<li>在JavaScript中，每次创建函数时都会创建闭包。</li>
<li>但是，闭包特性往往需要将函数“换一个地方”执行，才能 被观察出来。</li>
</ul><p><strong>闭包非常实用</strong></p><ul>
<li>闭包很有用，因为它允许我们将数据与操作该数据的函数关联 起来。这与“面向对象编程”有少许相似之处。</li>
<li>闭包的功能：记忆性、模拟私有变量</li>
</ul></section><section><h2>闭包的记忆性-案例<a href="#闭包的记忆性-案例"><span>#</span></a></h2><ul>
<li>当闭包产生时，函数所处环境的状态会始终保持在内存中，不会在外层函数调用后被自动清除。这就是闭包的记忆性。</li>
</ul><p><strong>闭包的记忆性举例</strong></p><ul>
<li>
<p>创建体温检测函数checkTemp(n)，可以检查体温n是否正常 ，函数会返回布尔值。</p>
</li>
<li>
<p>但是，不同的小区有不同的体温检测标准，比如A小区体温合 格线是37.1℃，而B小区体温合格线是37.3℃，应该怎么编程 呢？</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>createCheckTemp</span><span><span>(</span><span>standardTemp</span><span>){</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>function</span><span> </span><span>checkTemp</span><span><span>(</span><span>temp</span><span>){</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>if</span><span><span>(</span><span>temp</span><span> </span></span><span>&lt;=</span><span><span> </span><span>standardTemp</span><span>){</span></span></div></div><div><div><div>4</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'你的体温正常'</span><span>);</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>}</span><span>else</span><span>{</span></div></div><div><div><div>6</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'你的体温异常'</span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>  </span><span>return</span><span><span> </span><span>checkTemp</span><span>;</span></span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div><span>var</span><span><span> </span><span>checkTemp</span><span> </span></span><span>=</span><span> </span><span>createCheckTemp</span><span>(</span><span>37.1</span><span>);</span><span>//创建一个检查体温的函数，标准体温为37.1度</span></div></div><div><div><div>12</div></div><div><span>var</span><span><span> </span><span>checkTemp1</span><span> </span></span><span>=</span><span> </span><span>createCheckTemp</span><span>(</span><span>37.3</span><span>);</span><span>//创建一个检查体温的函数，标准体温为37.3度</span></div></div><div><div><div>13</div></div><div><span>checkTemp</span><span>(</span><span>36.5</span><span>);</span></div></div><div><div><div>14</div></div><div><span>checkTemp</span><span>(</span><span>37.5</span><span>);</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>checkTemp1</span><span>(</span><span>37.2</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
</li>
</ul><p>ES6版本实现记忆性：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>class</span><span> </span><span>CheckTemp</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>#standardTemp</span><span>; </span><span>// 私有字段：标准体温</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>  </span><span>constructor</span><span><span>(</span><span>standardTemp</span><span>) {</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>this</span><span>.</span><span>#standardTemp</span><span> </span><span>=</span><span><span> </span><span>standardTemp</span><span>;</span></span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>  </span><span>checkTemp</span><span><span>(</span><span>temp</span><span>) {</span></span></div></div><div><div><div>9</div></div><div><span>    </span><span>if</span><span><span> (</span><span>temp</span><span> </span></span><span>&lt;=</span><span> </span><span>this</span><span>.</span><span>#standardTemp</span><span>) {</span></div></div><div><div><div>10</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'你的体温正常'</span><span>);</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>12</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>'你的体温异常'</span><span>);</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>// 创建两个不同标准的体温检测实例</span></div></div><div><div><div>18</div></div><div><span>const</span><span> </span><span>checkTemp</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>CheckTemp</span><span>(</span><span>37.1</span><span>);</span></div></div><div><div><div>19</div></div><div><span>const</span><span> </span><span>checkTemp1</span><span> </span><span>=</span><span> </span><span>new</span><span> </span><span>CheckTemp</span><span>(</span><span>37.3</span><span>);</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>// 检测体温</span></div></div><div><div><div>22</div></div><div><span><span>checkTemp</span><span>.</span></span><span>checkTemp</span><span>(</span><span>36.5</span><span>);  </span><span>// 你的体温正常</span></div></div><div><div><div>23</div></div><div><span><span>checkTemp</span><span>.</span></span><span>checkTemp</span><span>(</span><span>37.5</span><span>);  </span><span>// 你的体温异常</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span><span>checkTemp1</span><span>.</span></span><span>checkTemp</span><span>(</span><span>37.2</span><span>); </span><span>// 你的体温正常</span></div></div><div><div><div>26</div></div><div><span><span>checkTemp1</span><span>.</span></span><span>checkTemp</span><span>(</span><span>37.5</span><span>); </span><span>// 你的体温异常</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h2>闭包模拟私有变量<a href="#闭包模拟私有变量"><span>#</span></a></h2><ul>
<li>
<p>题目：请定义一个变量a，要求是能保证这个a只能被进行指 定操作（如加1、乘2），而不能进行其他操作，应该怎么编 程呢？</p>
</li>
<li>
<p>在Java、C++等语言中，有私有属性的概念，但是JavaScript 中只能用闭包来模拟。</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>fun</span><span>(){</span></div></div><div><div><div>2</div></div><div><span>  </span><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>3</div></div><div><span>  </span><span>return</span><span> {</span></div></div><div><div><div>4</div></div><div><span>    </span><span>getA</span><span>:</span><span> </span><span>function</span><span>(){</span></div></div><div><div><div>5</div></div><div><span><span>      </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>a</span><span>);</span></span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>},</span></div></div><div><div><div>7</div></div><div><span>    </span><span>add</span><span>:</span><span>function</span><span>(){</span></div></div><div><div><div>8</div></div><div><span><span>      </span></span><span>a</span><span>++</span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>},</span></div></div><div><div><div>10</div></div><div><span>    </span><span>pow</span><span>:</span><span>function</span><span>(){</span></div></div><div><div><div>11</div></div><div><span><span>      </span></span><span>a</span><span> </span><span>*=</span><span>2</span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div><div><div><div>15</div></div><div><span>var</span><span><span> </span><span>obj</span><span> </span></span><span>=</span><span> </span><span>fun</span><span>();</span></div></div><div><div><div>16</div></div><div><span>//如果想在fun函数中访问a变量，唯一的方法是通过getA方法访问a变量</span></div></div><div><div><div>17</div></div><div><span><span>obj</span><span>.</span></span><span>getA</span><span>();</span></div></div><div><div><div>18</div></div><div><span><span>obj</span><span>.</span></span><span>add</span><span>();</span></div></div><div><div><div>19</div></div><div><span><span>obj</span><span>.</span></span><span>getA</span><span>();</span></div></div><div><div><div>20</div></div><div><span><span>obj</span><span>.</span></span><span>pow</span><span>();</span></div></div><div><div><div>21</div></div><div><span><span>obj</span><span>.</span></span><span>getA</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
</li>
</ul><p><strong>使用闭包的注意点</strong></p><ul>
<li>不能滥用闭包，否则会造成网页的性能问题，严重时可能导致 内存泄露。所谓内存泄漏是指程序中己动态分配的内存由于某 种原因未释放或无法释放。</li>
<li>所谓内存泄漏是指程序中己动态分配的内存由于某种原因未释 放或无法释放。</li>
</ul><p><strong>闭包的一道面试题</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span> </span><span>addCount</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>var</span><span><span> </span><span>count</span><span> </span></span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>3</div></div><div><span>  </span><span>return</span><span> </span><span>function</span><span> () {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>count</span><span> </span><span>=</span><span><span> </span><span>count</span><span> </span></span><span>+</span><span> </span><span>1</span><span>;</span><span>//count++也可以;1</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>count</span><span>);</span></span><span>//1</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>};</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div><span>var</span><span><span> </span><span>fun1</span><span> </span></span><span>=</span><span> </span><span>addCount</span><span>();</span></div></div><div><div><div>9</div></div><div><span>var</span><span><span> </span><span>fun2</span><span> </span></span><span>=</span><span> </span><span>addCount</span><span>();</span></div></div><div><div><div>10</div></div><div><span>fun1</span><span>();</span><span>//1</span></div></div><div><div><div>11</div></div><div><span>fun2</span><span>();</span><span>//1</span></div></div><div><div><div>12</div></div><div><span>fun2</span><span>();</span><span>//2</span></div></div><div><div><div>13</div></div><div><span>fun1</span><span>();</span><span>//2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li>闭包具有记忆性</li>
</ul></section><section><h2>立即执行函数IIFE<a href="#立即执行函数iife"><span>#</span></a></h2><p><strong>什么是IIFE</strong></p><p>IIFE（Immediately Invoked Function Expression，立即 调用函数表达式）是一种特殊的JavaScript函数写法，一旦 被定义，就立即被调用。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>(</span><span>function</span><span> () {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>statements</span></div></div><div><div><div>3</div></div><div><span>})();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>形成IIFE的方法</strong></p><p>函数不能直接加圆括号被调用</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>function</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>alert</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>3</div></div><div><span>}();</span><span>//错误</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>函数必须转为“函数表达式”才能被调用。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>(</span><span>function</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>alert</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>3</div></div><div><span>})();</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>+</span><span>function</span><span>() {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>alert</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>7</div></div><div><span>}();</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>-</span><span>function</span><span>() {</span></div></div><div><div><div>10</div></div><div><span>    </span><span>alert</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>11</div></div><div><span>}();</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>写法</th><th>作用</th><th>最终表达式的值</th><th>推荐程度</th></tr></thead><tbody><tr><td><code>(function(){})()</code></td><td>括号转换为表达式并立即调用</td><td>函数的返回值</td><td>推荐</td></tr><tr><td><code>+function(){}()</code></td><td>一元加号转换为表达式并立即调用</td><td>返回值经过数值转换</td><td>不推荐</td></tr><tr><td><code>-function(){}()</code></td><td>一元减号转换为表达式并立即调用</td><td>返回值数值转换后取负</td><td>不推荐</td></tr></tbody></table><p><strong>IIFE的作用1 - 为变量赋值</strong></p><p>为变量赋值：当给变量赋值需要一些较为复杂的计算时（如 if语句），使用IIFE显得语法更紧凑。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>age</span><span> </span></span><span>=</span><span> </span><span>12</span><span>;</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>sex</span><span> </span></span><span>=</span><span> </span><span>'男'</span><span>;</span></div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>title</span><span> </span></span><span>=</span><span> (</span><span>function</span><span> () {</span></div></div><div><div><div>4</div></div><div><span>    </span><span>if</span><span><span> (</span><span>age</span><span> </span></span><span>&lt;</span><span> </span><span>18</span><span>) {</span></div></div><div><div><div>5</div></div><div><span>        </span><span>return</span><span> </span><span>'小朋友'</span><span> } </span><span>else</span><span> {</span></div></div><div><div><div>6</div></div><div><span>            </span><span>if</span><span><span> (</span><span>sex</span><span> </span></span><span>==</span><span> </span><span>'男'</span><span>) {</span></div></div><div><div><div>7</div></div><div><span>                </span><span>return</span><span> </span><span>'先生'</span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>            </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>9</div></div><div><span>                </span><span>return</span><span> </span><span>'女士'</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>})();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>IIFE的作用2</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [];</span></div></div><div><div><div>2</div></div><div><span>for</span><span> (</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span> </span><span>5</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>arr</span><span>.</span><span>push</span><span>(</span><span>function</span><span> () {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>i</span><span>);</span></span><span>//变量i是全局变量，所有函数都共享内存中的同一个变量i</span></div></div><div><div><div>5</div></div><div><span>});</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div><span><span>arr</span><span>[</span></span><span>1</span><span>]();</span><span>//5</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>IIFE的作用 - 将全局变量变为局部变量</strong></p><p>IIFE可以在一些场合（如for循环中）将全局变量变为局部变 量，语法显得紧凑</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [];</span></div></div><div><div><div>2</div></div><div><span>for</span><span> (</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span> </span><span>5</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>3</div></div><div><span>(</span><span>function</span><span><span> (</span><span>i</span><span>) {</span></span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>arr</span><span>.</span><span>push</span><span>(</span><span>function</span><span> () {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>i</span><span>);</span></span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>});</span></div></div><div><div><div>8</div></div><div><span><span>})(</span><span>i</span><span>);</span></span><span>//这是立即执行函数，i是当前循环的变量</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div><span><span>arr</span><span>[</span></span><span>2</span><span>](); </span><span>// 弹出2</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026101902javascript-shu-zu/</id>
      <title type="text">JavaScript数组</title>
      <published>2026-10-19T03:17:22.000Z</published>
      <updated>2026-10-19T03:17:22.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026101902javascript-shu-zu/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>数组简介和定义<a href="#数组简介和定义"><span>#</span></a></h1><p><strong>什么是数组</strong></p><p>数组（Array）是 JavaScript 中的一种引用数据类型，用于在一个变量中存储多个数据。</p><p>数组具有以下特点：</p><ul>
<li>可以存储多个数据，且数据类型可以不同。</li>
<li>数组中的每个元素都有对应的下标（索引）。</li>
<li>下标从 <code>0</code> 开始。</li>
<li>数组长度可以动态变化。</li>
</ul><p><strong>数组的定义方法</strong></p><p>数组的定义方法有几种：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//使用 [] 定义数组，是最常用、最推荐的方式。</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>'A'</span><span>, </span><span>'B'</span><span>,</span><span>'C'</span><span>,</span><span>'D'</span><span>];</span></div></div><div><div><div>3</div></div><div><span>//使用 new Array() 创建数组</span></div></div><div><div><div>4</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>Array</span><span>(</span><span>'A'</span><span>,</span><span>'B'</span><span>, </span><span>'C'</span><span>, </span><span>'D'</span><span>);</span></div></div><div><div><div>5</div></div><div><span>//下面的代码表示定义一个长度为4的数组，但是这4项都是 undefined</span></div></div><div><div><div>6</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>Array</span><span>(</span><span>4</span><span>);</span></div></div><div><div><div>7</div></div><div><span>//根据传入的参数创建数组，解决了 Array() 传入单个数字时的歧义。</span></div></div><div><div><div>8</div></div><div><span>const</span><span> </span><span>arr2</span><span> </span><span>=</span><span><span> </span><span>Array</span><span>.</span></span><span>of</span><span>(</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>); </span><span>// [10, 20, 30]</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>访问数组项</strong></p><p>通过数组的下标访问元素，语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//数组名[下标]</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>fruits</span><span> </span><span>=</span><span> [</span><span>"苹果"</span><span>, </span><span>"香蕉"</span><span>, </span><span>"橘子"</span><span>];</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>fruits</span><span>[</span></span><span>0</span><span>]); </span><span>// 苹果</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>fruits</span><span>[</span></span><span>1</span><span>]); </span><span>// 香蕉</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>fruits</span><span>[</span></span><span>2</span><span>]); </span><span>// 橘子</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>下标越界</strong></p><p>当访问的下标不存在时，JavaScript 通常返回 <code>undefined</code>，不会直接报错。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>[</span></span><span>3</span><span>]);  </span><span>// undefined</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>[</span></span><span>10</span><span>]); </span><span>// undefined</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>[</span></span><span>-</span><span>1</span><span>]); </span><span>// undefined</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意：对数组本身访问不存在的下标通常不会报错，但继续访问 <code>undefined</code> 的属性可能报错。</p><p><strong>数组的长度</strong></p><p>使用 <code>length</code> 属性获取数组长度。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const arr = [10, 20, 30, 40];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>console.log(arr.length); // 4</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>// 获取最后一个元素</span></div></div><div><div><div>6</div></div><div><span>console.log(arr[arr.length - 1]); // 40</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>length</code> 可以修改：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>arr</span><span>.</span></span><span>length</span><span> </span><span>=</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// [10, 20]</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>arr</span><span>.</span></span><span>length</span><span> </span><span>=</span><span> </span><span>5</span><span>; </span><span>// 长度为5，后面增加3个空槽位</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意：<strong>数组长度不一定等于实际存在的元素数量</strong>，因为 JavaScript 允许稀疏数组。</p><p><strong>更改数组项</strong></p><p>直接通过下标修改数组中的元素。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>];</span></div></div><div><div><div>2</div></div><div><span><span>arr</span><span>[</span></span><span>1</span><span>] </span><span>=</span><span> </span><span>99</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// [10, 99, 30]</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>也可以通过新的下标添加元素：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>arr</span><span>[</span></span><span>3</span><span>] </span><span>=</span><span> </span><span>40</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// [10, 99, 30, 40]</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>即使使用 <code>const</code> 定义数组，也可以修改内部元素，因为 <code>const</code> 限制的是变量重新赋值，并不禁止修改数组内容。</p><p><strong>数组的遍历</strong></p><p>数组遍历，就是依次访问数组中的元素。（在学习ES6的时候，有扩展很多循环语法，基础的记住for和while，数组使用for…of，对象使用for…in，特殊情况除外 ）</p><p>方法1：for 循环：适合需要操作下标的场景。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>for</span><span> (</span><span>let</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>arr</span><span>.</span></span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>arr</span><span>[</span><span>i</span><span>]);</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>方法2：for…of：适合只需要获取元素值的场景。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>item</span><span> </span><span>of</span><span><span> </span><span>arr</span><span>) {</span></span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>item</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>方法3：forEach()：<code>forEach()</code> 可以同时获取元素值和下标，但不能像普通 <code>for</code> 循环一样通过 <code>break</code> 提前退出。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>arr</span><span>.</span></span><span>forEach</span><span><span>((</span><span>item</span><span>, </span><span>index</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>index</span><span>, </span><span>item</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>数组类型的检测<a href="#数组类型的检测"><span>#</span></a></h1><p>JavaScript 数组本质上属于对象，因此不能单纯使用 <code>typeof</code> 判断。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>typeof</span><span><span> </span><span>arr</span><span>); </span></span><span>// object</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>常见检测方式：</p>

<table><thead><tr><th>检测方式</th><th>示例</th><th>说明</th></tr></thead><tbody><tr><td><code>Array.isArray()</code></td><td><code>Array.isArray(arr)</code></td><td>推荐方式</td></tr><tr><td><code>instanceof</code></td><td><code>arr instanceof Array</code></td><td>检查原型链，跨执行环境可能不准确</td></tr><tr><td><code>Object.prototype.toString.call()</code></td><td><code>Object.prototype.toString.call(arr)</code></td><td>返回 <code>[object Array]</code></td></tr></tbody></table><p>实际开发推荐：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>Array</span><span>.</span></span><span>isArray</span><span><span>(</span><span>arr</span><span>)); </span></span><span>// true</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>Array</span><span>.</span></span><span>isArray</span><span>({}));  </span><span>// false</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>Array</span><span>.</span></span><span>isArray</span><span>(</span><span>"abc"</span><span>)); </span><span>// false</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>数组的常用方法<a href="#数组的常用方法"><span>#</span></a></h1><p>数组提供大量内置方法，主要包括添加、删除、查找、遍历、排序和转换。这里只列举一些常用的，在ES6语法中会再增加一些（slice、splice、<strong>split</strong>这三个英文非常像，初学很可能弄混，这三个是完全不一样功能的，split是字符串的方法，数组可以通过join转字符串，字符串可以使用split转为数组）</p><p><strong>添加与删除</strong>：这5个是最基础的，splice是功能最多的，push和pop是开发中最常用的</p>

<table><thead><tr><th>方法</th><th>作用</th><th>是否修改原数组</th></tr></thead><tbody><tr><td><code>push()</code></td><td>末尾添加元素</td><td>是</td></tr><tr><td><code>pop()</code></td><td>删除末尾元素</td><td>是</td></tr><tr><td><code>unshift()</code></td><td>开头添加元素</td><td>是</td></tr><tr><td><code>shift()</code></td><td>删除开头元素</td><td>是</td></tr><tr><td><code>splice()</code></td><td>添加、删除或替换指定位置元素</td><td>是</td></tr></tbody></table><p>push()方法：（末尾追加）</p><ul>
<li>
<p>push()方法用来在数组末尾推入新项，参数就是要推入 的项</p>
</li>
<li>
<p>如果要推入多项，可以用逗号隔开</p>
</li>
<li>
<p>调用push()方法后，数组会立即改变，不需要赋值</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>arr</span><span>.</span></span><span>push</span><span>(</span><span>4</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// [1, 2, 3, 4]</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>arr</span><span>.</span></span><span>push</span><span>(</span><span>5</span><span>, </span><span>6</span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// [1, 2, 3, 4, 5, 6]</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p>pop()方法：（删除末尾）</p><ul>
<li>
<p>与push()相反，pop()方法用来删除数组中的最后一项</p>
</li>
<li>
<p>pop()方法不仅会删除数组末项，而且会返回被删除的项</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>item</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>pop</span><span>();</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>);  </span></span><span>// [1, 2, 3]</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>item</span><span>);  </span></span><span>// 4</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p>unshift()方法：（头部插入）</p><ul>
<li>
<p>unshift()方法用来在数组头尾插入新项，参数就是要 插入的项</p>
</li>
<li>
<p>如果要插入多项，可以用逗号隔开</p>
</li>
<li>
<p>调用unshift()方法后，数组会立即改变，不需要赋值</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>arr</span><span>.</span></span><span>unshift</span><span>(</span><span>1</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// [1, 2, 3, 4]</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>arr</span><span>.</span></span><span>unshift</span><span>(</span><span>-</span><span>1</span><span>, </span><span>0</span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// [-1, 0, 1, 2, 3, 4]</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p>shift()方法：（删除头部）</p><ul>
<li>
<p>与unshift()相反，shift()方法用来删除数组中下标为0 的项</p>
</li>
<li>
<p>shift()方法不仅会删除数组末项，而且会返回被删除的项</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>item</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>shift</span><span>();</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// [20, 30]</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>item</span><span>); </span></span><span>// 10</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p>splice()方法</p><ul>
<li>
<p>splice()方法第一个参数是从哪个下标开始，第二个参数是删除多少个项</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>arr</span><span>.</span></span><span>splice</span><span><span>(</span><span>起始下标</span><span>, </span><span>删除个数</span><span>)</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>'A'</span><span>,</span><span>'B'</span><span>,</span><span>'C'</span><span>,</span><span>'D'</span><span>,</span><span>'E'</span><span>,</span><span>'F'</span><span>,</span><span>'G'</span><span>];</span></div></div><div><div><div>2</div></div><div><span><span>arr</span><span>.</span></span><span>splice</span><span>(</span><span>3</span><span>,</span><span>2</span><span>,</span><span>'X'</span><span>,</span><span>'Y'</span><span>,</span><span>'Z'</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>);</span></span></div></div><div><div><div>4</div></div><div><span>// 下标3开始，连续替换2项；这种说法错误的</span></div></div><div><div><div>5</div></div><div><span>// 准确是：下标3开始，连续删除2项，然后插入新元素</span></div></div><div><div><div>6</div></div><div><span>// [ 'A', 'B', 'C', 'X', 'Y', 'Z','F', 'G']</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>splice()方法可以用于在指定位置插入新项（第二个参数设置0，就没有删除项）</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>arr</span><span>.</span></span><span>splice</span><span><span>(</span><span>起始下标</span><span>, </span></span><span>0</span><span><span>, </span><span>新元素</span><span>)</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>5</span><span>, </span><span>6</span><span>];</span></div></div><div><div><div>2</div></div><div><span><span>arr</span><span>.</span></span><span>splice</span><span>(</span><span>2</span><span>, </span><span>0</span><span>, </span><span>3</span><span>, </span><span>4</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// [1, 2, 3, 4, 5, 6]</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>splice()方法可以用于删除指定项；result返回被删除的项</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>arr</span><span>.</span></span><span>splice</span><span><span>(</span><span>起始下标</span><span>, </span><span>删除个数</span><span>)</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>, </span><span>40</span><span>];</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>splice</span><span>(</span><span>1</span><span>, </span><span>1</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>);    </span></span><span>// [10, 30, 40]</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>); </span></span><span>// [20]</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>splice()方法会以数组形式返回被删除的项</p>
</li>
</ul><p><strong>查找与判断：</strong></p>

<table><thead><tr><th>方法</th><th>作用</th><th>返回值</th></tr></thead><tbody><tr><td><code>indexOf()</code></td><td>查找元素首次出现的位置</td><td>下标或 -1</td></tr><tr><td><code>lastIndexOf()</code></td><td>查找元素最后出现的位置</td><td>下标或 -1</td></tr><tr><td><code>includes()</code></td><td>判断是否包含元素</td><td>布尔值</td></tr><tr><td><code>find()</code></td><td>查找第一个符合条件的元素</td><td>元素或 undefined</td></tr><tr><td><code>findIndex()</code></td><td>查找第一个符合条件的元素下标</td><td>下标或 -1</td></tr><tr><td><code>some()</code></td><td>是否至少一个元素符合条件</td><td>布尔值</td></tr><tr><td><code>every()</code></td><td>是否所有元素符合条件</td><td>布尔值</td></tr></tbody></table><p>indexOf()方法的功能是搜索数组中的元素，并返回它所 在的位置，如果元素不存在，则返回-1</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>'A'</span><span>, </span><span>'B'</span><span>, </span><span>'C'</span><span>, </span><span>'D'</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>.</span></span><span>indexOf</span><span>(</span><span>'B'</span><span>)); </span><span>// 1</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>.</span></span><span>indexOf</span><span>(</span><span>'Z'</span><span>)); </span><span>// -1</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>includes()方法的功能是判断一个数组是否包含一个指定 的值，返回布尔值</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>'A'</span><span>, </span><span>'B'</span><span>, </span><span>'C'</span><span>];</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>.</span></span><span>includes</span><span>(</span><span>'B'</span><span>)); </span><span>// true</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>.</span></span><span>includes</span><span>(</span><span>'Z'</span><span>)); </span><span>// false</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>截取、合并与转换</strong></p>

<table><thead><tr><th>方法</th><th>作用</th><th>是否修改原数组</th></tr></thead><tbody><tr><td><code>slice()</code></td><td>截取数组片段</td><td>否</td></tr><tr><td><code>concat()</code></td><td>合并数组</td><td>否</td></tr><tr><td><code>join()</code></td><td>将数组连接成字符串</td><td>否</td></tr><tr><td><code>reverse()</code></td><td>反转数组</td><td>是</td></tr><tr><td><code>sort()</code></td><td>对数组排序</td><td>是</td></tr><tr><td><code>flat()</code></td><td>展平嵌套数组</td><td>否</td></tr></tbody></table><p>slice()方法：slice()方法用于得到子数组，slice(a, b)截取的子数组从下标为a的项开始，到下标为 b（但不包括下标为b的项）结束</p><ul>
<li>
<p>标准写法</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>'A'</span><span>,</span><span>'B'</span><span>,</span><span>'C'</span><span>,</span><span>'D'</span><span>,</span><span>'E'</span><span>,</span><span>'F'</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>slice</span><span>(</span><span>1</span><span>, </span><span>4</span><span>);</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>); </span></span><span>// ['B','C','D'] 从下标 1 开始；（B）到下标 4 结束（不包含4）所以是：B、C、D</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>);    </span></span><span>// ['A','B','C','D','E','F']</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>slice()如果不提供第二个参数，则表示从指定项开始，提 取所有后续所有项作为子数组</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>'A'</span><span>,</span><span>'B'</span><span>,</span><span>'C'</span><span>,</span><span>'D'</span><span>,</span><span>'E'</span><span>,</span><span>'F'</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>slice</span><span>(</span><span>2</span><span>);</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>); </span></span><span>// ['C','D','E','F']</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>slice(a, b)方法不会更改原有数组，返回的是截取的数组</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>slice</span><span>(</span><span>1</span><span>, </span><span>3</span><span>);</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>); </span></span><span>// [2, 3]</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>);    </span></span><span>// [1, 2, 3, 4]  ✔ 原数组不变</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>slice()方法的参数允许为负数，表示数组的倒数第几项</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>'A'</span><span>,</span><span>'B'</span><span>,</span><span>'C'</span><span>,</span><span>'D'</span><span>,</span><span>'E'</span><span>,</span><span>'F'</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>slice</span><span>(</span><span>-</span><span>3</span><span>);</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>); </span></span><span>// ['D','E','F']</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p>concat()方法</p><ul>
<li>
<p>concat()方法可以合并连结多个数组</p>
</li>
<li>
<p>concat()方法不会改变原数组</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr1</span><span> </span></span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>];</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>arr2</span><span> </span></span><span>=</span><span> [</span><span>5</span><span>, </span><span>6</span><span>, </span><span>7</span><span>, </span><span>8</span><span>];</span></div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>arr3</span><span> </span></span><span>=</span><span> [</span><span>9</span><span>, </span><span>10</span><span>, </span><span>11</span><span>];</span></div></div><div><div><div>4</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span><span> </span><span>arr1</span><span>.</span></span><span>concat</span><span><span>(</span><span>arr2</span><span> , </span><span>arr3</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>);</span></span></div></div><div><div><div>6</div></div><div><span>// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p>join()方法</p><ul>
<li>
<p><strong>数组的join()方法</strong>可以使数组转为字符串；<strong>字符串的split() 方法</strong>可以使字符串转为数组。</p>
</li>
<li>
<p>join()的参数表示以什么字符作为连接符，如果留空则默 认以逗号分隔，如同调用toString()方法</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>'A'</span><span>, </span><span>'B'</span><span>, </span><span>'C'</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>str</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>join</span><span>(</span><span>'-'</span><span>);</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>str</span><span>); </span></span><span>// "A-B-C"</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>split()的参数表示以什么字符拆分字符串，一般不能留空</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>str</span><span> </span></span><span>=</span><span> </span><span>"A-B-C"</span><span>;</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span><span> </span><span>str</span><span>.</span></span><span>split</span><span>(</span><span>'-'</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// ["A", "B", "C"]</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p>reverse()方法</p><ul>
<li>
<p>reverse()方法用来将一个数组中的全部项顺序置反</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>"A"</span><span>,</span><span>"B"</span><span>,</span><span>"C"</span><span>,</span><span>"D"</span><span>];</span></div></div><div><div><div>2</div></div><div><span><span>arr</span><span>.</span></span><span>reverse</span><span>();</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// ["D","C","B","A"]</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h1>遍历相关算法<a href="#遍历相关算法"><span>#</span></a></h1><ul>
<li>
<p>题目：求数组中每一项的总和、平均数</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>, </span><span>40</span><span>, </span><span>50</span><span>];</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>sum</span><span> </span></span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>3</div></div><div><span>for</span><span> (</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>arr</span><span>.</span></span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>sum</span><span> </span><span>+=</span><span><span> </span><span>arr</span><span>[</span><span>i</span><span>];</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>var</span><span><span> </span><span>avg</span><span> </span></span><span>=</span><span><span> </span><span>sum</span><span> </span></span><span>/</span><span><span> </span><span>arr</span><span>.</span></span><span>length</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>"总和："</span><span> </span><span>+</span><span><span> </span><span>sum</span><span>);</span></span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>"平均数："</span><span> </span><span>+</span><span><span> </span><span>avg</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>10</span><span>, </span><span>20</span><span>, </span><span>30</span><span>, </span><span>40</span><span>, </span><span>50</span><span>];</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>sum</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>reduce</span><span>(</span><span>function</span><span><span> (</span><span>acc</span><span>, </span><span>cur</span><span>) {</span></span></div></div><div><div><div>3</div></div><div><span>    </span><span>return</span><span><span> </span><span>acc</span><span> </span></span><span>+</span><span><span> </span><span>cur</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>}, </span><span>0</span><span>);</span></div></div><div><div><div>5</div></div><div><span>var</span><span><span> </span><span>avg</span><span> </span></span><span>=</span><span><span> </span><span>sum</span><span> </span></span><span>/</span><span><span> </span><span>arr</span><span>.</span></span><span>length</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>sum</span><span>, </span><span>avg</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>题目：求数组项的最大值和最小值</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>12</span><span>, </span><span>5</span><span>, </span><span>78</span><span>, </span><span>23</span><span>, </span><span>9</span><span>, </span><span>100</span><span>, </span><span>34</span><span>];</span></div></div><div><div><div>2</div></div><div><span>// 假设第一个是最大值和最小值</span></div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>max</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>[</span></span><span>0</span><span>];</span></div></div><div><div><div>4</div></div><div><span>var</span><span><span> </span><span>min</span><span> </span></span><span>=</span><span><span> </span><span>arr</span><span>[</span></span><span>0</span><span>];</span></div></div><div><div><div>5</div></div><div><span>for</span><span> (</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>1</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>arr</span><span>.</span></span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>if</span><span><span> (</span><span>arr</span><span>[</span><span>i</span><span>] </span></span><span>&gt;</span><span><span> </span><span>max</span><span>) {</span></span></div></div><div><div><div>7</div></div><div><span><span>        </span></span><span>max</span><span> </span><span>=</span><span><span> </span><span>arr</span><span>[</span><span>i</span><span>];</span></span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>    </span><span>if</span><span><span> (</span><span>arr</span><span>[</span><span>i</span><span>] </span></span><span>&lt;</span><span><span> </span><span>min</span><span>) {</span></span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>min</span><span> </span><span>=</span><span><span> </span><span>arr</span><span>[</span><span>i</span><span>];</span></span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>"最大值："</span><span> </span><span>+</span><span><span> </span><span>max</span><span>);</span></span></div></div><div><div><div>14</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>"最小值："</span><span> </span><span>+</span><span><span> </span><span>min</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>题目：统计符合条件的元素数量</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>12</span><span>, </span><span>25</span><span>, </span><span>36</span><span>, </span><span>47</span><span>, </span><span>58</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>let</span><span><span> </span><span>count</span><span> </span></span><span>=</span><span> </span><span>0</span><span>;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>for</span><span> (</span><span>const</span><span> </span><span>item</span><span> </span><span>of</span><span><span> </span><span>arr</span><span>) {</span></span></div></div><div><div><div>6</div></div><div><span>  </span><span>if</span><span><span> (</span><span>item</span><span> </span></span><span>%</span><span> </span><span>2</span><span> </span><span>===</span><span> </span><span>0</span><span>) {</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>count</span><span>++</span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>count</span><span>); </span></span><span>// 3</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h1>数组去重和随机样本<a href="#数组去重和随机样本"><span>#</span></a></h1><p><strong>数组去重</strong></p><ul>
<li>
<p>题目：去掉数组中的重复项</p>
</li>
<li>
<p>思路：准备一个空结果数组，遍历原数组，如果遍历到的项不在结果数组中，则推入结果数组。</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>2</span><span>, </span><span>4</span><span>, </span><span>1</span><span>, </span><span>5</span><span>];</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span> [];</span></div></div><div><div><div>3</div></div><div><span>for</span><span> (</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>arr</span><span>.</span></span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>4</div></div><div><span>    </span><span>if</span><span> (</span><span>!</span><span><span>result</span><span>.</span></span><span>includes</span><span><span>(</span><span>arr</span><span>[</span><span>i</span><span>])) {</span></span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>result</span><span>.</span><span>push</span><span><span>(</span><span>arr</span><span>[</span><span>i</span><span>]);</span></span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p>ES6版本：使用<code>Set</code>，<code>Set</code> 是一种不保存重复值的集合类型，配合展开运算符 <code>...</code> 可以转换回数组。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>3</span><span>, </span><span>4</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>result</span><span> </span><span>=</span><span> [</span><span>...</span><span>new</span><span> </span><span>Set</span><span><span>(</span><span>arr</span><span>)];</span></span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>); </span></span><span>// [1, 2, 3, 4]</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>filter() + indexOf()：原理：只保留每个元素首次出现的位置。这种方式对 <code>NaN</code> 等特殊值不如 <code>Set</code> 合适。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>3</span><span>, </span><span>4</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>result</span><span> </span><span>=</span><span><span> </span><span>arr</span><span>.</span></span><span>filter</span><span><span>((</span><span>item</span><span>, </span><span>index</span><span>) </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span>  </span><span>return</span><span><span> </span><span>arr</span><span>.</span></span><span>indexOf</span><span><span>(</span><span>item</span><span>) </span></span><span>===</span><span><span> </span><span>index</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>});</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>); </span></span><span>// [1, 2, 3, 4]</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>随机样本</strong></p><ul>
<li>
<p>题目：请随机从原数组中取3项</p>
</li>
<li>
<p>思路：准备一个空结果数组，遍历原数组，随机选择一项 ，推入结果数组，并且将这项删除</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>arr</span><span> </span></span><span>=</span><span> [</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>, </span><span>4</span><span>, </span><span>5</span><span>, </span><span>6</span><span>, </span><span>7</span><span>, </span><span>8</span><span>, </span><span>9</span><span>];</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span> [];</span></div></div><div><div><div>3</div></div><div><span>for</span><span> (</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span> </span><span>3</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>4</div></div><div><span>    </span><span>// 1. 随机下标</span></div></div><div><div><div>5</div></div><div><span>    </span><span>var</span><span><span> </span><span>index</span><span> </span></span><span>=</span><span><span> </span><span>Math</span><span>.</span></span><span>floor</span><span><span>(</span><span>Math</span><span>.</span></span><span>random</span><span>() </span><span>*</span><span><span> </span><span>arr</span><span>.</span></span><span>length</span><span>);</span></div></div><div><div><div>6</div></div><div><span>    </span><span>// 2. 取出该项</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>result</span><span>.</span><span>push</span><span><span>(</span><span>arr</span><span>[</span><span>index</span><span>]);</span></span></div></div><div><div><div>8</div></div><div><span>    </span><span>// 3. 删除该项（防止重复）</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>arr</span><span>.</span><span>splice</span><span><span>(</span><span>index</span><span>, </span></span><span>1</span><span>);</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h1>冒泡排序（重点）<a href="#冒泡排序重点"><span>#</span></a></h1><p>冒泡排序（Bubble Sort）是一种基础排序算法，**核心思想：相邻两个元素进行比较，如果顺序错误就交换位置。**以升序排序为例，每一轮都把当前未排序部分的最大元素移动到右边。</p><p>xxxxxxxxxx var arr = [];for (var i = 0; i &lt; 5; i++) {(function (i) {    arr.push(function () {    console.log(i);    });})(i);//这是立即执行函数，i是当前循环的变量}arr<a>2</a>; // 弹出2js</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>5</span><span>, </span><span>3</span><span>, </span><span>8</span><span>, </span><span>4</span><span>, </span><span>2</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>for</span><span> (</span><span>let</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>arr</span><span>.</span></span><span>length</span><span> </span><span>-</span><span> </span><span>1</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>4</div></div><div><span>  </span><span>for</span><span> (</span><span>let</span><span><span> </span><span>j</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>j</span><span> </span></span><span>&lt;</span><span><span> </span><span>arr</span><span>.</span></span><span>length</span><span> </span><span>-</span><span> </span><span>1</span><span> </span><span>-</span><span><span> </span><span>i</span><span>; </span><span>j</span></span><span>++</span><span>) {</span></div></div><div><div><div>5</div></div><div><span>    </span><span>if</span><span><span> (</span><span>arr</span><span>[</span><span>j</span><span>] </span></span><span>&gt;</span><span><span> </span><span>arr</span><span>[</span><span>j</span><span> </span></span><span>+</span><span> </span><span>1</span><span>]) {</span></div></div><div><div><div>6</div></div><div><span>      </span><span>const</span><span> </span><span>temp</span><span> </span><span>=</span><span><span> </span><span>arr</span><span>[</span><span>j</span><span>];</span></span></div></div><div><div><div>7</div></div><div><span><span>      </span></span><span>arr</span><span>[</span><span>j</span><span>] </span><span>=</span><span><span> </span><span>arr</span><span>[</span><span>j</span><span> </span></span><span>+</span><span> </span><span>1</span><span>];</span></div></div><div><div><div>8</div></div><div><span><span>      </span></span><span>arr</span><span>[</span><span>j</span><span> </span><span>+</span><span> </span><span>1</span><span>] </span><span>=</span><span><span> </span><span>temp</span><span>;</span></span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>); </span></span><span>// [2, 3, 4, 5, 8]</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>代码理解：</p>

<table><thead><tr><th>代码</th><th>作用</th></tr></thead><tbody><tr><td>外层 <code>i</code> 循环</td><td>控制排序轮数</td></tr><tr><td>内层 <code>j</code> 循环</td><td>比较相邻元素</td></tr><tr><td><code>arr[j] &gt; arr[j + 1]</code></td><td>判断是否需要交换</td></tr><tr><td><code>temp</code></td><td>临时保存元素，完成交换</td></tr><tr><td><code>arr.length - 1 - i</code></td><td>排除已经排好序的末尾部分</td></tr></tbody></table><p>实际开发中通常使用 <code>sort()</code> 排序，学习冒泡排序的重点在于掌握双层循环、相邻比较和元素交换。</p></section>
<section><h1>二维数组<a href="#二维数组"><span>#</span></a></h1><p>二维数组可以理解为数组中的元素仍然是数组。</p><p>访问二维数组：通过两个下标访问元素：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>[</span><span>1</span><span>, </span><span>2</span><span>, </span><span>3</span><span>],</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>[</span><span>4</span><span>, </span><span>5</span><span>, </span><span>6</span><span>],</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>[</span><span>7</span><span>, </span><span>8</span><span>, </span><span>9</span><span>]</span></div></div><div><div><div>5</div></div><div><span>];</span></div></div><div><div><div>6</div></div><div><span>//第一个下标表示外层数组的索引，第二个表示内层数组的索引。</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>[</span></span><span>0</span><span>][</span><span>0</span><span>]); </span><span>// 1</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>[</span></span><span>1</span><span>][</span><span>2</span><span>]); </span><span>// 6</span></div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>[</span></span><span>2</span><span>][</span><span>1</span><span>]); </span><span>// 8</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>遍历二维数组&lt;使用双层循环&gt;：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>let</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>arr</span><span>.</span></span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>for</span><span> (</span><span>let</span><span><span> </span><span>j</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>j</span><span> </span></span><span>&lt;</span><span><span> </span><span>arr</span><span>[</span><span>i</span><span>].</span></span><span>length</span><span><span>; </span><span>j</span></span><span>++</span><span>) {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>arr</span><span>[</span><span>i</span><span>][</span><span>j</span><span>]);</span></span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>创建二维数组</p><p>例如创建一个 3 行 4 列，所有元素为 0 的二维数组：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span><span> </span><span>Array</span><span>.</span></span><span>from</span><span>(</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>{ </span><span>length</span><span>:</span><span> </span><span>3</span><span> },</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>() </span><span>=&gt;</span><span> </span><span>Array</span><span>(</span><span>4</span><span>).</span><span>fill</span><span>(</span><span>0</span><span>)</span></div></div><div><div><div>4</div></div><div><span>);</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>得到：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>[</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>[</span><span>0</span><span>, </span><span>0</span><span>, </span><span>0</span><span>, </span><span>0</span><span>],</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>[</span><span>0</span><span>, </span><span>0</span><span>, </span><span>0</span><span>, </span><span>0</span><span>],</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>[</span><span>0</span><span>, </span><span>0</span><span>, </span><span>0</span><span>, </span><span>0</span><span>]</span></div></div><div><div><div>5</div></div><div><span>]</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意：不要使用 <code>Array(3).fill(Array(4).fill(0))</code> 创建需要独立修改每一行的二维数组，因为这种方式会让每一行引用同一个内层数组。</p></section>
<section><h1>基本类型值和引用类型值<a href="#基本类型值和引用类型值"><span>#</span></a></h1><ul>
<li>基本类型：number、boolean、string、undefined、 null</li>
<li>引用类型：array、object、function、regexp…</li>
</ul><p>相等判断时的区别：</p><ul>
<li>基本类型进行相等判断时，会比较值是否相等</li>
<li>引用类型进行相等判断时，会比较址是否相等，也就是说 它会比较是否为内存中的同一个东西</li>
</ul>

<table><thead><tr><th>类型</th><th>举例</th><th>当 var a = b 变量传值时</th><th>当用 == 比较时</th></tr></thead><tbody><tr><td>基本类型值</td><td>数字型、字符串型、布尔型、undefined 型</td><td>内存中产生新的副本</td><td>比较值是否相等</td></tr><tr><td>引用类型值</td><td>对象、数组</td><td>内存中不产生新的副本，而是让新变量指向同一个对象</td><td>比较内存地址是否相同，即比较是否是同一个对象</td></tr></tbody></table><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span><span> </span><span>a</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>2</span><span>;</span></div></div><div><div><div>4</div></div><div><span>// a 和 b 是不同的变量</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>);</span></span><span>//2</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>b</span><span>);</span></span><span>//1</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>深克隆和浅克隆（重点）<a href="#深克隆和浅克隆重点"><span>#</span></a></h1><ul>
<li>
<p>浅克隆：只克隆数组的第一层，如果是<strong>多维数组</strong>，或者<strong>数 组中的项是其他引用类型值</strong>，则不克隆其他层</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var arr = [1, 2, 3];</span></div></div><div><div><div>2</div></div><div><span>var newArr = [];</span></div></div><div><div><div>3</div></div><div><span>for (var i = 0; i &lt; arr.length; i++) {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>newArr.push(arr[i]);</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>arr.push(222);</span></div></div><div><div><div>7</div></div><div><span>console.log(newArr); // [1, 2, 3]</span></div></div><div><div><div>8</div></div><div><span>console.log(arr); // [1, 2, 3，222]</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var arr = [{ a: 1 }, { b: 2 }];</span></div></div><div><div><div>2</div></div><div><span>var newArr = [];</span></div></div><div><div><div>3</div></div><div><span>for (var i = 0; i &lt; arr.length; i++) {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>newArr.push(arr[i]);</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>newArr[0].a = 100//改变新数组，旧数组也更着变了</span></div></div><div><div><div>7</div></div><div><span>console.log(newArr); // [ { a: 100 }, { b: 2 } ]</span></div></div><div><div><div>8</div></div><div><span>console.log(arr); // [ { a: 100 }, { b: 2 } ]</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>深克隆：克隆数组的所有层，要使用递归技术，在后面介绍，但是在现代开发中有一个api可以实现，不用手写递归，那就是<code>structuredClone()</code> ，自 2022 年 3 月起已在主流浏览器中广泛支持，Node.js 从 17.0.0 开始提供该 API。</p>
</li>
<li>
<p>它支持数组、普通对象、<code>Date</code>、<code>Map</code>、<code>Set</code> 等，也支持循环引用，但有一些限制。</p>

<table><thead><tr><th>数据类型</th><th>是否支持</th></tr></thead><tbody><tr><td>普通对象、数组</td><td>✔</td></tr><tr><td>嵌套对象、二维数组</td><td>✔</td></tr><tr><td>Date、Map、Set</td><td>✔</td></tr><tr><td>循环引用</td><td>✔</td></tr><tr><td>函数</td><td>❌</td></tr><tr><td>DOM 元素</td><td>❌</td></tr><tr><td>Proxy 代理对象</td><td>❌</td></tr><tr><td>自定义类的原型与方法</td><td>不能完整保留</td></tr></tbody></table>
</li>
<li>
<p>对象深克隆：</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 对象深克隆</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>obj1</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>name</span><span>:</span><span> </span><span>"张三"</span><span>,</span></div></div><div><div><div>4</div></div><div><span>  </span><span>age</span><span>:</span><span> </span><span>20</span><span>,</span></div></div><div><div><div>5</div></div><div><span>  </span><span>hobby</span><span>:</span><span> [</span><span>"篮球"</span><span>, </span><span>"足球"</span><span>],</span></div></div><div><div><div>6</div></div><div><span>  </span><span>address</span><span>:</span><span> {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>city</span><span>:</span><span> </span><span>"北京"</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>};</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>const</span><span> </span><span>obj2</span><span> </span><span>=</span><span> </span><span>structuredClone</span><span><span>(</span><span>obj1</span><span>);</span></span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>obj2</span><span>.</span></span><span>hobby</span><span>[</span><span>0</span><span>] </span><span>=</span><span> </span><span>"羽毛球"</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>obj2</span><span>.</span></span><span>address</span><span>.</span><span>city</span><span> </span><span>=</span><span> </span><span>"上海"</span><span>;</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj1</span><span>.</span></span><span>hobby</span><span>);        </span><span>// ["篮球", "足球"]</span></div></div><div><div><div>17</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>obj1</span><span>.</span></span><span>address</span><span>.</span><span>city</span><span>); </span><span>// 北京</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
</li>
<li>
<p>数组深克隆</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr1</span><span> </span><span>=</span><span> [[</span><span>1</span><span>, </span><span>2</span><span>], [</span><span>3</span><span>, </span><span>4</span><span>]];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>arr2</span><span> </span><span>=</span><span> </span><span>structuredClone</span><span><span>(</span><span>arr1</span><span>);</span></span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>arr2</span><span>[</span></span><span>0</span><span>][</span><span>0</span><span>] </span><span>=</span><span> </span><span>99</span><span>;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr1</span><span>); </span></span><span>// [[1, 2], [3, 4]]</span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>arr2</span><span>); </span></span><span>// [[99, 2], [3, 4]]</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026101901javascript-liu-cheng-kong-zhi-yu-ju/</id>
      <title type="text">JavaScript流程控制语句</title>
      <published>2026-10-18T23:32:53.000Z</published>
      <updated>2026-10-18T23:32:53.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026101901javascript-liu-cheng-kong-zhi-yu-ju/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>JavaScript 中，流程控制语句用于控制代码的执行顺序，主要分为两大类：</p>
<ul>
<li>条件判断：<code>if...else</code>、<code>switch</code>、三元运算符，根据条件决定执行哪些代码。</li>
<li>循环控制：<code>for</code>、<code>while</code>、<code>do...while</code>，让代码重复执行。</li>
</ul>
<section><h1>if…else 条件判断语句<a href="#ifelse-条件判断语句"><span>#</span></a></h1><p><code>if...else</code> 用于根据条件是否成立，决定执行不同的代码。</p><section><h2>基本语法<a href="#基本语法"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>if</span><span><span> (</span><span>条件表达式</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>// 条件为 true 时执行</span></div></div><div><div><div>3</div></div><div><span>} </span><span>else</span><span> {</span></div></div><div><div><div>4</div></div><div><span>  </span><span>// 条件为 false 时执行</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>age</span><span> </span></span><span>=</span><span> </span><span>18</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>if</span><span><span> (</span><span>age</span><span> </span></span><span>&gt;=</span><span> </span><span>18</span><span>) {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"成年人"</span><span>);</span></div></div><div><div><div>5</div></div><div><span>} </span><span>else</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"未成年人"</span><span>);</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>多条件判断<a href="#多条件判断"><span>#</span></a></h2><p>通过 <code>else if</code> 可以判断多个条件。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>score</span><span> </span></span><span>=</span><span> </span><span>85</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>if</span><span><span> (</span><span>score</span><span> </span></span><span>&gt;=</span><span> </span><span>90</span><span>) {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"优秀"</span><span>);</span></div></div><div><div><div>5</div></div><div><span>} </span><span>else</span><span> </span><span>if</span><span><span> (</span><span>score</span><span> </span></span><span>&gt;=</span><span> </span><span>80</span><span>) {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"良好"</span><span>);</span></div></div><div><div><div>7</div></div><div><span>} </span><span>else</span><span> </span><span>if</span><span><span> (</span><span>score</span><span> </span></span><span>&gt;=</span><span> </span><span>60</span><span>) {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"及格"</span><span>);</span></div></div><div><div><div>9</div></div><div><span>} </span><span>else</span><span> {</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"不及格"</span><span>);</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意：</p><ul>
<li>条件表达式会转换为布尔值进行判断。</li>
<li>从上往下依次判断，命中第一个成立的条件后，跳过后续分支。</li>
<li><code>else if</code> 和 <code>else</code> 都是可选的。</li>
<li>建议始终使用 <code>{}</code> 包裹代码块。</li>
</ul></section></section>
<section><h1>switch 多分支选择语句<a href="#switch-多分支选择语句"><span>#</span></a></h1><p><code>switch</code> 用于将一个表达式的值与多个 <code>case</code> 进行匹配。</p><section><h2>基本语法<a href="#基本语法-1"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>switch (表达式) {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>case 值1:</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>// 匹配值1时执行</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>break;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>case 值2:</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>// 匹配值2时执行</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>break;</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>default:</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>// 都不匹配时执行</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>示例：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>day</span><span> </span></span><span>=</span><span> </span><span>3</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>switch</span><span><span> (</span><span>day</span><span>) {</span></span></div></div><div><div><div>4</div></div><div><span>  </span><span>case</span><span> </span><span>1</span><span>:</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"星期一"</span><span>);</span></div></div><div><div><div>6</div></div><div><span>    </span><span>break</span><span>;</span></div></div><div><div><div>7</div></div><div><span>  </span><span>case</span><span> </span><span>2</span><span>:</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"星期二"</span><span>);</span></div></div><div><div><div>9</div></div><div><span>    </span><span>break</span><span>;</span></div></div><div><div><div>10</div></div><div><span>  </span><span>case</span><span> </span><span>3</span><span>:</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"星期三"</span><span>);</span></div></div><div><div><div>12</div></div><div><span>    </span><span>break</span><span>;</span></div></div><div><div><div>13</div></div><div><span>  </span><span>default</span><span>:</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"其他日期"</span><span>);</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>输出：<code>星期三</code></p></section><section><h2>break 的作用<a href="#break-的作用"><span>#</span></a></h2><p><code>break</code> 用于结束当前 <code>switch</code> 语句。</p><p>如果不写 <code>break</code>，程序会继续执行后面的 <code>case</code> 代码，这种行为称为穿透（fall-through）。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>num</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>switch</span><span><span> (</span><span>num</span><span>) {</span></span></div></div><div><div><div>4</div></div><div><span>  </span><span>case</span><span> </span><span>1</span><span>:</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"一"</span><span>);</span></div></div><div><div><div>6</div></div><div><span>  </span><span>case</span><span> </span><span>2</span><span>:</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"二"</span><span>);</span></div></div><div><div><div>8</div></div><div><span>  </span><span>default</span><span>:</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"其他"</span><span>);</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>输出：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>一</span></div></div><div><div><div>2</div></div><div><span>二</span></div></div><div><div><div>3</div></div><div><span>其他</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>多个 case 共用代码<a href="#多个-case-共用代码"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>day</span><span> </span></span><span>=</span><span> </span><span>6</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>switch</span><span><span> (</span><span>day</span><span>) {</span></span></div></div><div><div><div>4</div></div><div><span>  </span><span>case</span><span> </span><span>6</span><span>:</span></div></div><div><div><div>5</div></div><div><span>  </span><span>case</span><span> </span><span>7</span><span>:</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"周末"</span><span>);</span></div></div><div><div><div>7</div></div><div><span>    </span><span>break</span><span>;</span></div></div><div><div><div>8</div></div><div><span>  </span><span>default</span><span>:</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"工作日"</span><span>);</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>输出：<code>周末</code></p><p>注意： <code>switch</code> 使用严格相等（<code>===</code>）的匹配规则，不会自动将字符串 <code>"1"</code> 转换为数字 <code>1</code>。</p></section></section>
<section><h1>三元运算符<a href="#三元运算符"><span>#</span></a></h1><p>三元运算符 <code>? :</code> 是一种根据条件返回不同结果的表达式，可以简化简单的 <code>if...else</code> 判断。</p><section><h2>基本语法<a href="#基本语法-2"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>条件表达式 ? 表达式1 : 表达式2;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li>条件为 <code>true</code>：返回表达式1的结果。</li>
<li>条件为 <code>false</code>：返回表达式2的结果。</li>
</ul><p>示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>age</span><span> </span></span><span>=</span><span> </span><span>18</span><span>;</span></div></div><div><div><div>2</div></div><div><span>let</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span><span> </span><span>age</span><span> </span></span><span>&gt;=</span><span> </span><span>18</span><span> </span><span>?</span><span> </span><span>"成年人"</span><span> </span><span>:</span><span> </span><span>"未成年人"</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>); </span></span><span>// 成年人</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>等价于：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>age</span><span> </span></span><span>=</span><span> </span><span>18</span><span>;</span></div></div><div><div><div>2</div></div><div><span>let</span><span><span> </span><span>result</span><span>;</span></span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>if</span><span><span> (</span><span>age</span><span> </span></span><span>&gt;=</span><span> </span><span>18</span><span>) {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>result</span><span> </span><span>=</span><span> </span><span>"成年人"</span><span>;</span></div></div><div><div><div>6</div></div><div><span>} </span><span>else</span><span> {</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>result</span><span> </span><span>=</span><span> </span><span>"未成年人"</span><span>;</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>嵌套三元运算符<a href="#嵌套三元运算符"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>score</span><span> </span></span><span>=</span><span> </span><span>85</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>let</span><span><span> </span><span>result</span><span> </span></span><span>=</span><span><span> </span><span>score</span><span> </span></span><span>&gt;=</span><span> </span><span>90</span></div></div><div><div><div>4</div></div><div><span>  </span><span>?</span><span> </span><span>"优秀"</span></div></div><div><div><div>5</div></div><div><span>  </span><span>:</span><span><span> </span><span>score</span><span> </span></span><span>&gt;=</span><span> </span><span>60</span></div></div><div><div><div>6</div></div><div><span>    </span><span>?</span><span> </span><span>"及格"</span></div></div><div><div><div>7</div></div><div><span>    </span><span>:</span><span> </span><span>"不及格"</span><span>;</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>result</span><span>); </span></span><span>// 及格</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>虽然三元运算符支持嵌套，但复杂条件推荐使用 <code>if...else</code>，可读性更好。</p></section></section>
<section><h1>for 循环语句<a href="#for-循环语句"><span>#</span></a></h1><p><code>for</code> 循环适合循环次数已知或可以明确控制的场景。</p><section><h2>基本语法<a href="#基本语法-3"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span><span> (</span><span>初始化表达式</span><span>; </span><span>条件表达式</span><span>; </span><span>更新表达式</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>// 循环执行的代码</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>使用示例<a href="#使用示例"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>let</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>1</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;=</span><span> </span><span>5</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>i</span><span>);</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>输出：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>1</span></div></div><div><div><div>2</div></div><div><span>2</span></div></div><div><div><div>3</div></div><div><span>3</span></div></div><div><div><div>4</div></div><div><span>4</span></div></div><div><div><div>5</div></div><div><span>5</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>执行过程：</p>

<table><thead><tr><th>循环</th><th><code>i</code> 的值</th><th>条件 <code>i &lt;= 5</code></th><th>结果</th></tr></thead><tbody><tr><td>第1次</td><td>1</td><td>true</td><td>输出1</td></tr><tr><td>第2次</td><td>2</td><td>true</td><td>输出2</td></tr><tr><td>第3次</td><td>3</td><td>true</td><td>输出3</td></tr><tr><td>第4次</td><td>4</td><td>true</td><td>输出4</td></tr><tr><td>第5次</td><td>5</td><td>true</td><td>输出5</td></tr><tr><td>第6次</td><td>6</td><td>false</td><td>结束循环</td></tr></tbody></table></section><section><h2>遍历数组<a href="#遍历数组"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>arr</span><span> </span><span>=</span><span> [</span><span>"HTML"</span><span>, </span><span>"CSS"</span><span>, </span><span>"JavaScript"</span><span>];</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>for</span><span> (</span><span>let</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>arr</span><span>.</span></span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>arr</span><span>[</span><span>i</span><span>]);</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>输出：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>HTML</span></div></div><div><div><div>2</div></div><div><span>CSS</span></div></div><div><div><div>3</div></div><div><span>JavaScript</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h1>while 循环语句<a href="#while-循环语句"><span>#</span></a></h1><p><code>while</code> 循环会先判断条件，条件成立才执行循环体。</p><p>通常适用于循环次数不确定，需要根据条件决定是否继续执行的场景。</p><section><h2>基本语法<a href="#基本语法-4"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>while</span><span><span> (</span><span>条件表达式</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>// 条件成立时重复执行</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>使用示例<a href="#使用示例-1"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>while</span><span><span> (</span><span>i</span><span> </span></span><span>&lt;=</span><span> </span><span>5</span><span>) {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>i</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>i</span><span>++</span><span>;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>输出：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>1</span></div></div><div><div><div>2</div></div><div><span>2</span></div></div><div><div><div>3</div></div><div><span>3</span></div></div><div><div><div>4</div></div><div><span>4</span></div></div><div><div><div>5</div></div><div><span>5</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意：</p><ul>
<li>先判断条件，再执行循环体。</li>
<li>如果第一次判断条件不成立，则一次都不会执行。</li>
<li>要确保循环条件最终能够变为 <code>false</code>，避免死循环。</li>
</ul><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>while</span><span><span> (</span><span>i</span><span> </span></span><span>&lt;</span><span> </span><span>5</span><span>) {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>i</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>因为条件一开始就不成立，所以不会输出任何内容。</p></section></section>
<section><h1>do…while 循环语句<a href="#dowhile-循环语句"><span>#</span></a></h1><p><code>do...while</code> 与 <code>while</code> 类似，但它会先执行一次循环体，再判断条件。</p><section><h2>基本语法<a href="#基本语法-5"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>do {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>// 循环体</span></div></div><div><div><div>3</div></div><div><span>} while (条件表达式);</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>使用示例<a href="#使用示例-2"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>1</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>do</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>i</span><span>);</span></span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>i</span><span>++</span><span>;</span></div></div><div><div><div>6</div></div><div><span>} </span><span>while</span><span><span> (</span><span>i</span><span> </span></span><span>&lt;=</span><span> </span><span>5</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>输出：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>1</span></div></div><div><div><div>2</div></div><div><span>2</span></div></div><div><div><div>3</div></div><div><span>3</span></div></div><div><div><div>4</div></div><div><span>4</span></div></div><div><div><div>5</div></div><div><span>5</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>与 while 的区别<a href="#与-while-的区别"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// while</span></div></div><div><div><div>2</div></div><div><span>let</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>while</span><span><span> (</span><span>a</span><span> </span></span><span>&lt;</span><span> </span><span>5</span><span>) {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"while执行"</span><span>);</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>// do...while</span></div></div><div><div><div>9</div></div><div><span>let</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>do</span><span> {</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"do...while执行"</span><span>);</span></div></div><div><div><div>13</div></div><div><span>} </span><span>while</span><span><span> (</span><span>b</span><span> </span></span><span>&lt;</span><span> </span><span>5</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>结果：</p><ul>
<li><code>while</code>：不会执行。</li>
<li><code>do...while</code>：执行一次。</li>
</ul></section></section>
<section><h1>循环控制语句 break 和 continue<a href="#循环控制语句-break-和-continue"><span>#</span></a></h1><p>这两个关键字可以用于 <code>for</code>、<code>while</code> 和 <code>do...while</code> 循环。</p><section><h2>break 结束循环<a href="#break-结束循环"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>let</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>1</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;=</span><span> </span><span>5</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>if</span><span><span> (</span><span>i</span><span> </span></span><span>===</span><span> </span><span>3</span><span>) {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>break</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>i</span><span>);</span></span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>输出：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>1</span></div></div><div><div><div>2</div></div><div><span>2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>当 <code>i === 3</code> 时，直接结束整个循环。</p></section><section><h2>continue 跳过本次循环<a href="#continue-跳过本次循环"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> (</span><span>let</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>1</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;=</span><span> </span><span>5</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>if</span><span><span> (</span><span>i</span><span> </span></span><span>===</span><span> </span><span>3</span><span>) {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>continue</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>i</span><span>);</span></span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>输出：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>1</span></div></div><div><div><div>2</div></div><div><span>2</span></div></div><div><div><div>3</div></div><div><span>4</span></div></div><div><div><div>4</div></div><div><span>5</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>当 <code>i === 3</code> 时，跳过本次循环剩余的代码，继续下一轮。</p></section></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026101805javascript-biao-da-shi-yu-cao-zuo-fu/</id>
      <title type="text">JavaScript表达式与操作符</title>
      <published>2026-10-18T07:24:01.000Z</published>
      <updated>2026-10-18T07:24:01.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026101805javascript-biao-da-shi-yu-cao-zuo-fu/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h2>什么是表达式和运算符<a href="#什么是表达式和运算符"><span>#</span></a></h2><ul>
<li>例如：5 + 3就是一个表达式，5和3是操作数，+是运算符；</li>
<li>表达式种类有：算术、关系、逻辑、赋值和综合表达式</li>
</ul></section>
<section><h2>算术表达式<a href="#算术表达式"><span>#</span></a></h2><p><strong>算术运算符</strong></p>

<table><thead><tr><th>意义</th><th>运算符</th></tr></thead><tbody><tr><td>加</td><td>+</td></tr><tr><td>减</td><td>-</td></tr><tr><td>乘</td><td>*</td></tr><tr><td>除</td><td>/</td></tr><tr><td>取余</td><td>%</td></tr></tbody></table><p><strong>加减乘除</strong>加减的符号和数学一致，乘法是*号，除法是/号  默认情况，乘除法的优先级要高于加法和减法；必要时 可以使用圆括号来改变运算的顺序</p><p><strong>加号的两种作用</strong></p><ul>
<li>
<p>加号有“加法”和“连字符”两种作用</p>
</li>
<li>
<p>如果加号两边的操作数都是数字，则为“加法”，否则 为连字符</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>1 + 2 // 3</span></div></div><div><div><div>2</div></div><div><span>1 + '2'; // '12'</span></div></div><div><div><div>3</div></div><div><span>'1' + '2'; // '12'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>取余运算</strong></p><ul>
<li>
<p>取余运算也叫作“求模运算”，用百分号“%”表示</p>
</li>
<li>
<p>a % b表示求a除以b的余数，它不关心整数部分，只关 心余数</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>11 % 4; //3，因为11除以4余数是3</span></div></div><div><div><div>2</div></div><div><span>20 % 6; //2，因为20除以6余数是2</span></div></div><div><div><div>3</div></div><div><span>12 % 3; //0，因为能够整除，余数是0</span></div></div><div><div><div>4</div></div><div><span>9 % 3; //0，因为能够整除，余数是0</span></div></div><div><div><div>5</div></div><div><span>3 % 9; //3，因为商0，余数是3</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>隐式类型转换</strong></p><ul>
<li>
<p>如果参与数学运算的某操作数不是数字型，那么JavaScript 会自动将此操作数转换为数字型</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>3 * '4' //12</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>隐式转换的本质是内部调用Number()函数</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>true + true //2</span></div></div><div><div><div>2</div></div><div><span>false + 2 //2</span></div></div><div><div><div>3</div></div><div><span>3 * '2天' //NaN</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>有关IEEE754</strong></p><ul>
<li>
<p>在JavaScript中，有些小数的数学运算不是很精准</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>0.1 + 0.2 // 0.30000000000000004</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>JavaScript使用了IEEE754二进制浮点数算术标准，这会使 一些个别的小数运算产生“丢失精度”问题</p>
</li>
<li>
<p>解决办法：在进行小数运算时，要调用数字的toFixed()方法 保留指定的小数位数</p>
</li>
</ul><p><strong>幂和开根号</strong></p><ul>
<li>
<p>JavaScript中没有提供幂计算、开根号的运算符。需要使用 Math对象的相关方法进行计算。</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Math.pow(2, 3) // 8</span></div></div><div><div><div>2</div></div><div><span>Math.pow(3, 2) // 9</span></div></div><div><div><div>3</div></div><div><span>Math.sqrt(81) // 9</span></div></div><div><div><div>4</div></div><div><span>Math.sqrt(-81) // NaN</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>向上取整和向下取整</strong></p><ul>
<li>
<p>Math.ceil() 向上取整； Math.floor()向下取整</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Math.ceil(2.4) // 3</span></div></div><div><div><div>2</div></div><div><span>Math.floor(2.4) // 2</span></div></div><div><div><div>3</div></div><div><span>Math.ceil(-2.4) // -2</span></div></div><div><div><div>4</div></div><div><span>Math.floor(-2.4) // -3</span></div></div><div><div><div>5</div></div><div><span>Math.ceil(2) // 2</span></div></div><div><div><div>6</div></div><div><span>Math.floor(2) // 2</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h2>关系表达式<a href="#关系表达式"><span>#</span></a></h2><p><strong>关系运算符</strong></p>

<table><thead><tr><th>意义</th><th>运算符</th></tr></thead><tbody><tr><td>大于</td><td>&gt;</td></tr><tr><td>小于</td><td>&lt;</td></tr><tr><td>大于或等于</td><td>&gt;=</td></tr><tr><td>小于或等于</td><td>&lt;=</td></tr><tr><td>等于</td><td>==</td></tr><tr><td>不等于</td><td>!=</td></tr><tr><td>全等于</td><td>===</td></tr><tr><td>不全等于</td><td>!==</td></tr></tbody></table><p><strong>大于和小于</strong></p><ul>
<li>
<p>大于&gt;、小于&lt;两个符号和数学相同</p>
</li>
<li>
<p>“大于等于”运算符是&gt;= ，“小于等于”运算符是&lt;=</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>8 &gt; 5 // true</span></div></div><div><div><div>2</div></div><div><span>7 &lt; 4 // false</span></div></div><div><div><div>3</div></div><div><span>8 &gt;= 7 // true</span></div></div><div><div><div>4</div></div><div><span>8 &gt;= 8 // true</span></div></div><div><div><div>5</div></div><div><span>8 &lt;= 8 // true</span></div></div><div><div><div>6</div></div><div><span>8 &lt;= 11 // true</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>判断是否相等</strong></p><ul>
<li>
<p>如果想比较两个值是否相等，此时应该使用==运算符</p>
</li>
<li>
<p>JavaScript中等号=表示赋值，而并不是相等。判断相等应 该使用==运算符</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>3 == 3 // true</span></div></div><div><div><div>2</div></div><div><span>3 === 3 // true</span></div></div><div><div><div>3</div></div><div><span>3 = 3 // 错误语句</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>相等和全等</strong></p><ul>
<li>
<p>两个等号==运算符不比较值的类型，它会进行隐式转换后 比较值是否相等</p>
</li>
<li>
<p>三个等号===运算符，不仅比较值是否相同，也比较类型 是否相同</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>5 == '5'; // true</span></div></div><div><div><div>2</div></div><div><span>5 === '5'; // false</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>示例：</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>1 == true // true</span></div></div><div><div><div>2</div></div><div><span>1 === true // false</span></div></div><div><div><div>3</div></div><div><span>0 == false // true</span></div></div><div><div><div>4</div></div><div><span>0 === false // false</span></div></div><div><div><div>5</div></div><div><span>0 == undefined // false</span></div></div><div><div><div>6</div></div><div><span>0 === undefined // false</span></div></div><div><div><div>7</div></div><div><span>undefined == null // true</span></div></div><div><div><div>8</div></div><div><span>undefined === null // false</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>NaN不自等</strong></p><ul>
<li>
<p>NaN作为一个特殊的数字类型值，它在用==比较的时候也 有特殊的结果</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>NaN == NaN // false</span></div></div><div><div><div>2</div></div><div><span>NaN === NaN // false</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>如何判断某变量值为NaN</strong></p><ul>
<li>
<p>isNaN()函数可以用来判断变量值是否为NaN</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>isNaN(NaN) // true</span></div></div><div><div><div>2</div></div><div><span>isNaN(5) // false</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>但isNaN()也不好用，它的机理是：只要该变量传入 Number()的执行结果是NaN，则isNaN()函数都会得到true</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>isNaN(undefined) // true</span></div></div><div><div><div>2</div></div><div><span>isNaN('3天') // true</span></div></div><div><div><div>3</div></div><div><span>isNaN(null) // false</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>特殊值的相等关系</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>null == undefined // true</span></div></div><div><div><div>2</div></div><div><span>null == 0 // false</span></div></div><div><div><div>3</div></div><div><span>NaN == NaN // false</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>不相等和不全等</strong></p><ul>
<li>
<p>!=表示不相等，!==表示不全等</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>5 != 6 // true</span></div></div><div><div><div>2</div></div><div><span>5 !== 6 // true</span></div></div><div><div><div>3</div></div><div><span>5 !=</span></div></div><div><div><div>4</div></div><div><span>'5' // false</span></div></div><div><div><div>5</div></div><div><span>5 !== '5' // true</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>JS中没有连比</strong></p><ul>
<li>
<p>判断变量a是不是介于3到15之间，应该怎么写呢？</p>
<p>错误示范：</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>3 &lt;= a &lt;= 15</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>正确示范：使用逻辑运算符</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>3 &lt;= a &amp;&amp; a&lt;= 15</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>a 大于等于3 ，并且a小于等于15</p>
</li>
</ul></section>
<section><h2>逻辑表达式<a href="#逻辑表达式"><span>#</span></a></h2><p>逻辑运算符：</p>

<table><thead><tr><th>意义</th><th>运算符</th></tr></thead><tbody><tr><td>非</td><td>!</td></tr><tr><td>与</td><td>&amp;&amp;</td></tr><tr><td>或</td><td>||</td></tr></tbody></table><p><strong>非运算</strong></p><ul>
<li>
<p>!表示“非”，也可以称为“置反运算”</p>
</li>
<li>
<p>!是一个“单目运算符”，只需要一个操作数</p>
</li>
<li>
<p>置反运算的结果一定是布尔值</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>!true // false</span></div></div><div><div><div>2</div></div><div><span>!false // true</span></div></div><div><div><div>3</div></div><div><span>!!true // true</span></div></div><div><div><div>4</div></div><div><span>!0 // true</span></div></div><div><div><div>5</div></div><div><span>!undefined // true</span></div></div><div><div><div>6</div></div><div><span>!'' // true</span></div></div><div><div><div>7</div></div><div><span>!'imooc' // false</span></div></div><div><div><div>8</div></div><div><span>!!0 // false</span></div></div><div><div><div>9</div></div><div><span>!!'' // false</span></div></div><div><div><div>10</div></div><div><span>!!'imooc' // true</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>与运算</strong></p><ul>
<li>
<p>&amp;&amp;表示“并且”，称为“与运算”，口诀：都真才真</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>true &amp;&amp; true // true</span></div></div><div><div><div>2</div></div><div><span>true &amp;&amp; false // false</span></div></div><div><div><div>3</div></div><div><span>false &amp;&amp; true // false</span></div></div><div><div><div>4</div></div><div><span>false &amp;&amp; false // false</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>或运算</strong></p><ul>
<li>
<p>||表示“或者”，称为“或运算”，口诀：有真就真</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>true || true //true</span></div></div><div><div><div>2</div></div><div><span>true || false //true</span></div></div><div><div><div>3</div></div><div><span>false || true //true</span></div></div><div><div><div>4</div></div><div><span>false || false //false</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>短路计算</strong></p><p>思考以下计算会得出什么？</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>3 &amp;&amp; 6</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>3为真，6也为真，&amp;&amp;表示“并且”，称为“与运算”，口诀：都真才真，起到最终决定的是后面的6，所以最终输出6</p><ul>
<li>a &amp;&amp; b运算中：<strong>a真，表达式值为b</strong>；<strong>a假，表达式值为a</strong></li>
</ul><p>再来看看以下例子：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>3 &amp;&amp; 6 // 6</span></div></div><div><div><div>2</div></div><div><span>undefined &amp;&amp; 15 // undefined</span></div></div><div><div><div>3</div></div><div><span>15 &amp;&amp; undefined // undefined</span></div></div><div><div><div>4</div></div><div><span>null &amp;&amp; 2 // null</span></div></div><div><div><div>5</div></div><div><span>'' &amp;&amp; 16 // ''</span></div></div><div><div><div>6</div></div><div><span>NaN &amp;&amp; undefined // NaN</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>那如果换成以下会什么结果</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>3 || 6</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>3为真，不用看后面的6，最终输出3，||表示“或者”，称为“或运算”，口诀：有真就真</p><p>再来看看以下例子：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>3 || 6 // 3</span></div></div><div><div><div>2</div></div><div><span>0 || 6 // 6</span></div></div><div><div><div>3</div></div><div><span>null || undefined // undefined</span></div></div><div><div><div>4</div></div><div><span>'a' || 'b' // 'a'</span></div></div><div><div><div>5</div></div><div><span>NaN || null // null</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li>不需要背诵和记忆规律，遇见题目只需要“现场分析”即 可</li>
</ul><p><strong>逻辑运算顺序</strong></p><ul>
<li>
<p>逻辑运算的优先级是：非 → 与 → 或</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>!true || true // true</span></div></div><div><div><div>2</div></div><div><span>3 &amp;&amp; 4 || 5 &amp;&amp; 6 // 4</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h2>赋值表达式<a href="#赋值表达式"><span>#</span></a></h2><p><strong>赋值运算符</strong></p>

<table><thead><tr><th>意义</th><th>运算符</th></tr></thead><tbody><tr><td>赋值</td><td><code>=</code></td></tr><tr><td>快捷赋值</td><td><code>%=、/=、*=、-=、+=</code></td></tr><tr><td>自增运算</td><td><code>++</code></td></tr><tr><td>自减运算</td><td><code>--</code></td></tr></tbody></table><ul>
<li>JS中，=表示赋值，==判断是否相等（不判断类型），===判 断是否全等</li>
<li>赋值运算符会将等号右边的数值，赋予等号左边的变量</li>
</ul><p><strong>赋值运算也产生值</strong></p><ul>
<li>
<p>赋值运算也产生值，等号后面的值将作为“赋值运算的值”</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>a</span><span>;</span></span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span> </span></span><span>=</span><span> </span><span>4</span><span>); </span><span>// 4</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>这就意味着，可以连续使用赋值运算符</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>a</span><span>, </span><span>b</span><span>, </span><span>c</span><span>;</span></span></div></div><div><div><div>2</div></div><div><span><span>a</span><span> </span></span><span>=</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span><span> </span><span>c</span><span> </span></span><span>=</span><span> </span><span>15</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 15</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>b</span><span>); </span></span><span>// 15</span></div></div><div><div><div>5</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>c</span><span>); </span></span><span>// 15</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>快捷赋值</strong></p><ul>
<li>
<p>快捷赋值运算符表示在原数值基础上进一步进行运算</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>3</span><span>;</span></div></div><div><div><div>2</div></div><div><span><span>a</span><span> </span></span><span>+=</span><span> </span><span>5</span><span>; </span><span>// 等价于a = a + 5</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 8</span></div></div><div><div><div>4</div></div><div><span>var</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span> </span><span>14</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>b</span><span> </span></span><span>/=</span><span> </span><span>2</span><span>; </span><span>// 等价于b = b / 2</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>b</span><span>); </span></span><span>// 7</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>c</span><span> </span></span><span>=</span><span> </span><span>16</span><span>;</span></div></div><div><div><div>2</div></div><div><span><span>c</span><span> </span></span><span>%=</span><span> </span><span>3</span><span>; </span><span>// 等价于c = c % 3</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>c</span><span>); </span></span><span>// 1</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>自增/自减运算符</strong></p><ul>
<li>
<p>++和—是自增/自减运算符，表示在自身基础上加1或减1</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>3</span><span>;</span></div></div><div><div><div>2</div></div><div><span>a</span><span>++</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 4</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>a++和++a的区别</strong></p><ul>
<li>
<p>a++ 先用再加； ++a 先加再用</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>3</span><span>;</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span><span> </span><span>a</span></span><span>++</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>b</span><span>); </span></span><span>// 3</span></div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 4</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>3</span><span>;</span></div></div><div><div><div>7</div></div><div><span>var</span><span><span> </span><span>b</span><span> </span></span><span>=</span><span> </span><span>++</span><span><span>a</span><span>;</span></span></div></div><div><div><div>8</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>b</span><span>); </span></span><span>// 4</span></div></div><div><div><div>9</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>); </span></span><span>// 4</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h2>综合表达式<a href="#综合表达式"><span>#</span></a></h2><p>运算顺序： 非运算 → 数学运算 → 关系运算 → 逻辑运算</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>5</span><span> </span><span>&lt;</span><span> </span><span>3</span><span> </span><span>+</span><span> </span><span>3</span><span> </span><span>// true</span></div></div><div><div><div>2</div></div><div><span>3</span><span> </span><span>&gt;</span><span> </span><span>2</span><span> </span><span>&amp;&amp;</span><span> </span><span>8</span><span> </span><span>&gt;</span><span> </span><span>3</span><span> </span><span>+</span><span> </span><span>4</span><span> </span><span>// true</span></div></div><div><div><div>3</div></div><div><span>3</span><span> </span><span>&gt;</span><span> </span><span>2</span><span> </span><span>&amp;&amp;</span><span> </span><span>8</span><span> </span><span>&gt;</span><span> </span><span>3</span><span> </span><span>+</span><span> </span><span>5</span><span> </span><span>// false</span></div></div><div><div><div>4</div></div><div><span>!</span><span>13</span><span> </span><span>&lt;</span><span> </span><span>5</span><span> </span><span>-</span><span> </span><span>3</span><span> </span><span>// true</span></div></div><div><div><div>5</div></div><div><span>!</span><span>13</span><span> </span><span>&lt;</span><span> </span><span>5</span><span> </span><span>-</span><span> </span><span>5</span><span> </span><span>// false</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>变量的范围表示</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>5</span><span> </span><span>&lt;=</span><span><span> </span><span>a</span><span> </span></span><span>&lt;=</span><span> </span><span>12</span><span>//❌</span></div></div><div><div><div>2</div></div><div><span><span>a</span><span> </span></span><span>&gt;=</span><span> </span><span>5</span><span> </span><span>&amp;&amp;</span><span><span> </span><span>a</span><span> </span></span><span>&lt;=</span><span> </span><span>12</span><span>//✔</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026101803javascript-ji-ben-shu-ju-lei-xing/</id>
      <title type="text">JavaScript基本数据类型</title>
      <published>2026-10-18T07:05:28.000Z</published>
      <updated>2026-10-18T07:05:28.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026101803javascript-ji-ben-shu-ju-lei-xing/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h2>数据类型简介和检测<a href="#数据类型简介和检测"><span>#</span></a></h2><p><strong>JavaScript中两大类数据类型</strong></p><ul>
<li>基本数据类型：Number、String、Boolean、 Undefined和Null</li>
<li>复杂数据类型：Object、Array、Function、 RegExp、Date、Map、Set、 Symbol等等</li>
</ul><p><strong>typeof运算符</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>typeof</span><span> </span><span>5</span><span>; </span><span>// number</span></div></div><div><div><div>2</div></div><div><span>typeof</span><span> </span><span>'慕课网'</span><span>; </span><span>// string</span></div></div><div><div><div>3</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>12</span><span>;</span></div></div><div><div><div>4</div></div><div><span>var</span><span><span> </span><span>b</span><span> </span></span><span>=</span></div></div><div><div><div>5</div></div><div><span>'慕课网'</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>typeof</span><span><span> </span><span>a</span><span>); </span></span><span>// number</span></div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span>(</span><span>typeof</span><span><span> </span><span>b</span><span>); </span></span><span>// string</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>5种基本数据类型的typeof检测结果：</p>

<table><thead><tr><th>类型名</th><th>typeof检测结果</th><th>值举例</th></tr></thead><tbody><tr><td>数字类型</td><td>number</td><td>5</td></tr><tr><td>字符串类型</td><td>string</td><td>‘慕课网’</td></tr><tr><td>布尔类型</td><td>boolean</td><td>true</td></tr><tr><td>undefined类型</td><td>undefined</td><td>undefined</td></tr><tr><td>null类型</td><td>object</td><td>null</td></tr></tbody></table></section>
<section><h2>Number（数字）类型<a href="#number数字类型"><span>#</span></a></h2><ul>
<li>
<p>所有数字不分大小、不分整浮、不分正负，都是数字类型</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>typeof</span><span> </span><span>925</span><span>; </span><span>//number</span></div></div><div><div><div>2</div></div><div><span>typeof</span><span> </span><span>3.13</span><span>; </span><span>//number</span></div></div><div><div><div>3</div></div><div><span>typeof</span><span> </span><span>-</span><span>6</span><span>; </span><span>//number</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>小数中0可以省略</strong></p><ul>
<li>
<p>介于0和1之间的小数，可以不书写0</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.5</span><span>; </span><span>//0.5</span></div></div><div><div><div>2</div></div><div><span>typeof</span><span> </span><span>.5</span><span>; </span><span>//number</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>科学计数法</strong></p><ul>
<li>
<p>较大数或较小数（绝对值较小）可以写成科学计数法</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>3e8</span><span>; </span><span>//300000000</span></div></div><div><div><div>2</div></div><div><span>typeof</span><span> </span><span>3e8</span><span>; </span><span>//number</span></div></div><div><div><div>3</div></div><div><span>3e-4</span><span>; </span><span>//0.0003</span></div></div><div><div><div>4</div></div><div><span>typeof</span><span> </span><span>3e-8</span><span>; </span><span>//number</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>不同进制的数字</strong></p><ul>
<li>
<p>二进制数值以0b开头</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>0b10</span><span> </span><span>// 2</span></div></div><div><div><div>2</div></div><div><span>0b1111</span><span> </span><span>// 15</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>八进制数值以0开头</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>017 // 15</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>十六进制数字以0x开头</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>0xf // 15</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>一个特殊的数字型值NaN</strong></p><ul>
<li>
<p>NaN是英语“not a number”的意思，即“不是一个数”，但它 是一个数字类型的值</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>typeof NaN; //number</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>0除以0的结果是NaN，事实上，在数学运算中，若结果不能得到数 字，其结果往往都是NaN</p>
</li>
<li>
<p>NaN有一个“奇怪”的性质：不自等。这个知识点将在后续课程中 讲解</p>
</li>
</ul></section>
<section><h2>String（字符串）类型<a href="#string字符串类型"><span>#</span></a></h2><ul>
<li>
<p>字符串就是“人类的自然语言”</p>
</li>
<li>
<p>字符串要用引号包裹，双引号或者单引号均可</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>typeof</span><span> </span><span>"慕课网"</span><span>; </span><span>// string</span></div></div><div><div><div>2</div></div><div><span>typeof</span><span> </span><span>'慕课网'</span><span>; </span><span>// string</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>分清数字和字符串</strong></p><ul>
<li>
<p>数字11和字符串’11’在语义上是不同的，前者表达一个数量， 后者是一个文本</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>typeof</span><span> </span><span>11</span><span>; </span><span>//number</span></div></div><div><div><div>2</div></div><div><span>typeof</span><span> </span><span>'11'</span><span>; </span><span>//string</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>字符串的拼接</strong></p><ul>
<li>
<p>加号可以用来拼接多个字符串</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'imo'</span><span> </span><span>+</span><span> </span><span>'oc'</span><span> </span><span>// 'immoc'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>字符串和变量的拼接</strong></p><ul>
<li>
<p>要将一个变量的值“插入”到字符串中，要“斩断链接”</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>year</span><span> </span></span><span>=</span><span> </span><span>2022</span><span>;</span></div></div><div><div><div>2</div></div><div><span>var</span><span><span> </span><span>str</span><span> </span></span><span>=</span><span>'北京冬季奥运会在'</span><span> </span><span>+</span><span><span> </span><span>year</span><span> </span></span><span>+</span><span> </span><span>'年召开'</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>新版ES中增加了反引号表示法，可以更方便进行变量插值，后续 将进行介绍</p>
</li>
</ul><p><strong>空字符串</strong></p><ul>
<li>
<p>一些时候需要使用空字符串，直接书写闭合的引号对即可</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>str</span><span> </span></span><span>=</span><span>''</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>字符串的length属性</strong></p><ul>
<li>
<p>字符串的length 属性表示字符串的长度</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS'</span><span>.</span><span>length</span><span> </span><span>// 5</span></div></div><div><div><div>2</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>length</span><span> </span><span>// 14</span></div></div><div><div><div>3</div></div><div><span>''</span><span>.</span><span>length</span><span> </span><span>// 0</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>字符串的常用方法</strong></p><ul>
<li>
<p>“方法”就是能够打点调用的函数，字符串有丰富的方法</p>

<table><thead><tr><th>方法</th><th>功能</th></tr></thead><tbody><tr><td><code>charAt()</code></td><td>得到指定位置的字符</td></tr><tr><td><code>substring()</code></td><td>提取子串</td></tr><tr><td><code>substr()</code></td><td>提取子串</td></tr><tr><td><code>slice()</code></td><td>提取子串</td></tr><tr><td><code>toUpperCase()</code></td><td>将字符串转换为大写</td></tr><tr><td><code>toLowerCase()</code></td><td>将字符串转换为小写</td></tr><tr><td><code>indexOf()</code></td><td>检索字符串，返回指定内容首次出现的位置</td></tr></tbody></table>
</li>
</ul><p><strong>charAt()方法</strong></p><ul>
<li>
<p>charAt()方法可以得到指定位置的字符</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>charAt</span><span>(</span><span>0</span><span>) </span><span>// '我'</span></div></div><div><div><div>2</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>charAt</span><span>(</span><span>11</span><span>) </span><span>// 'T'</span></div></div><div><div><div>3</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>charAt</span><span>(</span><span>74</span><span>) </span><span>// ''</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>substring()、substr()和slice()</strong></p><ul>
<li>
<p>substring(a, b) 方法得到从a开始到b结束（不包括b处）的子串</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>substring</span><span>(</span><span>3</span><span>, </span><span>5</span><span>) </span><span>// 'JS'</span></div></div><div><div><div>2</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>substring</span><span>(</span><span>10</span><span>, </span><span>14</span><span>) </span><span>// 'HTML'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>substring(a, b) 方法如果省略第二个参数，返回的子串会一直到字符串 的结尾</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>substring</span><span>(</span><span>6</span><span>) </span><span>// '我也喜欢HTML'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>substring(a, b) 中，a可以大于b，数字顺序将自动调整为小数在前</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>substring</span><span>(</span><span>5</span><span>, </span><span>3</span><span>) </span><span>// 'JS'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>substr (a, b)中，将得到从a开始的长度为b的子串</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>substr</span><span>(</span><span>3</span><span>, </span><span>2</span><span>) </span><span>// 'JS'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>substr(a, b)中，b可以省略，表示到字符串结尾</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>substr</span><span>(</span><span>3</span><span>) </span><span>// 'JS，我也喜欢HTML</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>substr (a, b)中，a可以是负数，表示倒数位置</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>substr</span><span>(</span><span>-</span><span>4</span><span>, </span><span>2</span><span>) </span><span>// HT'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>slice(a, b)方法得到从a开始到b结束（不包括b处）的子串</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>slice</span><span>(</span><span>3</span><span>, </span><span>5</span><span>) </span><span>// 'JS'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>slice(a, b)的参数a可以是负数</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>slice</span><span>(</span><span>-</span><span>4</span><span>, </span><span>-</span><span>1</span><span>) </span><span>// 'HTM'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>slice(a, b)中，参数a必须小于参数b</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'我喜欢JS，我也喜欢HTML'</span><span>.</span><span>slice</span><span>(</span><span>5</span><span>, </span><span>2</span><span>) </span><span>// ''</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>对比总结</strong></p><ul>
<li>
<p>substring(a, b)和slice(a, b)功能基本一致，都是得到从a开始到b 结束（不包括b）的子串，区别：</p>
<p>① substring()可以自动交换两个参数位置，而slice()不行；</p>
<p>②slice()的参数a可以是负数，而substring()不行。</p>
</li>
<li>
<p>substr(a, b)中参数b是子串长度，而不是位置编号</p>
</li>
</ul><p><strong>toUpperCase()和toLowerCase()</strong></p><ul>
<li>
<p>toUpperCase() 转为大写</p>
</li>
<li>
<p>toLowerCase() 转为小写</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'i love you'</span><span>.</span><span>toUpperCase</span><span>(); </span><span>// 'I LOVE YOU'</span></div></div><div><div><div>2</div></div><div><span>'IMOOC'</span><span>.</span><span>toLowerCase</span><span>(); </span><span>// 'imooc'</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>indexOf()</strong></p><ul>
<li>
<p>indexOf()方法返回某个指定的字符串值在字符串中首次出现的位置</p>
</li>
<li>
<p>如果要检索的字符串值没有出现，则该返回 -1</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>'abcdeb'</span><span>.</span><span>indexOf</span><span>(</span><span>'b'</span><span>) </span><span>// 1</span></div></div><div><div><div>2</div></div><div><span>'abcdeb'</span><span>.</span><span>indexOf</span><span>(</span><span>'de'</span><span>) </span><span>// 3</span></div></div><div><div><div>3</div></div><div><span>'abcdeb'</span><span>.</span><span>indexOf</span><span>(</span><span>'m'</span><span>) </span><span>// -1</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h2>Boolean（布尔）类型<a href="#boolean布尔类型"><span>#</span></a></h2><ul>
<li>
<p>布尔（Boole·George）英国19世纪数学家及逻 辑学家。</p>
</li>
<li>
<p>布尔型值只有两个：true和false，分别表示真和 假</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>typeof true; //boolean</span></div></div><div><div><div>2</div></div><div><span>typeof false; //boolean</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h2>Undefined类型<a href="#undefined类型"><span>#</span></a></h2><p><strong>undefined是什么</strong></p><ul>
<li>
<p>一个没有被赋值的变量的默认值是undefined，而undefined 的类型也是undefined</p>
</li>
<li>
<p>即：undefined又是值，又是一种类型，这种类型只有它自己 一个值</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>typeof undefined; //undefined</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>变量声明提升的情况</strong></p><ul>
<li>在变量声明提升时，变量的值也是undefined。</li>
</ul></section>
<section><h2>Null类型<a href="#null类型"><span>#</span></a></h2><p><strong>null类型是什么</strong></p><ul>
<li>null表示“空”，它是“空对象”</li>
<li>当我们需要将对象销毁、数组销毁或者删除事件监听时，通常将 它们设置为null。</li>
</ul><p><strong>用typeof检测null结果是object</strong></p><ul>
<li>使用typeof检测null值，结果是object，这点尤其要注意</li>
<li>类型和typeof检测结果并不总是一一对应，比如数组用 typeof检测结果也是object</li>
</ul></section>
<section><h2>数据类型转换<a href="#数据类型转换"><span>#</span></a></h2><p><strong>其他值 → 数字</strong></p><p>使用Number()函数：</p><p>字符串 → 数字：纯数字字符串能变为数字，不 是纯数字的字符串将转为NaN</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Number('123'); // 123</span></div></div><div><div><div>2</div></div><div><span>Number('123.4'); // 123.4</span></div></div><div><div><div>3</div></div><div><span>Number('123年'); // NaN</span></div></div><div><div><div>4</div></div><div><span>Number('2e3'); // 2000</span></div></div><div><div><div>5</div></div><div><span>Number(''); // 0</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>布尔值 → 数字：true变为1，false变为0</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Number(true); // 1</span></div></div><div><div><div>2</div></div><div><span>Number(false); //</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>undefined和null → 数字：undefined变为NaN null变为0</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Number(undefined); // NaN</span></div></div><div><div><div>2</div></div><div><span>Number(null); // 0</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>使用parseInt() 函数：</p><p>parseInt()函数的功能是将字符串转为整数</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>parseInt('3.14'); // 3  parseInt()将自动截掉第一个非数字字符之后的所有字符</span></div></div><div><div><div>2</div></div><div><span>parseInt('3.14是圆周率'); // 3 所有文字都将被截掉</span></div></div><div><div><div>3</div></div><div><span>parseInt('圆周率是3.14'); // NaN  如果字符串不是以数字开头，则转为NaN</span></div></div><div><div><div>4</div></div><div><span>parseInt('3.99'); // 3 parseInt()函数不四舍五入</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>使用parseFloat() 函数</p><p>parseFloat()函数的功能是将字符串转为浮点数</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>parseFloat('3.14'); // 3.14 parseFloat()可以将小数字符串转为数字小数</span></div></div><div><div><div>2</div></div><div><span>parseFloat('3.14是圆周率'); // 3.14 parseFloat()将自动截掉第一个非数字字符、非小数点之后的所有字符</span></div></div><div><div><div>3</div></div><div><span>parseFloat('圆周率是3.14'); // NaN  如果字符串并不是以数字开头，则转为NaN</span></div></div><div><div><div>4</div></div><div><span>parseFloat('3.99'); // 3.99  不四舍五入</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>其他值 → 字符串</strong></p><p>使用String()函数：</p><p>数字 → 字符串：变为“长得相同”的字符串。 科学计数法和非10进制数字会 转为10进制的值。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>String(123); // '123'</span></div></div><div><div><div>2</div></div><div><span>String(123.4); // '123.4'</span></div></div><div><div><div>3</div></div><div><span>String(2e3); // '2000'</span></div></div><div><div><div>4</div></div><div><span>String(NaN); // 'NaN'</span></div></div><div><div><div>5</div></div><div><span>String(Infinity); // 'Infinity'</span></div></div><div><div><div>6</div></div><div><span>String(0xf); // '15'</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>布尔值 → 字符串：变为“长得相同”的字符串</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>String(true); // 'true'</span></div></div><div><div><div>2</div></div><div><span>String(false); // 'false'</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>undefined和null → 字符串：变为“长得相同”的字符串</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>String(undefined); // 'undefined'</span></div></div><div><div><div>2</div></div><div><span>String(null); // 'null'</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>使用toString()方法：</p><p>几乎所有值都有toString()方法，功能是将值转为字符串</p><p><strong>其他值 → 布尔值</strong></p><p>使用Boolean ()函数</p><p>数字 → 布尔值：0和NaN转为false，其他数字 都转为true</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Boolean(123); // true</span></div></div><div><div><div>2</div></div><div><span>Boolean(0); // false</span></div></div><div><div><div>3</div></div><div><span>Boolean(NaN); // false</span></div></div><div><div><div>4</div></div><div><span>Boolean(Infinity); // true</span></div></div><div><div><div>5</div></div><div><span>Boolean(-Infinity); // true</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>布尔值 → 布尔值：空字符串变为false，其他都转 为true</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Boolean(''); // false</span></div></div><div><div><div>2</div></div><div><span>Boolean('abc'); // true</span></div></div><div><div><div>3</div></div><div><span>Boolean('false'); // true</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>undefined和null → 布尔值：转为false</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Boolean(undefined); // false</span></div></div><div><div><div>2</div></div><div><span>Boolean(null); // false</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026101802-sui-bi-gan-wu/</id>
      <title type="text">10月18日随笔感悟</title>
      <published>2026-10-18T02:54:31.000Z</published>
      <updated>2026-10-18T02:54:31.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026101802-sui-bi-gan-wu/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>记录一下最近的一些小感悟：</p>
<p>学习编程基础真的就是在学习语数英、历史、地理、物理、化学、政治、生物 九大课程一样，枯燥，重点在于内容特别多，记不住，一个小知识块能理解，但是过几天又会忘记，又得重新看；</p>
<p>而做项目就好比一场考试，把各种知识串联起来，但是前面说了，基础内容特别多记不住，又得看一下之前的，项目还有一点，必须建立一个工程思维，否则很难做好；</p>
<p>基于以上2点：基础依然需要巩固，但是项目应该从小项目Demo开始，通过Demo项目来串联知识点，对大项目也有一定帮助，起到一个承上启下的作用；</p>
<p>但是大项目这里需要注意，应该做有用的，能商业化的东西了，如之前的社区应用，使用vue3和koa实现起来基本完整，但是没有什么用，pc端网页端几乎已经淘汰，并且koa这个选型不太好。</p>
<p>这几天想做一个首页官网，然后再写一些产品，现在这个想法不太可靠，应该写一些闭环的产品，然后再去考虑首页官网，这样的首页官网才不会空洞，那闭环的产品也就是上面说的做有用的，能商业化的东西，而技术栈也选当下流行的Vue3+NestJs，再使用AI辅助，但是第一个或者前几个闭环产品不应该使用AI，只有自己能非常熟悉开发流程让AI介入，感觉才能事半功倍。</p>
<p>完…</p>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026101801javascript-ji-chu-yu-fa-yu-bian-liang/</id>
      <title type="text">Javascript基础语法与变量</title>
      <published>2026-10-18T02:07:31.000Z</published>
      <updated>2026-10-18T02:07:31.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026101801javascript-ji-chu-yu-fa-yu-bian-liang/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>前言<a href="#前言"><span>#</span></a></h1><p>基础的HTML和CSS已经学完，接下进入JavaScript的知识学习，大致可以分为JavaScript的核心语法、DOM、BOM、ES6语法这4大模块，其中核心语法和ES6是重点，至于DOM、BOM这两个，目前有像Vue和React的框架，可以不用深入过度学习，除非想做类似框架，除此之外还有移动端的事件，TypeScript这两个，TypeScript是重点，尤其是在使用Vue3、NestJS大量使用，</p></section>
<section><h1>初识JavaScript<a href="#初识javascript"><span>#</span></a></h1><p><strong>前端三层</strong></p>

<table><thead><tr><th></th><th>语言</th><th>功能</th></tr></thead><tbody><tr><td>结构层</td><td>HTML</td><td>搭建结构、放置部件、描述语义</td></tr><tr><td>样式层</td><td>CSS</td><td>美化页面、实现布局</td></tr><tr><td>行为层</td><td>JavaScript</td><td>实现交互效果、数据收发、表单验证等</td></tr></tbody></table><p><strong>JavaScript的历史</strong></p><ul>
<li>创始人：Brendan Eich（布兰登·艾奇）</li>
<li>netscape公司 1995年发明JavaScript，前身LiveScrip</li>
<li>JavaScript跟java没有关系，只是为了蹭java的热度</li>
</ul><p><strong>JavaScript垄断了浏览器端脚本</strong></p><ul>
<li>在JavaScript之前，还有VBScript、JScript脚本语言，但是随之时间推移，后两者都被淘汰</li>
</ul><p><strong>什么是前端语言和后端语言</strong></p><ul>
<li>前端页面用前端语言，数据处理需要使用后端语言</li>
<li>像HTML、CSS、JavaScript属于前端语言，java、php、python、nodejs属于后端</li>
<li>JavaScript属于前后端语言，既可以写前端也可以写后端</li>
</ul><p><strong>ECMAScript是JavaScript的标准</strong></p><ul>
<li>1997年，欧洲计算机制造商协会（ECMA）设置了 JavaScript的标准，命名为ECMAScript</li>
<li>JavaScript实现了ECMAScript，ECMAScript规范了JavaScript</li>
</ul><p><strong>JavaScript体系</strong></p><ul>
<li>语言核心：ES5、ES6、ES7……</li>
<li>DOM</li>
<li>BOM</li>
</ul><p>JS<strong>的书写位置</strong></p><ul>
<li>在body中script标签，在内部书写JavaScript代码</li>
<li>将代码单独保存为.js格式文件，然后在HTML文件中引入 它</li>
</ul><p><strong>认识输出语句</strong></p><ul>
<li>alert()语句 - 弹出警告框</li>
<li>console.log()语句 - 控制台输出</li>
</ul><p><strong>学会处理报错</strong></p><ul>
<li>
<p>alert(‘慕课网’)； 不小心写成了中文分号</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Uncaught SyntaxError: Invalid or unexpected token;//未捕获的语法错误：不合法或错误的符号</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>alert(慕课网); 忘记用引号包裹</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Uncaught ReferenceError: 慕课网 is not defined;//未捕获的引用错误：慕课网没有被定义</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>alret(慕课网); 错误拼写alert</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Uncaught ReferenceError: alret is not defined;//未捕获的引用错误：alret没有被定义</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>REPL环境</strong></p><p>read读-&gt;eval执行-&gt;print打印-&gt;loop循环-&gt;read读-&gt;eval执行-&gt;print打印-&gt;loop循环-&gt;</p></section>
<section><h1>变量<a href="#变量"><span>#</span></a></h1><p><strong>变量是什么</strong></p><ul>
<li>变量是在内存中存储值的符号</li>
<li>变量不是数值本身，它们仅仅是一个用于存储数值的容器</li>
</ul><p><strong>定义变量</strong></p><ul>
<li>
<p>要想使用变量，第一步就是声明它，并给它赋值</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var a = 5;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>变量的使用</strong></p><ul>
<li>
<p>变量被赋值后，就可以使用它了；变量使用时不 能使用引号</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>console.log(a);</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>变量的默认值</strong></p><ul>
<li>
<p>一个变量只定义，但没有赋初值，默认值是undefined</p>
</li>
<li>
<p>一个变量只有被var定义，并赋初值之后，才算正式初始 化完成</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var a = 10;</span></div></div><div><div><div>2</div></div><div><span>console.log(a); // undefined</span></div></div><div><div><div>3</div></div><div><span>a = 10;</span></div></div><div><div><div>4</div></div><div><span>console.log(a); // 10</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>变量的常见错误</strong></p><ul>
<li>
<p>不用var定义，而直接将值赋予它，虽不引发报错，但会 产生作用域问题。</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>a = 10;</span></div></div><div><div><div>2</div></div><div><span>console.log(a); // 10；定义变量时必须写var</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>尝试使用一个既没有被var定义过，也没有赋过值的字符， 就会产生引用错误。</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>console.log(b);// Reference Error；变量必须先赋值再使用</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>变量的合法命名</strong></p><ul>
<li>只能由字母、数字、下划线、$组 成，但不能以数字开头</li>
<li>不能是关键字或保留字</li>
<li>大小写敏感，a和A两个不同的变量</li>
<li>函数、类名、对象的属性等 也都要遵守这个命名规则</li>
</ul><p><strong>优秀的变量命名法</strong></p><ul>
<li>驼峰命名法：mathTestScore，不建议的命名：mathtestscore</li>
<li>c风格: math_test_score</li>
<li>匈牙利命名法：iMathTestScore</li>
</ul><p><strong>变量的值</strong></p><ul>
<li>
<p>变量的值可以被改变</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var a = 10;</span></div></div><div><div><div>2</div></div><div><span>a = 18;</span></div></div><div><div><div>3</div></div><div><span>console.log(a); // 18</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>改变变量的值，不需要再次书写var</p>
</li>
</ul><p><strong>JS中的等号</strong></p><ul>
<li>等号表示赋值</li>
</ul><p><strong>变量声明</strong></p><ul>
<li>
<p>使用逗号同时声明和初始化两个变量</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var a = 0, b = 0;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>变量声明提升（重点）</strong></p><ul>
<li>
<p>变量声明的提升：你可以提前使用一个稍后才声明的变量，而不 会引发异常</p>
</li>
<li>
<p>变量声明提升时，<strong>只提升变量的定义，不会提升它的值</strong></p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 先使用变量</span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>);</span></span><span>//输出undefined</span></div></div><div><div><div>3</div></div><div><span>// 后定义变量</span></div></div><div><div><div>4</div></div><div><span>var</span><span><span> </span><span>a</span><span> </span></span><span>=</span><span> </span><span>12</span><span>;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>相当于：</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span><span> </span><span>a</span><span>;</span></span></div></div><div><div><div>2</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>a</span><span>);</span></span><span>//输出undefined</span></div></div><div><div><div>3</div></div><div><span><span>a</span><span> </span></span><span>=</span><span> </span><span>12</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>注意事项</strong></p><ul>
<li>变量声明的提升是JavaScript的特性，所以经常出面试题</li>
<li>在实际开发时，一定要先定义并给变量赋初值，然后再使用变量</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026101701-wang-ge-bu-ju/</id>
      <title type="text">Grid网格布局</title>
      <published>2026-10-17T00:19:04.000Z</published>
      <updated>2026-10-17T00:19:04.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026101701-wang-ge-bu-ju/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>前言<a href="#前言"><span>#</span></a></h1><p>一样的，在学习之前，搞懂一些匪夷所思的概念：</p><p>单元格和项目，学习之初，视频教程都会拿出一张无数常规的网格图片讲网格布局，这当然没问题，但是如果讲到单元格和项目，这时候就懵了，因为教程说的它们是不一样的，但是图片里面表现又一样，其实就是一个先入为主了，因为网格布局最常用的反而不像图片那样一张网格，而是会跨列跨行，所以可以理解单元格是一种虚无的东西，无形的大网，而项目是实实在在的东西，如果它们刚好落在每个单元格，那确实会像单元格=项目，而一般情况下，项目是会跨 单元格的</p><p>网格线、轨道和间距也是一个比较难理解的地方：</p></section>
<section><h1>Grid 基础知识<a href="#grid-基础知识"><span>#</span></a></h1><p>CSS Grid（网格布局）是一种<strong>二维布局系统</strong>，能够同时控制元素在行（Row）和列（Column）两个方向上的排列。</p><p>使用 Grid 布局时，浏览器会建立一套网格结构，再根据布局规则将 HTML 元素放置到网格中。</p><section><h2>Grid 容器和项目<a href="#grid-容器和项目"><span>#</span></a></h2><p>Grid 布局主要包含两个基本对象：</p><ul>
<li><strong>Grid 容器（Container）</strong>：设置了 <code>display: grid</code> 或 <code>display: inline-grid</code> 的元素。</li>
<li><strong>Grid 项目（Item）</strong>：Grid 容器中参与网格布局的直接子元素。</li>
</ul><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"container"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"item"</span><span>&gt;项目1&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"item"</span><span>&gt;项目2&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"item"</span><span>&gt;项目3&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span>.container {</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>grid-template-columns: repeat(3, 100px);</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>gap: 10px;</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>此时 <code>.container</code> 是 Grid 容器，三个 <code>.item</code> 是 Grid 项目，按照网格布局规则排列。</p><p><strong>常见的容器属性和项目属性：</strong></p>

<table><thead><tr><th>容器属性</th><th>项目属性</th></tr></thead><tbody><tr><td><code>grid-template-columns</code></td><td><code>grid-column</code></td></tr><tr><td><code>grid-template-rows</code></td><td><code>grid-row</code></td></tr><tr><td><code>grid-template-areas</code></td><td><code>grid-area</code></td></tr><tr><td><code>gap</code></td><td><code>justify-self</code></td></tr><tr><td><code>justify-items</code></td><td><code>align-self</code></td></tr><tr><td><code>align-items</code></td><td><code>order</code></td></tr></tbody></table><p><strong>注意：容器负责定义和管理网格结构，项目则根据网格规则进行排列。</strong></p></section><section><h2>行、列和单元格<a href="#行列和单元格"><span>#</span></a></h2><p>Grid 会将布局空间划分为行（Row）和列（Column），两者交叉形成单元格（Cell）。</p><ul>
<li><strong>行（Row）</strong>：网格中水平方向的一排空间。</li>
<li><strong>列（Column）</strong>：网格中垂直方向的一列空间。</li>
<li><strong>单元格（Cell）</strong>：一行与一列交叉形成的最小网格空间。</li>
</ul><p>例如，创建一个 2 行 3 列的网格：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: </span><span>grid</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: </span><span><span>100</span><span>px</span></span><span> </span><span><span>200</span><span>px</span></span><span> </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-template-rows: </span><span><span>80</span><span>px</span></span><span> </span><span><span>120</span><span>px</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这段代码定义了：</p><ul>
<li>3 列：宽度分别为 <code>100px</code>、<code>200px</code>、<code>100px</code>。</li>
<li>2 行：高度分别为 <code>80px</code>、<code>120px</code>。</li>
<li>6 个单元格：每行 3 个，共 2 行。</li>
</ul><p>单元格的尺寸由所在行、列的尺寸共同决定：</p>

<table><thead><tr><th>单元格位置</th><th>宽度</th><th>高度</th></tr></thead><tbody><tr><td>第一行第一列</td><td>100px</td><td>80px</td></tr><tr><td>第一行第二列</td><td>200px</td><td>80px</td></tr><tr><td>第一行第三列</td><td>100px</td><td>80px</td></tr><tr><td>第二行第一列</td><td>100px</td><td>120px</td></tr><tr><td>第二行第二列</td><td>200px</td><td>120px</td></tr><tr><td>第二行第三列</td><td>100px</td><td>120px</td></tr></tbody></table><section><h3>单元格与项目的区别<a href="#单元格与项目的区别"><span>#</span></a></h3><p>这是 Grid 布局中非常容易混淆的概念。</p><p><strong>单元格是浏览器划分的布局空间，项目是实际参与布局的 HTML 元素。</strong></p><p>它们之间并不一定是一一对应的关系。</p><p><strong>情况一：一个项目占据一个单元格。</strong></p><p>这是最常见的情况，项目默认自动排列，通常一个项目占据一个单元格。</p><p><strong>情况二：一个项目占据多个单元格。</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>grid-column: 1 / 3;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-row: 1 / 3;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>项目横跨 2 行、2 列，占据 4 个单元格。</p><p>需要注意，<strong>跨行、跨列不会真正合并单元格，只是让项目占据更大的网格区域。</strong></p><p><strong>情况三：存在没有项目的单元格。</strong></p><p>即使没有对应的 HTML 元素，已经建立的网格中仍然可以存在空单元格。</p><p>因此，单元格和项目不能画等号。</p></section></section><section><h2>网格线<a href="#网格线"><span>#</span></a></h2><p>网格线（Grid Line）是用于划分网格和定位项目的参考线。</p><p>网格线分为两种：</p><ul>
<li><strong>列网格线</strong>：垂直方向的参考线，用于划分列。</li>
<li><strong>行网格线</strong>：水平方向的参考线，用于划分行。</li>
</ul><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: repeat(3, 100px);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-template-rows: repeat(2, 80px);</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这会形成：</p>

<table><thead><tr><th>网格结构</th><th>数量</th></tr></thead><tbody><tr><td>行</td><td>2</td></tr><tr><td>列</td><td>3</td></tr><tr><td>行网格线</td><td>3</td></tr><tr><td>列网格线</td><td>4</td></tr><tr><td>单元格</td><td>6</td></tr></tbody></table><p>在普通的显式网格中，<strong>某一方向的网格线数量 = 对应方向的轨道数量 + 1</strong>。</p><section><h3>网格线的作用<a href="#网格线的作用"><span>#</span></a></h3><p>网格线最主要的用途是<strong>确定项目的起始位置和结束位置</strong>，从而实现跨行、跨列布局。</p><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>grid-column: 1 / 3;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-row: 1 / 3;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li><code>grid-column: 1 / 3</code>：从第 1 条列网格线到第 3 条列网格线，横跨 2 列。</li>
<li><code>grid-row: 1 / 3</code>：从第 1 条行网格线到第 3 条行网格线，纵跨 2 行。</li>
</ul><p>也可以使用 <code>span</code> 表示跨越的轨道数量：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>grid-column: span 2;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-row: span 2;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>两种方式的区别：</p><ul>
<li><code>1 / 3</code>：指定起始和结束网格线。</li>
<li><code>span 2</code>：指定跨越 2 条轨道，起始位置可以由自动布局确定。</li>
</ul></section><section><h3>网格线能不能自定义？<a href="#网格线能不能自定义"><span>#</span></a></h3><p>可以为网格线命名：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns:</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>[start] 100px</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>[middle] 200px</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>[end];</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>.item {</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>grid-column: start / end;</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>不过网格线属于抽象的布局参考线，并不是真正显示出来的 CSS 边框，不能直接像 <code>border</code> 一样设置颜色和线条样式。</p></section></section><section><h2>其他（间距、区域、内容、轨道）<a href="#其他间距区域内容轨道"><span>#</span></a></h2><section><h3>1. 间距（Gap）<a href="#1-间距gap"><span>#</span></a></h3><p>间距用于控制相邻行轨道、列轨道之间的距离。</p><p>常见属性：</p>

<table><thead><tr><th>属性</th><th>说明</th></tr></thead><tbody><tr><td><code>row-gap</code></td><td>行轨道之间的间距</td></tr><tr><td><code>column-gap</code></td><td>列轨道之间的间距</td></tr><tr><td><code>gap</code></td><td>两者的简写</td></tr></tbody></table><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: 100px 200px;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-template-rows: 80px 120px;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>gap: 10px 20px;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这里：</p><ul>
<li>行间距：<code>10px</code>。</li>
<li>列间距：<code>20px</code>。</li>
</ul><p><strong>间距到底占不占单元格的空间？</strong></p><p>间距不属于单元格，也不计入普通轨道自身的尺寸。</p><p>但是，间距会占据整个网格中的空间。</p><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: 100px 200px;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>column-gap: 20px;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>显式网格的总宽度为：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>100px + 20px + 200px = 320px</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其中 <code>20px</code> 是额外的轨道间距，两个列轨道仍然分别宽 <code>100px</code> 和 <code>200px</code>。</p><p>如果使用 <code>1fr</code> 等弹性轨道，在空间受限时，浏览器会先考虑间距，再将剩余可分配空间分给弹性轨道。</p><p><strong>间距与网格线的关系</strong></p><p>CSS Grid 规范中，可以将 <code>gap</code> 形象地理解为网格线具有了厚度。</p><p>但要注意：</p><ul>
<li>这只是布局计算层面的理解。</li>
<li>不意味着网格线真的变成了可见的粗线。</li>
<li>也不能认为网格线等于轨道宽度加间距。</li>
</ul></section><section><h3>2. 区域（Area）<a href="#2-区域area"><span>#</span></a></h3><p>网格区域（Grid Area）是由四条网格线限定的矩形空间，可以包含一个或多个单元格。</p><p>可以通过 <code>grid-template-areas</code> 为区域命名：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"container"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>header</span><span> </span><span>class</span><span>=</span><span>"header"</span><span>&gt;头部&lt;/</span><span>header</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>main</span><span> </span><span>class</span><span>=</span><span>"main"</span><span>&gt;主体&lt;/</span><span>main</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>&lt;</span><span>aside</span><span> </span><span>class</span><span>=</span><span>"aside"</span><span>&gt;侧边栏&lt;/</span><span>aside</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span>.container {</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>grid-template-columns: 100px 200px 100px;</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>grid-template-rows: 80px 120px;</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>gap: 10px;</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>grid-template-areas:</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>"header header aside"</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>"main   main   aside";</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>.header {</span></div></div><div><div><div>18</div></div><div><span><span>  </span></span><span>grid-area: header;</span></div></div><div><div><div>19</div></div><div><span>}</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>.main {</span></div></div><div><div><div>22</div></div><div><span><span>  </span></span><span>grid-area: main;</span></div></div><div><div><div>23</div></div><div><span>}</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span>.aside {</span></div></div><div><div><div>26</div></div><div><span><span>  </span></span><span>grid-area: aside;</span></div></div><div><div><div>27</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>这里虽然只有三个项目，但实际上建立了 2 行 3 列，共 6 个单元格。</p><ul>
<li><code>header</code>：占据第一行的前两个单元格。</li>
<li><code>main</code>：占据第二行的前两个单元格。</li>
<li><code>aside</code>：占据第三列的两个单元格。</li>
</ul><p>注意：</p><p><strong>区域并不一定要通过</strong> <code>**grid-template-areas**</code> <strong>命名。</strong></p><p>通过 <code>grid-column</code> 和 <code>grid-row</code> 指定的矩形范围，同样是网格区域。</p><p>单元格可以理解为最小的网格区域，而更大的区域则可以包含多个单元格及它们之间的间距。</p></section><section><h3>3. 内容（Content）<a href="#3-内容content"><span>#</span></a></h3><p>内容通常指项目内部的文字、图片、按钮等实际内容，而不是另一种网格结构。</p><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;div class="container"&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;div class="item"&gt;</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>&lt;h3&gt;文章标题&lt;/h3&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;p&gt;文章内容&lt;/p&gt;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>&lt;/div&gt;</span></div></div><div><div><div>6</div></div><div><span>&lt;/div&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这里：</p><ul>
<li><code>.container</code>：Grid 容器。</li>
<li><code>.item</code>：Grid 项目。</li>
<li><code>h3</code> 和 <code>p</code>：项目内部的内容元素。</li>
</ul><p>内容会影响元素自身的尺寸，并可能影响使用 <code>auto</code> 等尺寸规则的轨道。</p><p>Grid 还提供了对齐相关属性：</p>

<table><thead><tr><th>属性</th><th>说明</th></tr></thead><tbody><tr><td><code>justify-items</code></td><td>控制项目在其网格区域内的行内方向对齐</td></tr><tr><td><code>align-items</code></td><td>控制项目在其网格区域内的块级方向对齐</td></tr><tr><td><code>justify-content</code></td><td>控制整个网格轨道集合在容器内的行内方向对齐或分布</td></tr><tr><td><code>align-content</code></td><td>控制整个网格轨道集合在容器内的块级方向对齐或分布</td></tr></tbody></table><p>常见的水平书写模式下，行内方向通常是水平，块级方向通常是垂直。</p><p>需要区分：<strong>项目的对齐与项目内部文字的对齐不是同一回事。</strong></p></section><section><h3>4. 轨道（Track）<a href="#4-轨道track"><span>#</span></a></h3><p>轨道是 Grid 布局中用于定义行、列空间尺寸的概念。</p><p>轨道分为两种：</p><ul>
<li><strong>列轨道（Column Track）</strong>：两条相邻列网格线之间的列空间，其宽度决定这一列单元格的宽度。</li>
<li><strong>行轨道（Row Track）</strong>：两条相邻行网格线之间的行空间，其高度决定这一行单元格的高度。</li>
</ul><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: 100px 200px 100px;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-template-rows: 80px 120px;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这里建立了：</p><ul>
<li>3 条列轨道。</li>
<li>2 条行轨道。</li>
<li>6 个单元格。</li>
</ul><p><strong>轨道与单元格有什么区别？</strong></p><p>可以借助 Excel 来理解：</p><ul>
<li>轨道类似 Excel 中的一整行或一整列。</li>
<li>单元格类似 Excel 中行与列交叉形成的格子。</li>
</ul><p>不过轨道并不是将单元格的宽度或高度累加起来得到的。</p><p>例如第一列宽 <code>100px</code>，那么该列每个单元格都宽 <code>100px</code>，而不是整列所有单元格宽度加起来为 <code>100px</code>。</p><p><strong>轨道与间距有什么关系？</strong></p><p>轨道是相邻、平行网格线之间的带状空间，不能把它理解成一节一节的独立盒子。</p><p>列轨道纵向延伸时会经过行间距，行轨道横向延伸时也会经过列间距。</p><p>但：</p><ul>
<li>列轨道的宽度不包含 <code>column-gap</code>。</li>
<li>行轨道的高度不包含 <code>row-gap</code>。</li>
</ul><p>因此，虽然间距会影响整个网格的尺寸，但不会直接计入普通轨道自身的宽度或高度。</p></section></section><section><h2>总结<a href="#总结"><span>#</span></a></h2>

<table><thead><tr><th>概念</th><th>通俗理解</th><th>主要作用</th></tr></thead><tbody><tr><td>容器（Container）</td><td>网格布局的外层元素</td><td>建立网格布局</td></tr><tr><td>项目（Item）</td><td>放入网格中的 HTML 元素</td><td>参与排列、定位和跨行跨列</td></tr><tr><td>行（Row）</td><td>横向的一排</td><td>组织网格结构</td></tr><tr><td>列（Column）</td><td>纵向的一列</td><td>组织网格结构</td></tr><tr><td>单元格（Cell）</td><td>最小的格子</td><td>提供基本网格空间</td></tr><tr><td>网格线（Line）</td><td>看不见的定位参考线</td><td>划分轨道、定位项目</td></tr><tr><td>轨道（Track）</td><td>一条行或列空间</td><td>定义行高、列宽</td></tr><tr><td>间距（Gap）</td><td>相邻轨道之间的空隙</td><td>分隔行与列</td></tr><tr><td>区域（Area）</td><td>一个或多个单元格构成的矩形空间</td><td>表示项目可以占据的范围</td></tr><tr><td>内容（Content）</td><td>项目内部的文字、图片等</td><td>组成实际页面内容</td></tr></tbody></table><p><strong>最需要记住的三个区别：</strong></p><ol>
<li><strong>单元格 ≠ 项目</strong>：单元格是布局空间，项目是实际元素。</li>
<li><strong>轨道 ≠ 间距</strong>：轨道定义行高、列宽，间距是相邻轨道之间额外的空间。</li>
<li><strong>网格线 ≠ 轨道</strong>：网格线是参考边界，轨道是相邻网格线之间的空间。</li>
</ol><p>最后，可以把 Grid 的整个工作过程概括为：</p><p><strong>容器建立网格 → 轨道定义行列尺寸 → 行列交叉形成单元格 → 网格线用于定位 → 项目占据对应的网格区域。</strong></p><p><code>gap</code> 负责相邻轨道之间的留白，而项目内部的内容最终构成我们看到的页面。</p><p>理解这些概念后，再学习 Grid 容器属性、项目属性以及实际布局，就会清晰很多。</p></section></section>
<section><h1>Grid 容器的属性<a href="#grid-容器的属性"><span>#</span></a></h1><p>Grid 容器属性主要用于定义网格的行列结构、轨道尺寸、排列方向、间距以及项目的对齐方式。</p><section><h2>一、display<a href="#一display"><span>#</span></a></h2><p>通过 <code>display</code> 属性创建 Grid 容器，使其直接子元素按照网格布局规则排列。</p>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>grid</code></td><td>创建块级 Grid 容器</td></tr><tr><td><code>inline-grid</code></td><td>创建行内级 Grid 容器</td></tr></tbody></table><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>两者的区别：</strong></p><ul>
<li><code>display: grid</code>：容器在外部表现为块级元素，内部使用 Grid 布局。</li>
<li><code>display: inline-grid</code>：容器在外部表现为行内级元素，内部同样使用 Grid 布局。</li>
</ul><p>注意：设置 <code>display: grid</code> 后，即使没有定义行列，浏览器也会根据布局规则自动创建网格轨道。</p></section><section><h2>二、grid-template-rows / grid-template-columns<a href="#二grid-template-rows--grid-template-columns"><span>#</span></a></h2><p>这两个属性用于定义 Grid <strong>显式网格的行列轨道及其尺寸</strong>。</p>

<table><thead><tr><th>属性</th><th>说明</th></tr></thead><tbody><tr><td><code>grid-template-columns</code></td><td>定义列轨道及其宽度</td></tr><tr><td><code>grid-template-rows</code></td><td>定义行轨道及其高度</td></tr></tbody></table><section><h3>1. 基本使用<a href="#1-基本使用"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: 100px 200px 100px;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-template-rows: 80px 120px;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>表示：</p><ul>
<li>3 条列轨道：宽度分别为 <code>100px</code>、<code>200px</code>、<code>100px</code>。</li>
<li>2 条行轨道：高度分别为 <code>80px</code>、<code>120px</code>。</li>
<li>两者交叉形成 6 个单元格。</li>
</ul><p><strong>注意：定义了 6 个单元格，不代表必须有 6 个项目。</strong> 即使只有两个 HTML 子元素，这套网格结构仍然存在。</p></section><section><h3>2. 常用属性值<a href="#2-常用属性值"><span>#</span></a></h3>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>100px</code></td><td>固定轨道尺寸</td></tr><tr><td><code>50%</code></td><td>相对于 Grid 容器对应的尺寸计算百分比</td></tr><tr><td><code>auto</code></td><td>根据可用空间、内容等规则确定尺寸</td></tr><tr><td><code>1fr</code></td><td>使用一份弹性空间</td></tr><tr><td><code>repeat()</code></td><td>重复定义轨道</td></tr><tr><td><code>minmax()</code></td><td>指定轨道尺寸范围</td></tr></tbody></table><p><strong>fr 单位</strong></p><p><code>fr</code> 表示分配给弹性轨道的空间份额。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: 1fr 2fr 1fr;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>在空间充足且没有额外尺寸限制的情况下，三列按照 <code>1:2:1</code> 分配可用空间。</p><p><strong>repeat() 函数</strong></p><p>用于简化重复的轨道定义。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: repeat(3, 100px);</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>等价于：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>grid-template-columns: 100px 100px 100px;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>minmax() 函数</strong></p><p>用于设置轨道尺寸的最小值和最大值。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: repeat(3, minmax(100px, 1fr));</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>每列最小宽度为 <code>100px</code>，空间充足时可以弹性扩展。</p><p>需要注意，最小尺寸限制可能导致网格在容器较窄时溢出。</p></section></section><section><h2>三、grid-auto-flow<a href="#三grid-auto-flow"><span>#</span></a></h2><p><code>grid-auto-flow</code> 用于控制<strong>没有明确指定位置的 Grid 项目如何自动排列</strong>。</p>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>row</code></td><td>默认值，优先沿行方向依次排列</td></tr><tr><td><code>column</code></td><td>优先沿列方向依次排列</td></tr><tr><td><code>row dense</code></td><td>按行排列，并尝试用后续项目填补空位</td></tr><tr><td><code>column dense</code></td><td>按列排列，并尝试用后续项目填补空位</td></tr></tbody></table><section><h3>1. row（默认）<a href="#1-row默认"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: repeat(3, 100px);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-auto-flow: row;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>假设有 6 个项目：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>┌───┬───┬───┐</span></div></div><div><div><div>2</div></div><div><span>│ 1 │ 2 │ 3 │</span></div></div><div><div><div>3</div></div><div><span>├───┼───┼───┤</span></div></div><div><div><div>4</div></div><div><span>│ 4 │ 5 │ 6 │</span></div></div><div><div><div>5</div></div><div><span>└───┴───┴───┘</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>项目优先从左到右排列，当前行无法继续放置时，自动进入下一行。</p></section><section><h3>2. column<a href="#2-column"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-rows: repeat(3, 80px);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-auto-flow: column;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>grid-auto-columns: 100px;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>假设有 6 个项目：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>┌───┬───┐</span></div></div><div><div><div>2</div></div><div><span>│ 1 │ 4 │</span></div></div><div><div><div>3</div></div><div><span>├───┼───┤</span></div></div><div><div><div>4</div></div><div><span>│ 2 │ 5 │</span></div></div><div><div><div>5</div></div><div><span>├───┼───┤</span></div></div><div><div><div>6</div></div><div><span>│ 3 │ 6 │</span></div></div><div><div><div>7</div></div><div><span>└───┴───┘</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>项目优先沿列方向排列，当前列无法继续放置时，自动进入下一列。</p></section><section><h3>3. dense<a href="#3-dense"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: repeat(3, 100px);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-auto-flow: row dense;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>当某些项目跨越多列而产生空位时，<code>dense</code> 会尝试使用后续能够放入空位的项目进行填补。</p><p>注意：<code>dense</code> 可能导致项目的视觉排列顺序与 HTML 源码顺序不同，因此需要考虑键盘导航和阅读顺序。</p></section></section><section><h2>四、grid-auto-rows / grid-auto-columns<a href="#四grid-auto-rows--grid-auto-columns"><span>#</span></a></h2><p>这两个属性用于控制<strong>隐式网格轨道（Implicit Tracks）的尺寸</strong>。</p>

<table><thead><tr><th>属性</th><th>说明</th></tr></thead><tbody><tr><td><code>grid-auto-rows</code></td><td>设置自动创建的隐式行轨道尺寸</td></tr><tr><td><code>grid-auto-columns</code></td><td>设置自动创建的隐式列轨道尺寸</td></tr></tbody></table><section><h3>1. 显式网格和隐式网格<a href="#1-显式网格和隐式网格"><span>#</span></a></h3><ul>
<li><strong>显式网格</strong>：通过 <code>grid-template-columns</code>、<code>grid-template-rows</code> 等属性明确定义的网格。</li>
<li><strong>隐式网格</strong>：当现有显式网格无法容纳项目，或项目被定位到显式网格之外时，浏览器自动补充的网格轨道。</li>
</ul></section><section><h3>2. grid-auto-rows<a href="#2-grid-auto-rows"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: repeat(3, 100px);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-auto-rows: 80px;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>gap: 10px;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这里明确规定了三列，但没有定义显式行轨道。</p><p>浏览器会根据项目数量自动创建行，每条自动创建的行轨道高 <code>80px</code>。</p><p>例如有 9 个项目，就会自动排列成 3 行 3 列。</p></section><section><h3>3. grid-auto-columns<a href="#3-grid-auto-columns"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-rows: repeat(2, 100px);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-auto-flow: column;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>grid-auto-columns: 150px;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>gap: 10px;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这里定义了两行，项目按照列方向排列。</p><p>当需要新的列时，浏览器会自动创建隐式列轨道，每列宽 <code>150px</code>。</p><p><strong>容易混淆的区别：</strong></p><ul>
<li><code>grid-template-rows / columns</code>：定义显式网格轨道。</li>
<li><code>grid-auto-rows / columns</code>：控制自动创建的隐式轨道尺寸。</li>
<li><code>grid-auto-flow</code>：控制项目的自动放置方向及是否尝试填补空位。</li>
</ul><p><code>grid-auto-rows</code> 和 <code>grid-auto-columns</code> 并不是用来指定创建多少行、多少列的。</p></section></section><section><h2>五、row-gap / column-gap / gap<a href="#五row-gap--column-gap--gap"><span>#</span></a></h2><p>这三个属性用于设置<strong>相邻网格轨道之间的间距</strong>。</p>

<table><thead><tr><th>属性</th><th>说明</th></tr></thead><tbody><tr><td><code>row-gap</code></td><td>行轨道之间的间距</td></tr><tr><td><code>column-gap</code></td><td>列轨道之间的间距</td></tr><tr><td><code>gap</code></td><td>两者的简写属性</td></tr></tbody></table><section><h3>1. 基本使用<a href="#1-基本使用-1"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: repeat(3, 100px);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-template-rows: repeat(2, 80px);</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>row-gap: 10px;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>column-gap: 20px;</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>可以简写为：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>gap: 10px 20px;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其中：</p><ul>
<li>第一个值：<code>row-gap</code>。</li>
<li>第二个值：<code>column-gap</code>。</li>
</ul><p>如果只设置一个值：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>gap: 10px;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>表示行间距、列间距均为 <code>10px</code>。</p></section><section><h3>2. 间距和轨道的关系<a href="#2-间距和轨道的关系"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: 100px 200px;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>column-gap: 20px;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>网格在列方向上的总尺寸为：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>100px + 20px + 200px = 320px</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>注意：</strong></p><ul>
<li><code>gap</code> 不属于单元格，也不计入普通轨道自身的尺寸。</li>
<li>固定尺寸的轨道不会因为设置 <code>gap</code> 而自动缩小。</li>
<li>如果轨道使用 <code>fr</code> 等弹性尺寸，则需要在分配可用空间时考虑 <code>gap</code>。</li>
<li>当项目跨越多条轨道时，其占据的网格区域包含中间的 <code>gap</code>。</li>
</ul><p>从布局计算角度，也可以把 <code>gap</code> 想象成网格线具有了厚度，但网格线并不是真实可见的边框。</p></section></section><section><h2>六、grid-template-areas<a href="#六grid-template-areas"><span>#</span></a></h2><p><code>grid-template-areas</code> 用于<strong>通过名称定义网格区域</strong>，让布局结构更加直观。</p><p>通常与项目属性 <code>grid-area</code> 配合使用。</p><section><h3>1. 基本使用<a href="#1-基本使用-2"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;div class="container"&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;header class="header"&gt;头部&lt;/header&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;main class="main"&gt;主体&lt;/main&gt;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>&lt;aside class="aside"&gt;侧边栏&lt;/aside&gt;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>&lt;footer class="footer"&gt;底部&lt;/footer&gt;</span></div></div><div><div><div>6</div></div><div><span>&lt;/div&gt;</span></div></div><div><div><div>7</div></div><div><span>.container {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>grid-template-columns: 200px 1fr;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>grid-template-rows: 80px 1fr 60px;</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>grid-template-areas:</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>"header header"</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>"aside  main"</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>"footer footer";</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span><span>  </span></span><span>gap: 10px;</span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>min-height: 500px;</span></div></div><div><div><div>20</div></div><div><span>}</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>.header {</span></div></div><div><div><div>23</div></div><div><span><span>  </span></span><span>grid-area: header;</span></div></div><div><div><div>24</div></div><div><span>}</span></div></div><div><div><div>25</div></div><div>
</div></div><div><div><div>26</div></div><div><span>.main {</span></div></div><div><div><div>27</div></div><div><span><span>  </span></span><span>grid-area: main;</span></div></div><div><div><div>28</div></div><div><span>}</span></div></div><div><div><div>29</div></div><div>
</div></div><div><div><div>30</div></div><div><span>.aside {</span></div></div><div><div><div>31</div></div><div><span><span>  </span></span><span>grid-area: aside;</span></div></div><div><div><div>32</div></div><div><span>}</span></div></div><div><div><div>33</div></div><div>
</div></div><div><div><div>34</div></div><div><span>.footer {</span></div></div><div><div><div>35</div></div><div><span><span>  </span></span><span>grid-area: footer;</span></div></div><div><div><div>36</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>布局结构为：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>┌─────────────────┐</span></div></div><div><div><div>2</div></div><div><span>│      header     │</span></div></div><div><div><div>3</div></div><div><span>├───────┬─────────┤</span></div></div><div><div><div>4</div></div><div><span>│ aside │  main   │</span></div></div><div><div><div>5</div></div><div><span>├───────┴─────────┤</span></div></div><div><div><div>6</div></div><div><span>│      footer     │</span></div></div><div><div><div>7</div></div><div><span>└─────────────────┘</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>2. 使用规则<a href="#2-使用规则"><span>#</span></a></h3><ul>
<li>同名区域必须组成一个连续的矩形。</li>
<li>一个区域可以占据一个或多个单元格。</li>
<li>使用 <code>.</code> 可以表示不属于任何命名区域的单元格。</li>
<li>每行必须声明相同数量的单元格名称或占位符。</li>
<li><code>grid-template-areas</code> 可以建立显式网格结构，即使没有另外设置行高、列宽。</li>
</ul><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>grid-template-areas:</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>"header header"</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>"main   .";</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其中 <code>.</code> 表示未命名的单元格。</p><p>注意：区域不是新的 HTML 元素，也不会真正合并单元格，只是定义了项目可以占据的网格空间。</p></section></section><section><h2>七、align-items / justify-items / place-items<a href="#七align-items--justify-items--place-items"><span>#</span></a></h2><p>这三个属性用于<strong>控制 Grid 项目在各自网格区域内的对齐方式</strong>。</p>

<table><thead><tr><th>属性</th><th>说明</th></tr></thead><tbody><tr><td><code>align-items</code></td><td>控制项目在块级方向的对齐，常见水平书写模式下为垂直方向</td></tr><tr><td><code>justify-items</code></td><td>控制项目在行内方向的对齐，常见水平书写模式下为水平方向</td></tr><tr><td><code>place-items</code></td><td>两者的简写属性</td></tr></tbody></table><section><h3>1. 常用属性值<a href="#1-常用属性值"><span>#</span></a></h3>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>normal</code></td><td>默认值，在常见 Grid 场景中通常表现为拉伸</td></tr><tr><td><code>start</code></td><td>靠起始位置对齐</td></tr><tr><td><code>end</code></td><td>靠结束位置对齐</td></tr><tr><td><code>center</code></td><td>居中对齐</td></tr><tr><td><code>stretch</code></td><td>拉伸项目以填充可用空间，受尺寸约束影响</td></tr></tbody></table></section><section><h3>2. 基本使用<a href="#2-基本使用"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: repeat(3, 150px);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-template-rows: 150px;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>align-items: center;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>justify-items: center;</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>表示让所有项目在各自的网格区域内水平、垂直居中。</p><p>可以简写为：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>place-items: center;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>3. place-items 的两个值<a href="#3-place-items-的两个值"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>place-items: start end;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>等价于：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>align-items: start;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>justify-items: end;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>第一个值控制</strong> <code>**align-items**</code><strong>，第二个值控制</strong> <code>**justify-items**</code><strong>。</strong></p><p>注意：</p><p>这三个都是容器属性，统一控制项目在网格区域中的对齐方式。</p><p>如果希望单独控制某个项目，可以使用项目属性：</p><ul>
<li><code>align-self</code></li>
<li><code>justify-self</code></li>
<li><code>place-self</code></li>
</ul><p>另外，项目的对齐不等于项目内部文字的对齐。</p></section></section><section><h2>八、align-content / justify-content / place-content<a href="#八align-content--justify-content--place-content"><span>#</span></a></h2><p>这三个属性用于<strong>控制整个网格轨道集合在容器中的对齐和分布方式</strong>。</p><p>与 <code>*-items</code> 不同，<code>*-content</code> 调整的是网格轨道整体的位置或间距。</p>

<table><thead><tr><th>属性</th><th>说明</th></tr></thead><tbody><tr><td><code>align-content</code></td><td>控制网格轨道集合在块级方向上的对齐和分布</td></tr><tr><td><code>justify-content</code></td><td>控制网格轨道集合在行内方向上的对齐和分布</td></tr><tr><td><code>place-content</code></td><td>两者的简写属性</td></tr></tbody></table><section><h3>1. 常用属性值<a href="#1-常用属性值-1"><span>#</span></a></h3>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>normal</code></td><td>默认值，在常见 Grid 场景中效果通常接近 <code>stretch</code></td></tr><tr><td><code>start</code></td><td>靠起始位置排列</td></tr><tr><td><code>end</code></td><td>靠结束位置排列</td></tr><tr><td><code>center</code></td><td>居中排列</td></tr><tr><td><code>space-between</code></td><td>首尾贴边，剩余空间分布在轨道之间</td></tr><tr><td><code>space-around</code></td><td>每条轨道两侧分配相等的空间份额</td></tr><tr><td><code>space-evenly</code></td><td>轨道之间及两端的空隙相等</td></tr><tr><td><code>stretch</code></td><td>在适用条件下拉伸可自动调整尺寸的轨道</td></tr></tbody></table></section><section><h3>2. 基本使用<a href="#2-基本使用-1"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>width: 500px;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>height: 400px;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>grid-template-columns: repeat(2, 100px);</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>grid-template-rows: repeat(2, 80px);</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>gap: 10px;</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>align-content: center;</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>justify-content: center;</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这里网格轨道集合的宽度为 <code>210px</code>，高度为 <code>170px</code>。</p><p>由于容器宽 <code>500px</code>、高 <code>400px</code>，还存在剩余空间，因此可以将整个网格居中。</p><p>可以简写为：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>place-content: center;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>3. place-content 的两个值<a href="#3-place-content-的两个值"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>place-content: start center;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>等价于：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>align-content: start;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>justify-content: center;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>4. items 和 content 的区别<a href="#4-items-和-content-的区别"><span>#</span></a></h3><p>这是 Grid 中容易混淆的一组属性。</p>

<table><thead><tr><th>对比</th><th><code>*-items</code></th><th><code>*-content</code></th></tr></thead><tbody><tr><td>控制对象</td><td>各个 Grid 项目</td><td>整个网格轨道集合</td></tr><tr><td>主要作用</td><td>控制项目在网格区域中的对齐</td><td>控制轨道集合在容器中的对齐和分布</td></tr><tr><td>常见用法</td><td><code>place-items: center</code></td><td><code>place-content: center</code></td></tr><tr><td>是否控制项目内部文字</td><td>否</td><td>否</td></tr></tbody></table><p><strong>简单记忆：</strong></p><ul>
<li><code>items</code>：调整项目的位置。</li>
<li><code>content</code>：调整网格轨道整体的位置及分布。</li>
</ul><p>注意：<code>align-content</code>、<code>justify-content</code> 并不是任何时候都能明显改变布局。</p><p>例如，使用 <code>1fr</code> 的轨道可能已经占满可用空间，此时没有剩余空间供这些属性分配，对齐效果就可能不明显。</p></section></section><section><h2>九、grid-template / grid<a href="#九grid-template--grid"><span>#</span></a></h2><p>这两个都是 Grid 的<strong>简写属性</strong>，用于同时设置多个网格布局相关属性。</p><section><h3>1. grid-template<a href="#1-grid-template"><span>#</span></a></h3><p><code>grid-template</code> 是以下三个属性的简写：</p><ul>
<li><code>grid-template-rows</code></li>
<li><code>grid-template-columns</code></li>
<li><code>grid-template-areas</code></li>
</ul><p><strong>基本写法：</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-template:</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>80px 120px</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>/ 100px 200px;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>等价于：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>grid-template-rows: 80px 120px;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: 100px 200px;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>也可以同时定义命名区域：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-template:</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>"header header" 80px</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>"aside main" 1fr</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>/ 200px 1fr;</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这里：</p><ul>
<li>第一行高 <code>80px</code>。</li>
<li>第二行占据剩余的弹性空间。</li>
<li>第一列宽 <code>200px</code>。</li>
<li>第二列使用 <code>1fr</code>。</li>
<li>同时定义了 <code>header</code>、<code>aside</code>、<code>main</code> 三个区域。</li>
</ul></section><section><h3>2. grid<a href="#2-grid"><span>#</span></a></h3><p><code>grid</code> 是范围更广的简写属性，可以同时设置显式网格和隐式网格相关配置。</p><p>它涉及：</p><ul>
<li><code>grid-template-rows</code></li>
<li><code>grid-template-columns</code></li>
<li><code>grid-template-areas</code></li>
<li><code>grid-auto-rows</code></li>
<li><code>grid-auto-columns</code></li>
<li><code>grid-auto-flow</code></li>
</ul><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid: 80px 120px / 100px 200px;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这会定义两条显式行轨道和两条显式列轨道，同时将相关的其他 Grid 子属性重置为初始值。</p></section><section><h3>3. 两者的区别<a href="#3-两者的区别"><span>#</span></a></h3>

<table><thead><tr><th>属性</th><th>作用</th></tr></thead><tbody><tr><td><code>grid-template</code></td><td>主要定义显式网格的行、列及命名区域</td></tr><tr><td><code>grid</code></td><td>既能定义显式网格，也能配置部分隐式网格规则</td></tr></tbody></table><p>注意：</p><ul>
<li><code>grid</code> 的写法较灵活，但语法也更复杂。</li>
<li><code>grid</code> 不包含 <code>gap</code>、<code>align-items</code>、<code>justify-items</code> 等对齐和间距属性。</li>
<li>使用简写时要注意其他相关子属性可能被重置。</li>
</ul><p>实际开发中，通常更推荐分别使用 <code>grid-template-columns</code>、<code>grid-template-rows</code>、<code>grid-auto-flow</code> 等属性，方便阅读和维护。</p></section></section><section><h2>总结<a href="#总结-1"><span>#</span></a></h2>

<table><thead><tr><th>属性</th><th>核心作用</th></tr></thead><tbody><tr><td><code>display</code></td><td>创建 Grid 容器</td></tr><tr><td><code>grid-template-rows</code></td><td>定义显式行轨道及其高度</td></tr><tr><td><code>grid-template-columns</code></td><td>定义显式列轨道及其宽度</td></tr><tr><td><code>grid-auto-flow</code></td><td>控制自动放置项目的方向和填补规则</td></tr><tr><td><code>grid-auto-rows</code></td><td>设置隐式行轨道尺寸</td></tr><tr><td><code>grid-auto-columns</code></td><td>设置隐式列轨道尺寸</td></tr><tr><td><code>row-gap</code></td><td>设置行轨道间距</td></tr><tr><td><code>column-gap</code></td><td>设置列轨道间距</td></tr><tr><td><code>gap</code></td><td>设置行、列轨道间距</td></tr><tr><td><code>grid-template-areas</code></td><td>定义命名网格区域</td></tr><tr><td><code>align-items</code></td><td>控制项目在块级方向的对齐</td></tr><tr><td><code>justify-items</code></td><td>控制项目在行内方向的对齐</td></tr><tr><td><code>place-items</code></td><td>简写项目对齐方式</td></tr><tr><td><code>align-content</code></td><td>控制轨道集合在块级方向的对齐和分布</td></tr><tr><td><code>justify-content</code></td><td>控制轨道集合在行内方向的对齐和分布</td></tr><tr><td><code>place-content</code></td><td>简写轨道集合的对齐和分布方式</td></tr><tr><td><code>grid-template</code></td><td>显式网格结构的简写</td></tr><tr><td><code>grid</code></td><td>显式及隐式网格相关配置的综合简写</td></tr></tbody></table><p><strong>Grid 容器属性可以归纳为四类：</strong></p><ol>
<li><strong>结构与尺寸</strong>：定义行列轨道及其宽高。</li>
<li><strong>自动排列</strong>：决定项目如何自动放置，以及隐式轨道如何确定尺寸。</li>
<li><strong>间距与区域</strong>：控制轨道间隔和项目的布局区域。</li>
<li><strong>对齐与分布</strong>：控制项目在网格区域中的位置，以及网格轨道整体在容器中的位置。</li>
</ol><p>理解这四类属性的职责后，Grid 容器属性就不再是零散的 CSS 语法，而是一套有明确分工的布局规则。</p></section></section>
<section><h1>Grid 项目的属性<a href="#grid-项目的属性"><span>#</span></a></h1><p>Grid 项目属性主要用于控制<strong>项目在网格中的位置、跨行跨列的范围，以及项目在网格区域内的对齐方式</strong>。</p><p>Grid 项目通常是 Grid 容器中参与网格布局的直接子元素。</p><section><h2>一、grid-column-start / grid-column-end / grid-row-start / grid-row-end<a href="#一grid-column-start--grid-column-end--grid-row-start--grid-row-end"><span>#</span></a></h2><p>这四个属性用于通过**网格线（Grid Line）**确定项目的起始位置和结束位置。</p>

<table><thead><tr><th>属性</th><th>说明</th></tr></thead><tbody><tr><td><code>grid-column-start</code></td><td>项目在列方向的起始网格线</td></tr><tr><td><code>grid-column-end</code></td><td>项目在列方向的结束网格线</td></tr><tr><td><code>grid-row-start</code></td><td>项目在行方向的起始网格线</td></tr><tr><td><code>grid-row-end</code></td><td>项目在行方向的结束网格线</td></tr></tbody></table><section><h3>1. 基本使用<a href="#1-基本使用-3"><span>#</span></a></h3><p>首先创建一个 3 行 3 列的网格：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: repeat(3, 100px);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-template-rows: repeat(3, 100px);</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>gap: 10px;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>然后指定项目的位置：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>grid-column-start: 1;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-column-end: 3;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-row-start: 1;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>grid-row-end: 3;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>表示：</p><ul>
<li>列方向：从第 1 条列网格线到第 3 条列网格线，跨越 2 列。</li>
<li>行方向：从第 1 条行网格线到第 3 条行网格线，跨越 2 行。</li>
<li>最终项目占据 2 行 2 列，共 4 个单元格对应的矩形区域。</li>
</ul><p><strong>注意：指定的是网格线编号，而不是单元格编号。</strong></p><p>例如一个 3 行 3 列的显式网格，在两个方向上分别有 4 条网格线。</p></section><section><h3>2. 常用属性值<a href="#2-常用属性值-1"><span>#</span></a></h3>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>auto</code></td><td>默认值，由自动布局规则确定位置或范围</td></tr><tr><td><code>1</code>、<code>2</code>、<code>3</code></td><td>指定网格线编号</td></tr><tr><td><code>-1</code></td><td>从显式网格末端反向编号，表示最后一条显式网格线</td></tr><tr><td><code>span 2</code></td><td>从相应位置跨越 2 条轨道</td></tr><tr><td><code>header</code></td><td>引用符合规则的命名网格线或区域名称</td></tr></tbody></table><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>grid-column-start: 1;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-column-end: span 2;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>表示项目从第 1 条列网格线开始，横跨 2 列。</p><p>还可以通过负数引用显式网格的末端网格线：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>grid-column-start: 1;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-column-end: -1;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这里表示从第 1 条列网格线延伸到显式网格的最后一条列网格线。</p></section></section><section><h2>二、grid-column / grid-row<a href="#二grid-column--grid-row"><span>#</span></a></h2><p><code>grid-column</code> 和 <code>grid-row</code> 是起始、结束网格线属性的简写。</p>

<table><thead><tr><th>简写属性</th><th>对应属性</th></tr></thead><tbody><tr><td><code>grid-column</code></td><td><code>grid-column-start</code>、<code>grid-column-end</code></td></tr><tr><td><code>grid-row</code></td><td><code>grid-row-start</code>、<code>grid-row-end</code></td></tr></tbody></table><section><h3>1. 基本使用<a href="#1-基本使用-4"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>grid-column: 1 / 3;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-row: 1 / 3;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>等价于：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>grid-column-start: 1;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-column-end: 3;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>grid-row-start: 1;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>grid-row-end: 3;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其中 <code>/</code> 用于分隔起始位置和结束位置。</p></section><section><h3>2. 常见写法<a href="#2-常见写法"><span>#</span></a></h3>

<table><thead><tr><th>写法</th><th>说明</th></tr></thead><tbody><tr><td><code>grid-column: 1 / 3</code></td><td>从第 1 条列网格线到第 3 条，跨越 2 列</td></tr><tr><td><code>grid-column: 1 / 4</code></td><td>从第 1 条列网格线到第 4 条，跨越 3 列</td></tr><tr><td><code>grid-column: 2</code></td><td>从第 2 条列网格线开始，通常跨越 1 列</td></tr><tr><td><code>grid-column: 1 / span 2</code></td><td>从第 1 条列网格线开始，跨越 2 列</td></tr><tr><td><code>grid-column: span 2</code></td><td>跨越 2 列，起始位置可由自动布局确定</td></tr><tr><td><code>grid-column: 1 / -1</code></td><td>从第 1 条列网格线到显式网格最后一条列网格线</td></tr></tbody></table><p><code>grid-row</code> 的使用方式相同，只是控制行方向。</p></section><section><h3>3. 跨列和跨行<a href="#3-跨列和跨行"><span>#</span></a></h3><p><strong>跨列：</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>grid-column: span 2;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>表示项目横跨 2 条列轨道。</p><p><strong>跨行：</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>grid-row: span 2;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>表示项目横跨 2 条行轨道。</p><p><strong>同时跨行、跨列：</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>grid-column: 1 / 3;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-row: 1 / 3;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>表示项目占据一个 2 行 2 列的矩形区域。</p><p>需要注意：</p><ul>
<li>项目跨越多个单元格，并不意味着单元格被真正合并。</li>
<li>项目跨越的区域包含中间的 <code>gap</code>。</li>
<li>项目定位后，如果与其他项目占据相同区域，可能发生重叠。</li>
</ul></section></section><section><h2>三、grid-area<a href="#三grid-area"><span>#</span></a></h2><p><code>grid-area</code> 用于指定 Grid 项目所在的网格区域。</p><p>它既可以引用<strong>命名区域</strong>，也可以作为四个网格线定位属性的简写。</p><section><h3>1. 使用命名区域<a href="#1-使用命名区域"><span>#</span></a></h3><p>首先通过容器属性 <code>grid-template-areas</code> 定义区域：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-template-columns: 200px 1fr;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>grid-template-rows: 80px 200px;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>grid-template-areas:</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>"header header"</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>"aside  main";</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>然后通过项目属性 <code>grid-area</code> 指定位置：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.header {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>grid-area: header;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>.aside {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>grid-area: aside;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>.main {</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>grid-area: main;</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其中：</p><ul>
<li><code>header</code>：占据第一行的两列。</li>
<li><code>aside</code>：占据第二行第一列。</li>
<li><code>main</code>：占据第二行第二列。</li>
</ul><p><code>**grid-template-areas**</code> <strong>是容器属性，</strong><code>**grid-area**</code> <strong>是项目属性。</strong></p></section><section><h3>2. 使用网格线定位<a href="#2-使用网格线定位"><span>#</span></a></h3><p><code>grid-area</code> 还可以直接指定四条网格线：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>grid-area: 1 / 2 / 3 / 4;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其顺序为：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>grid-area:</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>row-start / column-start / row-end / column-end;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>对应：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>grid-row-start: 1;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-column-start: 2;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-row-end: 3;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>grid-column-end: 4;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>表示项目：</p><ul>
<li>从第 1 条行网格线到第 3 条行网格线。</li>
<li>从第 2 条列网格线到第 4 条列网格线。</li>
</ul><p>最终横跨 2 行、2 列。</p></section><section><h3>3. grid-area 与 grid-column、grid-row 的区别<a href="#3-grid-area-与-grid-columngrid-row-的区别"><span>#</span></a></h3>

<table><thead><tr><th>属性</th><th>作用</th></tr></thead><tbody><tr><td><code>grid-column</code></td><td>控制项目在列方向的位置与范围</td></tr><tr><td><code>grid-row</code></td><td>控制项目在行方向的位置与范围</td></tr><tr><td><code>grid-area</code></td><td>可以同时控制行列位置，也可以引用命名区域</td></tr></tbody></table><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>grid-column: 2 / 4;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-row: 1 / 3;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>可以写成：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>grid-area: 1 / 2 / 3 / 4;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>注意：区域是布局空间，项目是实际元素。使用</strong> <code>**grid-area**</code> <strong>不会真正创建或合并 HTML 元素。</strong></p></section></section><section><h2>四、align-self / justify-self / place-self<a href="#四align-self--justify-self--place-self"><span>#</span></a></h2><p>这三个属性用于控制<strong>单个 Grid 项目在其网格区域内的对齐方式</strong>。</p>

<table><thead><tr><th>属性</th><th>说明</th></tr></thead><tbody><tr><td><code>align-self</code></td><td>控制项目在块级方向上的对齐，通常是垂直方向</td></tr><tr><td><code>justify-self</code></td><td>控制项目在行内方向上的对齐，通常是水平方向</td></tr><tr><td><code>place-self</code></td><td>两者的简写属性</td></tr></tbody></table><p>这里的水平、垂直方向是基于常见的水平书写模式而言的。</p><section><h3>1. 常用属性值<a href="#1-常用属性值-2"><span>#</span></a></h3>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>auto</code></td><td>默认值，继承容器对应的 <code>align-items</code> 或 <code>justify-items</code> 效果</td></tr><tr><td><code>start</code></td><td>靠网格区域的起始位置对齐</td></tr><tr><td><code>end</code></td><td>靠网格区域的结束位置对齐</td></tr><tr><td><code>center</code></td><td>在网格区域内居中</td></tr><tr><td><code>stretch</code></td><td>拉伸项目以填充对应方向的可用空间，受尺寸限制影响</td></tr></tbody></table></section><section><h3>2. align-self<a href="#2-align-self"><span>#</span></a></h3><p>用于控制单个项目在块级方向上的对齐。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: repeat(3, 150px);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-template-rows: 150px;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>.item {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>align-self: center;</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>在常见水平书写模式下，项目会在所在网格区域内垂直居中。</p></section><section><h3>3. justify-self<a href="#3-justify-self"><span>#</span></a></h3><p>用于控制单个项目在行内方向上的对齐。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>justify-self: center;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>在常见水平书写模式下，项目会在所在网格区域内水平居中。</p></section><section><h3>4. place-self<a href="#4-place-self"><span>#</span></a></h3><p><code>place-self</code> 是 <code>align-self</code> 和 <code>justify-self</code> 的简写属性。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>place-self: center;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>等价于：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>align-self: center;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>justify-self: center;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>也可以指定两个值：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>place-self: start end;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>等价于：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>align-self: start;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>justify-self: end;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>第一个值对应</strong> <code>**align-self**</code><strong>，第二个值对应</strong> <code>**justify-self**</code><strong>。</strong></p></section><section><h3>5. items 和 self 的区别<a href="#5-items-和-self-的区别"><span>#</span></a></h3><p>Grid 容器属性中还有一组非常相似的属性：</p><ul>
<li><code>align-items</code></li>
<li><code>justify-items</code></li>
<li><code>place-items</code></li>
</ul><p>它们和项目属性的对应关系如下：</p>

<table><thead><tr><th>容器属性</th><th>项目属性</th></tr></thead><tbody><tr><td><code>align-items</code></td><td><code>align-self</code></td></tr><tr><td><code>justify-items</code></td><td><code>justify-self</code></td></tr><tr><td><code>place-items</code></td><td><code>place-self</code></td></tr></tbody></table><p><strong>区别：</strong></p><ul>
<li><code>*-items</code>：设置在 Grid 容器上，统一控制项目的对齐。</li>
<li><code>*-self</code>：设置在 Grid 项目上，单独控制某个项目的对齐。</li>
</ul><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: grid;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>grid-template-columns: repeat(3, 150px);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>grid-template-rows: 150px;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>place-items: center;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>.item-2 {</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>place-self: start;</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这里所有项目默认在各自的网格区域内居中，但 <code>.item-2</code> 单独靠起始位置对齐。</p><p>注意：</p><p><strong>这组属性控制的是项目自身在网格区域中的对齐，不是项目内部文字的对齐。</strong></p><p>如果项目设置了固定宽高，对齐效果通常更容易观察；如果项目默认拉伸填充整个网格区域，视觉上可能不容易看出位置变化。</p></section></section><section><h2>总结<a href="#总结-2"><span>#</span></a></h2>

<table><thead><tr><th>属性</th><th>主要作用</th></tr></thead><tbody><tr><td><code>grid-column-start</code></td><td>设置列方向起始网格线</td></tr><tr><td><code>grid-column-end</code></td><td>设置列方向结束网格线</td></tr><tr><td><code>grid-row-start</code></td><td>设置行方向起始网格线</td></tr><tr><td><code>grid-row-end</code></td><td>设置行方向结束网格线</td></tr><tr><td><code>grid-column</code></td><td>简写列方向的起始、结束网格线</td></tr><tr><td><code>grid-row</code></td><td>简写行方向的起始、结束网格线</td></tr><tr><td><code>grid-area</code></td><td>指定命名区域或简写四条网格线</td></tr><tr><td><code>align-self</code></td><td>单独控制项目在块级方向上的对齐</td></tr><tr><td><code>justify-self</code></td><td>单独控制项目在行内方向上的对齐</td></tr><tr><td><code>place-self</code></td><td>简写项目自身的两个方向对齐方式</td></tr></tbody></table><p><strong>Grid 项目属性可以归纳为两个类别：</strong></p><ol>
<li><strong>位置与范围</strong>：通过 <code>grid-column-*</code>、<code>grid-row-*</code>、<code>grid-area</code> 决定项目放在哪里、占据多少行列。</li>
<li><strong>自身对齐</strong>：通过 <code>align-self</code>、<code>justify-self</code>、<code>place-self</code> 控制项目在所占网格区域中的位置。</li>
</ol><p>最重要的是区分：</p><ul>
<li><strong>网格定位</strong>：项目占据网格中的哪一块区域。</li>
<li><strong>项目对齐</strong>：项目在已经占据的区域内如何对齐。</li>
</ul><p><strong>简单理解：先通过网格线确定项目的布局区域，再通过对齐属性调整项目在该区域中的位置。</strong></p></section></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026101601-xiang-ying-shi-bu-ju/</id>
      <title type="text">响应式布局</title>
      <published>2026-10-16T01:47:53.000Z</published>
      <updated>2026-10-16T01:47:53.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026101601-xiang-ying-shi-bu-ju/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>前言<a href="#前言"><span>#</span></a></h1><p>响应式布局是2010年5月由Ethan Marcotte提出的一个概念，本质就是一个网站兼容多端，对不同尺寸的屏幕做出响应，并进行相应布局;既然是概念，那解决的方案是什么，答案就是媒体查询</p></section>
<section><h1>媒体查询<a href="#媒体查询"><span>#</span></a></h1><p>媒体查询（Media Queries）是 CSS 实现响应式布局的重要技术，可以根据媒体类型、视口宽度、设备方向等条件，为页面应用不同的 CSS 样式。</p><section><h2>基础语法<a href="#基础语法"><span>#</span></a></h2><p>使用 <code>@media</code> 定义媒体查询。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@media</span><span><span> 媒体类型 </span><span>and</span><span> (媒体特性) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>/* 满足条件时生效的 CSS 样式 */</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>/* 屏幕视口宽度 &gt;= 768px 时生效 */</span></div></div><div><div><div>6</div></div><div><span>@media</span><span> </span><span>screen</span><span><span> </span><span>and</span><span> (min-width: </span></span><span><span>768</span><span>px</span></span><span>) {</span></div></div><div><div><div>7</div></div><div><span>  </span><span>.box</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>width: </span><span><span>50</span><span>%</span></span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>媒体类型</strong></p><p>媒体类型（Media Type）用于指定 CSS 样式应用于哪一类设备或输出媒介。</p>

<table><thead><tr><th>媒体类型</th><th>说明</th></tr></thead><tbody><tr><td><code>all</code></td><td>所有设备，默认值</td></tr><tr><td><code>screen</code></td><td>屏幕设备，包括手机、平板、电脑等</td></tr><tr><td><code>print</code></td><td>打印设备及打印预览</td></tr></tbody></table><p>使用示例：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/* 所有设备 */</span></div></div><div><div><div>2</div></div><div><span>@media</span><span> </span><span>all</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>.box</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>color: </span><span>red</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>/* 屏幕设备 */</span></div></div><div><div><div>9</div></div><div><span>@media</span><span> </span><span>screen</span><span> {</span></div></div><div><div><div>10</div></div><div><span>  </span><span>.box</span><span> {</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>color: </span><span>blue</span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>/* 打印模式 */</span></div></div><div><div><div>16</div></div><div><span>@media</span><span> </span><span>print</span><span> {</span></div></div><div><div><div>17</div></div><div><span>  </span><span>.box</span><span> {</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>color: </span><span>black</span><span>;</span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>20</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>媒体类型可以省略，默认使用 <code>all</code>。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/* 以下两种写法等价 */</span></div></div><div><div><div>2</div></div><div><span>@media</span><span> </span><span>all</span><span><span> </span><span>and</span><span> (min-width: </span></span><span><span>768</span><span>px</span></span><span>) {}</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>@media</span><span> (min-width: </span><span><span>768</span><span>px</span></span><span>) {}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意：<code>screen</code> 并不专门代表电脑端，而是包含手机、平板和电脑等屏幕设备。</p><p><strong>媒体特性</strong>：媒体特性（Media Feature）用于检测视口、设备或用户环境的具体特征。</p>

<table><thead><tr><th>媒体特性</th><th>说明</th></tr></thead><tbody><tr><td><code>min-width</code></td><td>视口宽度大于等于指定值</td></tr><tr><td><code>max-width</code></td><td>视口宽度小于等于指定值</td></tr><tr><td><code>min-height</code></td><td>视口高度大于等于指定值</td></tr><tr><td><code>max-height</code></td><td>视口高度小于等于指定值</td></tr><tr><td><code>orientation: portrait</code></td><td>视口为纵向</td></tr><tr><td><code>orientation: landscape</code></td><td>视口为横向</td></tr><tr><td><code>prefers-color-scheme: dark</code></td><td>用户偏好深色主题</td></tr><tr><td><code>prefers-reduced-motion: reduce</code></td><td>用户偏好减少动画</td></tr></tbody></table><p>使用示例：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/* 视口宽度 &gt;= 768px */</span></div></div><div><div><div>2</div></div><div><span>@media</span><span> (min-width: </span><span><span>768</span><span>px</span></span><span>) {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>.box</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>width: </span><span><span>50</span><span>%</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>/* 视口宽度 &lt;= 767px */</span></div></div><div><div><div>9</div></div><div><span>@media</span><span> (max-width: </span><span><span>767</span><span>px</span></span><span>) {</span></div></div><div><div><div>10</div></div><div><span>  </span><span>.box</span><span> {</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>/* 横向视口 */</span></div></div><div><div><div>16</div></div><div><span>@media</span><span><span> (orientation: </span><span>landscape</span><span>) {</span></span></div></div><div><div><div>17</div></div><div><span>  </span><span>.box</span><span> {</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>background-color: </span><span>blue</span><span>;</span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>20</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>现代 CSS 还支持范围比较语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/* 视口宽度在 768px ~ 1199px 之间 */</span></div></div><div><div><div>2</div></div><div><span>@media</span><span> (</span><span><span>768</span><span>px</span></span><span><span> </span><span>&lt;=</span><span> width </span><span>&lt;</span><span> </span></span><span><span>1200</span><span>px</span></span><span>) {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>.box</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>width: </span><span><span>80</span><span>%</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>媒体查询中的逻辑</strong>：媒体查询支持通过逻辑运算符组合多个条件。</p>

<table><thead><tr><th>逻辑</th><th>说明</th></tr></thead><tbody><tr><td><code>and</code></td><td>逻辑与，所有条件满足时生效</td></tr><tr><td><code>not</code></td><td>逻辑非，对查询条件取反</td></tr><tr><td><code>or</code></td><td>逻辑或，任意条件满足时生效</td></tr><tr><td><code>,</code></td><td>逗号分隔多个查询，效果类似逻辑或</td></tr><tr><td><code>only</code></td><td>主要用于旧浏览器兼容，现代开发通常不需要</td></tr></tbody></table><p>使用示例：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/* 屏幕设备，并且视口宽度 &gt;= 768px */</span></div></div><div><div><div>2</div></div><div><span>@media</span><span> </span><span>screen</span><span><span> </span><span>and</span><span> (min-width: </span></span><span><span>768</span><span>px</span></span><span>) {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>.box</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>width: </span><span><span>50</span><span>%</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>/* 768px &lt;= 视口宽度 &lt;= 1200px */</span></div></div><div><div><div>9</div></div><div><span>@media</span><span> (min-width: </span><span><span>768</span><span>px</span></span><span><span>) </span><span>and</span><span> (max-width: </span></span><span><span>1200</span><span>px</span></span><span>) {</span></div></div><div><div><div>10</div></div><div><span>  </span><span>.box</span><span> {</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>width: </span><span><span>80</span><span>%</span></span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>/* 非打印模式 */</span></div></div><div><div><div>16</div></div><div><span>@media</span><span><span> </span><span>not</span><span> </span></span><span>print</span><span> {</span></div></div><div><div><div>17</div></div><div><span>  </span><span>.box</span><span> {</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>display: </span><span>block</span><span>;</span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>20</div></div><div><span>}</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>/* 不满足视口宽度 &gt;= 768px 的情况 */</span></div></div><div><div><div>23</div></div><div><span>@media</span><span><span> </span><span>not</span><span> </span></span><span>all</span><span><span> </span><span>and</span><span> (min-width: </span></span><span><span>768</span><span>px</span></span><span>) {</span></div></div><div><div><div>24</div></div><div><span>  </span><span>.box</span><span> {</span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>26</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>27</div></div><div><span>}</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>/* 与上面的 or 示例效果相同 */</span></div></div><div><div><div>30</div></div><div><span>@media</span><span> (max-width: </span><span><span>767</span><span>px</span></span><span><span>), (orientation: </span><span>landscape</span><span>) {</span></span></div></div><div><div><div>31</div></div><div><span>  </span><span>.box</span><span> {</span></div></div><div><div><div>32</div></div><div><span><span>    </span></span><span>background-color: </span><span>red</span><span>;</span></div></div><div><div><div>33</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>34</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h2>断点和书写位置<a href="#断点和书写位置"><span>#</span></a></h2><p>**响应式断点：**断点（Breakpoint）是指页面布局需要发生变化时，对应的视口宽度。</p><p>常见的参考断点：</p>

<table><thead><tr><th>视口宽度</th><th>参考设备类型</th></tr></thead><tbody><tr><td><code>&lt; 768px</code></td><td>手机等窄屏设备</td></tr><tr><td><code>768px ~ 1023px</code></td><td>平板等中等宽度设备</td></tr><tr><td><code>1024px ~ 1199px</code></td><td>小型桌面屏幕</td></tr><tr><td><code>&gt;= 1200px</code></td><td>大型桌面屏幕</td></tr></tbody></table><p>这些不是 CSS 强制规定的断点，而是开发中常见的参考值。实际项目应该根据页面布局需求选择断点。</p><p><strong>媒体查询的书写位置</strong>：媒体查询既可以写在 <code>&lt;style&gt;</code> 标签中，也可以写在外部 CSS 文件中。还有一种不推荐的写法，就是link的时候使用媒体查询，但是如果按照上面的断点，至少要写4份样式，然后媒体查询加载不同样式，需要注意的是，这不是按需加载，网页加载的时候会一起加载</p></section><section><h2>媒体查询的策略<a href="#媒体查询的策略"><span>#</span></a></h2><p>媒体查询的策略主要分为3种：无策略，移动端优先、PC优先，最终实现的效果是一样，无策略可能需要写逻辑判断，想到哪写到哪，移动端优先是从小的尺寸写到大，pc则是大写到小，一般情况下推荐使用移动端优先，下面通过一个示例演示：</p><div><div>index.htmlindex.cssfirstmoblie.csspc.css</div><div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"row"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"col"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>      </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"./images/1.png"</span><span> </span><span>alt</span><span>=</span><span>""</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"col"</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>      </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"./images/1.png"</span><span> </span><span>alt</span><span>=</span><span>""</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"col"</span><span>&gt;</span></div></div><div><div><div>9</div></div><div><span><span>      </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"./images/1.png"</span><span> </span><span>alt</span><span>=</span><span>""</span><span>&gt;</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"col"</span><span>&gt;</span></div></div><div><div><div>12</div></div><div><span><span>      </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"./images/1.png"</span><span> </span><span>alt</span><span>=</span><span>""</span><span>&gt;</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"col"</span><span>&gt;</span></div></div><div><div><div>15</div></div><div><span><span>      </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"./images/1.png"</span><span> </span><span>alt</span><span>=</span><span>""</span><span>&gt;</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"col"</span><span>&gt;</span></div></div><div><div><div>18</div></div><div><span><span>      </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"./images/1.png"</span><span> </span><span>alt</span><span>=</span><span>""</span><span>&gt;</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>20</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"col"</span><span>&gt;</span></div></div><div><div><div>21</div></div><div><span><span>      </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"./images/1.png"</span><span> </span><span>alt</span><span>=</span><span>""</span><span>&gt;</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"col"</span><span>&gt;</span></div></div><div><div><div>24</div></div><div><span><span>      </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"./images/1.png"</span><span> </span><span>alt</span><span>=</span><span>""</span><span>&gt;</span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>26</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"col"</span><span>&gt;</span></div></div><div><div><div>27</div></div><div><span><span>      </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"./images/1.png"</span><span> </span><span>alt</span><span>=</span><span>""</span><span>&gt;</span></div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>29</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"col"</span><span>&gt;</span></div></div><div><div><div>30</div></div><div><span><span>      </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"./images/1.png"</span><span> </span><span>alt</span><span>=</span><span>""</span><span>&gt;</span></div></div><div><div><div>31</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>32</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"col"</span><span>&gt;</span></div></div><div><div><div>33</div></div><div><span><span>      </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"./images/1.png"</span><span> </span><span>alt</span><span>=</span><span>""</span><span>&gt;</span></div></div><div><div><div>34</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>35</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"col"</span><span>&gt;</span></div></div><div><div><div>36</div></div><div><span><span>      </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"./images/1.png"</span><span> </span><span>alt</span><span>=</span><span>""</span><span>&gt;</span></div></div><div><div><div>37</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>38</div></div><div><span><span>  </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></div><div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/* 无策略 */</span></div></div><div><div><div>2</div></div><div><span>@media</span><span>(max-width: </span><span><span>576</span><span>px</span></span><span>) {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>.col</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>        </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>@media</span><span>(min-width: </span><span><span>576</span><span>px</span></span><span><span>)</span><span>and</span><span> (max-width: </span></span><span><span>768</span><span>px</span></span><span>) {</span></div></div><div><div><div>9</div></div><div><span>    </span><span>.col</span><span> {</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>width: </span><span><span>50</span><span>%</span></span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>@media</span><span>(min-width: </span><span><span>768</span><span>px</span></span><span><span>)</span><span>and</span><span> (max-width: </span></span><span><span>992</span><span>px</span></span><span>) {</span></div></div><div><div><div>15</div></div><div><span>    </span><span>.col</span><span> {</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>width: </span><span><span>25</span><span>%</span></span><span>;</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>@media</span><span>(min-width: </span><span><span>992</span><span>px</span></span><span><span>)</span><span>and</span><span> (max-width: </span></span><span><span>1200</span><span>px</span></span><span>) {</span></div></div><div><div><div>21</div></div><div><span>    </span><span>.col</span><span> {</span></div></div><div><div><div>22</div></div><div><span><span>        </span></span><span>width: </span><span><span>16.66667</span><span>%</span></span><span>;</span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>24</div></div><div><span>}</span></div></div><div><div><div>25</div></div><div>
</div></div><div><div><div>26</div></div><div><span>@media</span><span>(min-width: </span><span><span>1200</span><span>px</span></span><span>) {</span></div></div><div><div><div>27</div></div><div><span>    </span><span>.col</span><span> {</span></div></div><div><div><div>28</div></div><div><span><span>        </span></span><span>width: </span><span><span>8.3333</span><span>%</span></span><span>;</span></div></div><div><div><div>29</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>30</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></div><div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span> </span><span>/* 移动端优先 */</span></div></div><div><div><div>2</div></div><div><span>    </span><span>.col</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>      </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>    </span><span>@media</span><span>(min-width: </span><span><span>576</span><span>px</span></span><span>) {</span></div></div><div><div><div>7</div></div><div><span>      </span><span>.col</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>width: </span><span><span>50</span><span>%</span></span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>    </span><span>@media</span><span>(min-width: </span><span><span>768</span><span>px</span></span><span>) {</span></div></div><div><div><div>13</div></div><div><span>      </span><span>.col</span><span> {</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>width: </span><span><span>25</span><span>%</span></span><span>;</span></div></div><div><div><div>15</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>    </span><span>@media</span><span>(min-width: </span><span><span>992</span><span>px</span></span><span>) {</span></div></div><div><div><div>19</div></div><div><span>      </span><span>.col</span><span> {</span></div></div><div><div><div>20</div></div><div><span><span>        </span></span><span>width: </span><span><span>16.66667</span><span>%</span></span><span>;</span></div></div><div><div><div>21</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>    </span><span>@media</span><span>(min-width: </span><span><span>1200</span><span>px</span></span><span>) {</span></div></div><div><div><div>25</div></div><div><span>      </span><span>.col</span><span> {</span></div></div><div><div><div>26</div></div><div><span><span>        </span></span><span>width: </span><span><span>8.3333</span><span>%</span></span><span>;</span></div></div><div><div><div>27</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></div><div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/* pc端优先 */</span></div></div><div><div><div>2</div></div><div><span>.col</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>width: </span><span><span>8.3333</span><span>%</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>@media</span><span>(max-width: </span><span><span>1200</span><span>px</span></span><span>) {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>.col</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>width: </span><span><span>16.66667</span><span>%</span></span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>@media</span><span>(max-width:</span><span><span>992</span><span>px</span></span><span>) {</span></div></div><div><div><div>13</div></div><div><span>    </span><span>.col</span><span> {</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>width: </span><span><span>25</span><span>%</span></span><span>;</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>16</div></div><div><span>}</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>@media</span><span>(max-width:</span><span><span>768</span><span>px</span></span><span>) {</span></div></div><div><div><div>19</div></div><div><span>    </span><span>.col</span><span> {</span></div></div><div><div><div>20</div></div><div><span><span>        </span></span><span>width: </span><span><span>50</span><span>%</span></span><span>;</span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>22</div></div><div><span>}</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>@media</span><span>(max-width:</span><span><span>576</span><span>px</span></span><span>) {</span></div></div><div><div><div>25</div></div><div><span>    </span><span>.col</span><span> {</span></div></div><div><div><div>26</div></div><div><span><span>        </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>27</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>28</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></div></div></section></section>
<section><h1>实战<a href="#实战"><span>#</span></a></h1><p>使用媒体查询的方式实现rem布局，去掉之前的js代码，改为媒体查询监听改变html上font-size的字体大小：</p><p>github代码仓库：<a href="https://github.com/youzi177/css-layout-lab" target="_blank">https://github.com/youzi177/css-layout-lab</a></p></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026101501rem-he-vw-bu-ju/</id>
      <title type="text">rem和vw布局</title>
      <published>2026-10-15T07:07:02.000Z</published>
      <updated>2026-10-15T07:07:02.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026101501rem-he-vw-bu-ju/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>前言<a href="#前言"><span>#</span></a></h1><p>在学习本章之前，应该先建立一个概念，rem属于旧的布局方案，vw属于新的布局解决方案，rem和vw属于旧往新迁移的方案，当然这不是说rem完全淘汰，因为使用rem的存量项目基数庞大，rem布局依然非常有效，但是如果新项目，完全可以使用vw来布局</p><p>需要注意的是，这里说的是布局方案，并不是rem一点不用，而是rem用在字体相关上，不用在布局上，需要强调的是，在现代 CSS 布局的最佳实践，是根据实际需求综合使用不同的布局技术和尺寸单位，而不是依赖某一种方案解决所有问题。例如这里的rem和vw布局，解决的是等比例缩放问题，但是这个这里还不是响应式，移动端网页如果直接pc打开，会非常丑陋，需要借助媒体查询来改变一些布局样式。</p><p>另外一个如果使用px和媒体查询可以吗，答案也是可以，但是px属于绝对单位，媒体查询会较为复杂，在断点与断点之间是不会有变化的，而使用vw却可以天然支持动态变化（这里的断点，不是指调试的断点，而是页面在某个宽度下样式发生变化，断点可以自己随意设置，但是按照经验之谈，可以基本划分几个区间，如一些CSS框架就有断点区间，需要注意断点不是CSS规定死的，而是一种约定俗成的东西）</p><p>在一些教学视频中，会经常出现两个工具库：postcss-pxtorem和postcss-px-to-viewport，它们是将项目写的px转为rem或者vw，同样的转为rem，就需要写js脚本去动态修改html下的字体大小，vw是根据视口的，它们都有一个配置文件，来配置需要设置转换属性、忽略规则和适用范围，因为不能全部的px转为rem或者vw，如边框、图标、固定控件未必需要等比例缩放</p></section>
<section><h1>rem布局方案<a href="#rem布局方案"><span>#</span></a></h1><section><h2>原理<a href="#原理"><span>#</span></a></h2><p><code>em</code>（root em）是 CSS 中的相对长度单位，它的大小取决于根元素 <code>html</code> 的 <code>font-size</code>。</p><p>rem 布局的核心原理：通过 JavaScript 根据视口宽度动态修改 <code>html</code> 的 <code>font-size</code>，使使用 rem 单位的元素随屏幕宽度等比例缩放。</p><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>html</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>10</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>width: </span><span><span>10</span><span>rem</span></span><span>;  </span><span>/* 100px */</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>height: </span><span><span>5</span><span>rem</span></span><span>; </span><span>/* 50px */</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>当 <code>html</code> 的 <code>font-size</code> 变成 <code>5px</code> 时：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>html</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>5</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>元素的实际尺寸随之改变：</p><ul>
<li>宽度：10 × 5 = 50px</li>
<li>高度：5 × 5 = 25px</li>
</ul><p>因此，只需要动态调整根元素的字体大小，就能控制所有使用 <code>rem</code> 单位的元素尺寸。</p></section><section><h2>实现<a href="#实现"><span>#</span></a></h2><p>以 <code>750px</code> 宽度的移动端设计稿为例，实现底部 Tabbar 的等比例缩放。确定设计稿的基准值，假设设计稿尺寸：</p><ul>
<li>设计稿宽度：750px</li>
<li>Tabbar 高度：96px</li>
</ul><p>为了方便计算，规定设计稿中：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>1rem = 10px</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>那么：</p><p>[ 750 \div 10 = 75rem ]</p><p>Tabbar 的高度：</p><p>[ 96 \div 10 = 9.6rem ]</p><p>因此，我们需要在不同屏幕下始终保持：</p><p>[ htmlFontSize = \frac{viewWidth}{75} ]</p><p><strong>动态设置根元素字体大小</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>docEl</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>documentElement</span><span>;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>const</span><span> </span><span>setHtmlFontSize</span><span> </span><span>=</span><span> () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span>  </span><span>const</span><span> </span><span>viewWidth</span><span> </span><span>=</span><span><span> </span><span>docEl</span><span>.</span></span><span>clientWidth</span><span>;</span></div></div><div><div><div>5</div></div><div><span>  </span><span>const</span><span> </span><span>htmlFontSize</span><span> </span><span>=</span><span><span> </span><span>viewWidth</span><span> </span></span><span>/</span><span> </span><span>75</span><span>;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>docEl</span><span>.</span><span>style</span><span>.</span><span>fontSize</span><span> </span><span>=</span><span><span> </span><span>htmlFontSize</span><span> </span></span><span>+</span><span> </span><span>'px'</span><span>;</span></div></div><div><div><div>8</div></div><div><span>};</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>setHtmlFontSize</span><span>();</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span><span>window</span><span>.</span></span><span>addEventListener</span><span>(</span><span>'resize'</span><span><span>, </span><span>setHtmlFontSize</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>代码说明：</p><ul>
<li><code>document.documentElement</code>：获取根元素 <code>html</code>。</li>
<li><code>clientWidth</code>：获取当前布局视口宽度。</li>
<li><code>viewWidth / 75</code>：计算当前屏幕对应的根字体大小。</li>
<li><code>style.fontSize</code>：动态设置 <code>html</code> 的字体大小。</li>
<li><code>resize</code>：视口宽度变化时重新计算。</li>
</ul><p><strong>不同屏幕下的缩放效果</strong></p>

<table><thead><tr><th>视口宽度</th><th>html font-size</th><th>Tabbar 高度</th></tr></thead><tbody><tr><td>320px</td><td>4.267px</td><td>40.96px</td></tr><tr><td>375px</td><td>5px</td><td>48px</td></tr><tr><td>390px</td><td>5.2px</td><td>49.92px</td></tr><tr><td>414px</td><td>5.52px</td><td>52.99px</td></tr><tr><td>750px</td><td>10px</td><td>96px</td></tr></tbody></table><p><strong>完整实现</strong></p><div><div><div><figure><figcaption><span>index.html</span><span>展开</span><span>收起</span></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!</span><span>DOCTYPE</span><span> </span><span>html</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>html</span><span> </span><span>lang</span><span>=</span><span>"zh-CN"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>head</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>meta</span><span> </span><span>charset</span><span>=</span><span>"UTF-8"</span><span> /&gt;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>&lt;</span><span>meta</span></div></div><div><div><div>6</div></div><div><span>      </span><span>name</span><span>=</span><span>"viewport"</span></div></div><div><div><div>7</div></div><div><span>      </span><span>content</span><span>=</span><span>"width=device-width, initial-scale=1.0"</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>/&gt;</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>&lt;</span><span>title</span><span>&gt;rem 布局方案&lt;/</span><span>title</span><span>&gt;</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>12</div></div><div><span>      </span><span>*</span><span> {</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>box-sizing: </span><span>border-box</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>      </span><span>body</span><span> {</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>margin: </span><span>0</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>        </span></span><span>font-size: </span><span><span>16</span><span>px</span></span><span>;</span></div></div><div><div><div>19</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>      </span><span>.tabbar-layout</span><span> {</span></div></div><div><div><div>22</div></div><div><span><span>        </span></span><span>position: </span><span>fixed</span><span>;</span></div></div><div><div><div>23</div></div><div><span><span>        </span></span><span>bottom: </span><span>0</span><span>;</span></div></div><div><div><div>24</div></div><div><span><span>        </span></span><span>left: </span><span>0</span><span>;</span></div></div><div><div><div>25</div></div><div><span><span>        </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>26</div></div><div><span><span>        </span></span><span>height: </span><span><span>9.6</span><span>rem</span></span><span>;</span></div></div><div><div><div>27</div></div><div><span><span>        </span></span><span>box-shadow: </span><span>0</span><span> </span><span><span>-4</span><span>px</span></span><span> </span><span><span>4</span><span>px</span></span><span> </span><span>rgba</span><span>(</span><span>0</span><span>, </span><span>0</span><span>, </span><span>0</span><span>, </span><span>0.15</span><span>);</span></div></div><div><div><div>28</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>29</div></div><div>
</div></div><div><div><div>30</div></div><div><span>      </span><span>.tabbar-layout</span><span> </span><span>img</span><span> {</span></div></div><div><div><div>31</div></div><div><span><span>        </span></span><span>display: </span><span>block</span><span>;</span></div></div><div><div><div>32</div></div><div><span><span>        </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>33</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>34</div></div><div><span><span>    </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span><span>    </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>37</div></div><div><span>      </span><span>const</span><span> </span><span>docEl</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>documentElement</span><span>;</span></div></div><div><div><div>38</div></div><div>
</div></div><div><div><div>39</div></div><div><span>      </span><span>const</span><span> </span><span>setHtmlFontSize</span><span> </span><span>=</span><span> () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>40</div></div><div><span>        </span><span>const</span><span> </span><span>viewWidth</span><span> </span><span>=</span><span><span> </span><span>docEl</span><span>.</span></span><span>clientWidth</span><span>;</span></div></div><div><div><div>41</div></div><div><span>        </span><span>const</span><span> </span><span>htmlFontSize</span><span> </span><span>=</span><span><span> </span><span>viewWidth</span><span> </span></span><span>/</span><span> </span><span>75</span><span>;</span></div></div><div><div><div>42</div></div><div>
</div></div><div><div><div>43</div></div><div><span><span>        </span></span><span>docEl</span><span>.</span><span>style</span><span>.</span><span>fontSize</span><span> </span><span>=</span><span><span> </span><span>htmlFontSize</span><span> </span></span><span>+</span><span> </span><span>'px'</span><span>;</span></div></div><div><div><div>44</div></div><div><span><span>      </span></span><span>};</span></div></div><div><div><div>45</div></div><div>
</div></div><div><div><div>46</div></div><div><span>      </span><span>setHtmlFontSize</span><span>();</span></div></div><div><div><div>47</div></div><div>
</div></div><div><div><div>48</div></div><div><span><span>      </span></span><span>window</span><span>.</span><span>addEventListener</span><span>(</span><span>'resize'</span><span><span>, </span><span>setHtmlFontSize</span><span>);</span></span></div></div><div><div><div>49</div></div><div><span><span>    </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>50</div></div><div><span><span>  </span></span><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>51</div></div><div>
</div></div><div><div><div>52</div></div><div><span><span>  </span></span><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>53</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;段落&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>54</div></div><div>
</div></div><div><div><div>55</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"tabbar-layout"</span><span>&gt;</span></div></div><div><div><div>56</div></div><div><span><span>      </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"./tabbar.png"</span><span> </span><span>alt</span><span>=</span><span>"标签栏"</span><span> /&gt;</span></div></div><div><div><div>57</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>58</div></div><div><span><span>  </span></span><span>&lt;/</span><span>body</span><span>&gt;</span></div></div><div><div><div>59</div></div><div><span>&lt;/</span><span>html</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>这里有两个值得注意的地方：</p><p>第一，<code>body</code> 使用 <code>font-size: 16px</code>，因此段落文字不会随着根元素字体大小的变化而等比例缩放。这可以避免文字随着屏幕宽度无限放大或缩小。</p><p>第二，Tabbar 使用 <code>width: 100%</code>，高度使用 <code>rem</code>。也可以将宽度设置为 <code>75rem</code>，但当前情况下使用百分比更简单。</p></section><section><h2>扩展flexible<a href="#扩展flexible"><span>#</span></a></h2><p><strong>什么是 flexible？</strong></p><p><code>lib-flexible</code> 是阿里巴巴移动前端团队推出的一套移动端适配方案，主要用于实现基于 <code>rem</code> 的等比例布局。</p><p>GitHub：<a href="https://github.com/amfe/lib-flexible" target="_blank">amfe/lib-flexible</a></p><p>它的核心功能与前面手写的 JavaScript 一样：根据视口宽度，自动设置根元素 <code>html</code> 的 <code>font-size</code>。</p><p>不过，它采用了不同的换算规则。</p><p><strong>flexible 的计算原理</strong></p><p>flexible 经典的计算方式是将视口宽度划分为 10 份：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const docEl = document.documentElement;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>const setRemUnit = () =&gt; {</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>const rem = docEl.clientWidth / 10;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>docEl.style.fontSize = rem + 'px';</span></div></div><div><div><div>7</div></div><div><span>};</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>以 <code>750px</code> 设计稿为例：</p><p>[ 750 \div 10 = 75px ]</p><p>因此：</p><p><code>1rem = 75px</code>（设计稿基准下）</p><p>Tabbar 高度为 <code>96px</code>，换算为：</p><p>[ 96 \div 75 = 1.28rem ]</p><p>CSS：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.tabbar-layout {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: 100%;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>height: 1.28rem;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这样在 <code>375px</code> 的视口下：</p><p>[ 1.28 \times (375 \div 10) = 48px ]</p><p><strong>flexible 与手写方案的区别</strong></p>

<table><thead><tr><th>对比项</th><th>手写方案</th><th>flexible</th></tr></thead><tbody><tr><td>根字体计算</td><td>视口宽度 ÷ 75</td><td>视口宽度 ÷ 10</td></tr><tr><td>750px 视口下 1rem</td><td>10px</td><td>75px</td></tr><tr><td>96px 设计尺寸</td><td>9.6rem</td><td>1.28rem</td></tr><tr><td>核心机制</td><td>动态修改 font-size</td><td>动态修改 font-size</td></tr><tr><td>缩放效果</td><td>等比例缩放</td><td>等比例缩放</td></tr></tbody></table><p>两者没有本质区别，只是采用了不同的 rem 换算基准。</p></section><section><h2>拓展-VScode插件<a href="#拓展-vscode插件"><span>#</span></a></h2><p>在开发中，会计算rem的值，这非常麻烦，这里推荐一个插件px2rem</p></section></section>
<section><h1>vw+rem布局方案<a href="#vwrem布局方案"><span>#</span></a></h1><section><h2>原理<a href="#原理-1"><span>#</span></a></h2><p><code>rem + vw</code> 布局方案结合了两种单位的特点：</p><ul>
<li>vw：根据视口宽度动态计算根元素的字体大小。</li>
<li>rem：根据根元素的字体大小计算元素尺寸。</li>
</ul><p>核心原理：使用 <code>vw</code> 动态设置 <code>html</code> 的 <code>font-size</code>，再使用 <code>rem</code> 实现元素的等比例缩放。</p><p>与传统的 JS + rem 方案相比，不再需要 JavaScript 动态计算根元素字体大小，而是直接通过 CSS 实现。</p></section><section><h2>实现<a href="#实现-1"><span>#</span></a></h2><p>假设设计稿宽度为 <code>750px</code>，规定在设计稿宽度下：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>1rem = 100px</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>那么：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>html {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>font-size: calc(100vw / 7.5);</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>计算结果：</p>

<table><thead><tr><th>视口宽度</th><th>html 的 font-size</th><th>1rem</th></tr></thead><tbody><tr><td>320px</td><td>42.67px</td><td>42.67px</td></tr><tr><td>375px</td><td>50px</td><td>50px</td></tr><tr><td>414px</td><td>55.2px</td><td>55.2px</td></tr><tr><td>750px</td><td>100px</td><td>100px</td></tr></tbody></table><p>例如设计稿中的底部导航栏宽度为 <code>750px</code>，高度为 <code>96px</code>。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!</span><span>DOCTYPE</span><span> </span><span>html</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>html</span><span> </span><span>lang</span><span>=</span><span>"zh-CN"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;</span><span>head</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>&lt;</span><span>meta</span><span> </span><span>charset</span><span>=</span><span>"UTF-8"</span><span> /&gt;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>&lt;</span><span>meta</span><span> </span><span>name</span><span>=</span><span>"viewport"</span><span> </span><span>content</span><span>=</span><span>"width=device-width, initial-scale=1.0"</span><span> /&gt;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>&lt;</span><span>title</span><span>&gt;rem + vw 布局方案&lt;/</span><span>title</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span>    </span><span>*</span><span> {</span></div></div><div><div><div>9</div></div><div><span><span>      </span></span><span>box-sizing: </span><span>border-box</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>    </span><span>html</span><span> {</span></div></div><div><div><div>13</div></div><div><span><span>      </span></span><span>font-size: </span><span>calc</span><span>(</span><span><span>100</span><span>vw</span></span><span><span> </span><span>/</span><span> </span></span><span>7.5</span><span>);</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>    </span><span>body</span><span> {</span></div></div><div><div><div>17</div></div><div><span><span>      </span></span><span>margin: </span><span>0</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>      </span></span><span>font-size: </span><span><span>16</span><span>px</span></span><span>;</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>    </span><span>.tabbar-layout</span><span> {</span></div></div><div><div><div>22</div></div><div><span><span>      </span></span><span>position: </span><span>fixed</span><span>;</span></div></div><div><div><div>23</div></div><div><span><span>      </span></span><span>bottom: </span><span>0</span><span>;</span></div></div><div><div><div>24</div></div><div><span><span>      </span></span><span>left: </span><span>0</span><span>;</span></div></div><div><div><div>25</div></div><div><span><span>      </span></span><span>width: </span><span><span>7.5</span><span>rem</span></span><span>;</span></div></div><div><div><div>26</div></div><div><span><span>      </span></span><span>height: </span><span><span>0.96</span><span>rem</span></span><span>;</span></div></div><div><div><div>27</div></div><div><span><span>      </span></span><span>background-color: </span><span>#</span><span>eee</span><span>;</span></div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>29</div></div><div><span><span>  </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>30</div></div><div><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>31</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>32</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"tabbar-layout"</span><span>&gt;底部导航栏&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>33</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div><div><div><div>34</div></div><div><span>&lt;/</span><span>html</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>在不同设备下：</p>

<table><thead><tr><th>视口宽度</th><th>导航栏宽度</th><th>导航栏高度</th></tr></thead><tbody><tr><td>320px</td><td>320px</td><td>40.96px</td></tr><tr><td>375px</td><td>375px</td><td>48px</td></tr><tr><td>414px</td><td>414px</td><td>52.99px</td></tr><tr><td>750px</td><td>750px</td><td>96px</td></tr></tbody></table><p>最终实现：视口宽度发生变化时，<code>rem</code> 对应的像素值自动变化，从而实现元素等比例缩放。</p></section><section><h2>怎么计算<a href="#怎么计算"><span>#</span></a></h2><p><strong>为什么是 100vw / 7.5？</strong></p><p>假设：</p><ul>
<li>设计稿宽度：<code>750px</code></li>
<li>规定在设计稿宽度下：<code>1rem = 100px</code></li>
</ul><p>首先：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>100vw = 750px /* 当视口宽度为 750px 时 */</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>那么，要让根元素的 <code>font-size</code> 等于 <code>100px</code>：</p><p>[ 750 \div 7.5 = 100 ]</p><p>所以：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>html {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>font-size: calc(100vw / 7.5);</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其中 <code>7.5</code> 的来源就是：</p><p>[ 7.5 = \frac{750}{100} ]</p><p><strong>如果 1rem = 10px 呢？</strong></p><p>设计稿还是 <code>750px</code>，只是将基准改为：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>1rem = 10px</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>那么：</p><p>[ 750 \div 10 = 75 ]</p><p>代码变成：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>html {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>font-size: calc(100vw / 75);</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>对比一下：</p>

<table><thead><tr><th>视口宽度</th><th>1rem = 100px 方案</th><th>1rem = 10px 方案</th></tr></thead><tbody><tr><td>320px</td><td>42.67px</td><td>4.27px</td></tr><tr><td>375px</td><td>50px</td><td>5px</td></tr><tr><td>750px</td><td>100px</td><td>10px</td></tr></tbody></table><p>这里的 <code>1rem = 100px</code> 和 <code>1rem = 10px</code> 都是指设计稿对应的 750px 视口宽度下的值，并不是在所有屏幕下固定不变。</p><p><strong>通用计算公式</strong></p><p>例如设计稿宽度为 <code>750px</code>：</p><p>除数=设计稿宽度 /  设计稿设定的1rem像素值</p>

<table><thead><tr><th>设定的 1rem</th><th>计算过程</th><th>CSS</th></tr></thead><tbody><tr><td>100px</td><td>750 ÷ 100 = 7.5</td><td><code>calc(100vw / 7.5)</code></td></tr><tr><td>50px</td><td>750 ÷ 50 = 15</td><td><code>calc(100vw / 15)</code></td></tr><tr><td>10px</td><td>750 ÷ 10 = 75</td><td><code>calc(100vw / 75)</code></td></tr></tbody></table></section></section>
<section><h1>vw布局方案<a href="#vw布局方案"><span>#</span></a></h1><section><h2>原理<a href="#原理-2"><span>#</span></a></h2><p><code>vw</code> 是 CSS 的视口相对单位，<code>1vw</code> 等于视口宽度的 <code>1%</code>。</p><p>vw 布局方案的核心原理：将设计稿中的 px 单位换算为 vw，让元素尺寸随着视口宽度变化而等比例缩放。</p><p>例如：</p>

<table><thead><tr><th>视口宽度</th><th>1vw</th><th>10vw</th></tr></thead><tbody><tr><td>320px</td><td>3.2px</td><td>32px</td></tr><tr><td>375px</td><td>3.75px</td><td>37.5px</td></tr><tr><td>750px</td><td>7.5px</td><td>75px</td></tr></tbody></table><p><strong>换算公式</strong></p><p>[ vw = \frac{设计稿中元素的尺寸}{设计稿宽度}\times100 ]</p><p>假设设计稿宽度为 <code>750px</code>，其中一个元素的高度为 <code>96px</code>。</p><p>[ \frac{96}{750}\times100=12.8vw ]</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.tabbar {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>height: 12.8vw;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>实际效果：</p>

<table><thead><tr><th>视口宽度</th><th>元素高度</th></tr></thead><tbody><tr><td>320px</td><td>40.96px</td></tr><tr><td>375px</td><td>48px</td></tr><tr><td>750px</td><td>96px</td></tr></tbody></table><p>因此，元素能够根据视口宽度进行等比例缩放。</p></section><section><h2>实现<a href="#实现-2"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!</span><span>DOCTYPE</span><span> </span><span>html</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>html</span><span> </span><span>lang</span><span>=</span><span>"en"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>&lt;</span><span>head</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>&lt;</span><span>meta</span><span> </span><span>charset</span><span>=</span><span>"UTF-8"</span><span> /&gt;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>&lt;</span><span>meta</span><span> </span><span>name</span><span>=</span><span>"viewport"</span><span> </span><span>content</span><span>=</span><span>"width=device-width, initial-scale=1.0"</span><span> /&gt;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>&lt;</span><span>title</span><span>&gt;VW 布局方案&lt;/</span><span>title</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>9</div></div><div><span>    </span><span>img</span><span> {</span></div></div><div><div><div>10</div></div><div><span><span>      </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>    </span><span>body</span><span> {</span></div></div><div><div><div>13</div></div><div><span><span>      </span></span><span>font-size: </span><span><span>16</span><span>px</span></span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span>    </span><span>.tabbar-layout</span><span> {</span></div></div><div><div><div>16</div></div><div><span><span>      </span></span><span>position: </span><span>fixed</span><span>;</span></div></div><div><div><div>17</div></div><div><span><span>      </span></span><span>bottom: </span><span>0</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>      </span></span><span>left: </span><span>0</span><span>;</span></div></div><div><div><div>19</div></div><div><span><span>      </span></span><span>box-shadow: </span><span>0</span><span> </span><span><span>-.4</span><span>rem</span></span><span> </span><span><span>.4</span><span>rem</span></span><span> </span><span>rgba</span><span>(</span><span>0</span><span>, </span><span>0</span><span>, </span><span>0</span><span>, </span><span>0.15</span><span>);</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>      </span><span>/* width: 100%;</span></div></div><div><div><div>22</div></div><div><span><span>      </span></span><span>height: 48px; */</span></div></div><div><div><div>23</div></div><div><span><span>      </span></span><span>width: </span><span><span>100</span><span>vw</span></span><span>;</span></div></div><div><div><div>24</div></div><div><span><span>      </span></span><span>height: </span><span><span>12.88</span><span>vw</span></span><span>;</span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>26</div></div><div><span><span>  </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>27</div></div><div><span><span>  </span></span><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span><span>  </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>30</div></div><div><span><span>  </span></span><span>&lt;</span><span>script</span><span>&gt;</span></div></div><div><div><div>31</div></div><div><span>    </span><span>// 计算vw单位的值，以750px为基准</span></div></div><div><div><div>32</div></div><div><span>    </span><span>// 100vw = 750px</span></div></div><div><div><div>33</div></div><div><span>    </span><span>// 测量的ox/750px(基准) = ?VW/100vw</span></div></div><div><div><div>34</div></div><div><span>    </span><span>// ?VW = (测量的px/750px(基准)) * 100vw</span></div></div><div><div><div>35</div></div><div><span><span>  </span></span><span>&lt;/</span><span>script</span><span>&gt;</span></div></div><div><div><div>36</div></div><div><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>37</div></div><div>
</div></div><div><div><div>38</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>39</div></div><div><span><span>  </span></span><span>&lt;</span><span>p</span><span>&gt;段落&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>40</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"tabbar-layout"</span><span>&gt;</span></div></div><div><div><div>41</div></div><div><span><span>    </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"./tabbar.png"</span><span> </span><span>alt</span><span>=</span><span>"标签栏"</span><span> /&gt;</span></div></div><div><div><div>42</div></div><div><span><span>  </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>43</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div><div><div><div>44</div></div><div>
</div></div><div><div><div>45</div></div><div><span>&lt;/</span><span>html</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h2>拓展-VScode插件<a href="#拓展-vscode插件-1"><span>#</span></a></h2><p>在开发中，会计算rem的值，这非常麻烦，这里推荐一个插件px2rem</p></section></section>
<section><h1>实战<a href="#实战"><span>#</span></a></h1><p>结合以上三种方案，修改之前的仿慕课网首页</p><p>github代码仓库：<a href="https://github.com/youzi177/css-layout-lab" target="_blank">https://github.com/youzi177/css-layout-lab</a></p></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026101401flex-tan-xing-bu-ju/</id>
      <title type="text">Flex弹性布局</title>
      <published>2026-10-14T08:57:35.000Z</published>
      <updated>2026-10-14T08:57:35.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026101401flex-tan-xing-bu-ju/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>前言<a href="#前言"><span>#</span></a></h1><p>关于flex布局，网上有很多教程，但是这里记录一下我自己学习中容易踩坑的点：flex布局里面的主轴和交叉轴，不能简单的理解为横竖轴，如果映入这个想法，很容易弄混，增加学习的难度，主轴就是默认的排列方向，默认是横向，当然可以改为竖向，这时候主轴就是竖的，初学很容易就卡这一步了，什么乱七八糟横竖主轴交叉轴，所以只要记住主轴交叉轴就可以；</p><p>关于flex概念，只要设置一个<code>display：flex</code>，那这个<strong>元素就自动成为flex容器</strong>，里面的<strong>子元素就是flex项目</strong>，flex主要分为<strong>容器属性</strong>和<strong>项目属性</strong>，以上这句话包括了很多重点，只要明白flex容器，flex项目，以及它们各自属性基本就能使用flex布局了</p></section>
<section><h1>Flex基础知识<a href="#flex基础知识"><span>#</span></a></h1><p><strong>什么是flex布局</strong>：是 CSS 提供的一种一维布局方式，主要用于控制元素在水平或垂直方向上的排列、对齐、间距和伸缩。任何一个HTML元素都可以指定为flex布局；</p><p><strong>什么是flex容器</strong>：设置了 <code>display: flex</code> 或 <code>display: inline-flex</code> 的元素就是flex容器</p><p><strong>什么是flex项目</strong>：Flex 容器中的直接子元素。需要注意：只有 Flex 容器的直接子元素会成为 Flex 项目。Flex 项目的内部元素不会自动成为该容器的 Flex 项目。Flex 容器本身也可以同时是另一个 Flex 容器的 Flex 项目。</p><p><strong>什么是主轴，什么是交叉轴</strong>：主轴（Main Axis）：Flex 项目主要排列的方向，由 <code>flex-direction</code> 决定。交叉轴（Cross Axis）：与主轴垂直的方向。主轴不一定是水平方向，交叉轴也不一定是垂直方向。</p></section>
<section><h1>Flex容器的属性<a href="#flex容器的属性"><span>#</span></a></h1><section><h2>修改主轴方向<a href="#修改主轴方向"><span>#</span></a></h2><p><code>flex-direction</code> 用于设置 Flex 容器的主轴方向，决定 Flex 项目沿哪个方向排列。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>flex-direction: </span><span>row</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>row</code></td><td>默认值，主轴为水平方向，通常从左向右排列</td></tr><tr><td><code>row-reverse</code></td><td>主轴为水平方向，通常从右向左排列</td></tr><tr><td><code>column</code></td><td>主轴为垂直方向，通常从上向下排列</td></tr><tr><td><code>column-reverse</code></td><td>主轴为垂直方向，通常从下向上排列</td></tr></tbody></table></section><section><h2>是否换行<a href="#是否换行"><span>#</span></a></h2><p><code>flex-wrap</code> 用于设置当 Flex 项目在主轴方向上排列空间不足时，是否允许换行。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>flex-wrap: </span><span>wrap</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>nowrap</code></td><td>默认值，不换行</td></tr><tr><td><code>wrap</code></td><td>允许换行</td></tr><tr><td><code>wrap-reverse</code></td><td>允许换行，交叉轴的起止方向反转</td></tr></tbody></table><p>注意：</p><ul>
<li><code>nowrap</code> 并不代表子元素绝对不会超出容器，空间不足时，项目可能被压缩，也可能溢出。</li>
<li><code>wrap</code> 只是允许换行，并不保证一定换行。</li>
<li>当 <code>flex-direction: column</code> 时，换行表现为排列到新的列，通常需要容器有明确的高度限制才能观察到</li>
</ul></section><section><h2>简写属性<a href="#简写属性"><span>#</span></a></h2><p><code>flex-flow</code> 是 <code>flex-direction</code> 和 <code>flex-wrap</code> 的简写属性。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>flex-flow: </span><span>row</span><span> </span><span>wrap</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>等价于：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>flex-direction: </span><span>row</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>flex-wrap: </span><span>wrap</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>常见写法：</p>

<table><thead><tr><th>写法</th><th>说明</th></tr></thead><tbody><tr><td><code>flex-flow: row nowrap</code></td><td>默认值，水平排列，不换行</td></tr><tr><td><code>flex-flow: row wrap</code></td><td>水平排列，允许换行</td></tr><tr><td><code>flex-flow: column wrap</code></td><td>垂直排列，允许换列</td></tr><tr><td><code>flex-flow: row-reverse wrap</code></td><td>水平反向排列，允许换行</td></tr></tbody></table><p>注意： <code>flex-flow</code> 只负责排列方向和换行，与控制 Flex 项目自身伸缩的 <code>flex</code> 属性不同。</p></section><section><h2>主轴对齐方式<a href="#主轴对齐方式"><span>#</span></a></h2><p><code>justify-content</code> 用于控制 Flex 项目在主轴方向上的对齐方式以及剩余空间分配。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>justify-content: </span><span>center</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>flex-start</code></td><td>默认值，向主轴起点对齐</td></tr><tr><td><code>flex-end</code></td><td>向主轴终点对齐</td></tr><tr><td><code>center</code></td><td>在主轴上居中</td></tr><tr><td><code>space-between</code></td><td>首尾项目贴近两端，其余空间分布在项目之间</td></tr><tr><td><code>space-around</code></td><td>每个项目两侧分配相等空间，外侧间距为内部间距的一半</td></tr><tr><td><code>space-evenly</code></td><td>所有相邻间距与两端间距相等</td></tr></tbody></table><p>注意：</p><ul>
<li><code>justify-content</code> 控制的是主轴，不一定是水平方向。</li>
<li>当 <code>flex-direction: column</code> 时，它控制垂直方向的对齐。</li>
<li><strong>如果项目已经占满主轴可用空间，<code>space-between</code> 等空间分配方式可能看不出效果。</strong></li>
<li>当存在多行项目时，<code>justify-content</code> 会分别作用于每一行。</li>
</ul></section><section><h2>交叉轴对齐方式<a href="#交叉轴对齐方式"><span>#</span></a></h2><p><code>align-items</code> 用于控制 Flex 项目在交叉轴方向上的对齐方式。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: flex;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>align-items: center;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>normal</code></td><td>默认值，在常规 Flex 场景中通常表现为 <code>stretch</code></td></tr><tr><td><code>stretch</code></td><td>在交叉轴尺寸为 <code>auto</code> 等适用条件下拉伸项目</td></tr><tr><td><code>flex-start</code></td><td>向交叉轴起点对齐</td></tr><tr><td><code>flex-end</code></td><td>向交叉轴终点对齐</td></tr><tr><td><code>center</code></td><td>在交叉轴上居中</td></tr><tr><td><code>baseline</code></td><td>沿项目的基线对齐，通常用于文字</td></tr></tbody></table><p>注意：</p><ul>
<li><code>align-items</code> 控制交叉轴，不一定是垂直方向。</li>
<li>对多行 Flex 容器，它控制每一行内部项目的交叉轴对齐方式。</li>
<li><code>stretch</code> 不是无条件拉伸。如果项目已经设置固定高度（横向主轴时），通常不会被拉伸。</li>
</ul></section><section><h2>多行交叉轴对齐方式<a href="#多行交叉轴对齐方式"><span>#</span></a></h2><p><code>align-content</code> 用于控制 Flex 容器中多行项目在交叉轴方向上的整体排列及剩余空间分配。</p><p>与 <code>align-items</code> 不同，它操作的重点是多条 Flex 行，而不是每个项目自身。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>flex-wrap: </span><span>wrap</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>height: </span><span><span>300</span><span>px</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>align-content: </span><span>space-between</span><span>;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>normal</code></td><td>默认值，在 Flex 中通常表现为 <code>stretch</code></td></tr><tr><td><code>stretch</code></td><td>拉伸 Flex 行以填充交叉轴的剩余空间</td></tr><tr><td><code>flex-start</code></td><td>多行整体靠交叉轴起点</td></tr><tr><td><code>flex-end</code></td><td>多行整体靠交叉轴终点</td></tr><tr><td><code>center</code></td><td>多行整体在交叉轴居中</td></tr><tr><td><code>space-between</code></td><td>首尾行靠两端，其余行均匀分布</td></tr><tr><td><code>space-around</code></td><td>每行两侧分配相等空间</td></tr><tr><td><code>space-evenly</code></td><td>各行间距与两端间距相等</td></tr></tbody></table><p>注意：</p><ol>
<li>Flex 容器必须是多行，<code>align-content</code> 才能影响 Flex 行的排列。通常需要设置 <code>flex-wrap: wrap</code>。</li>
<li>交叉轴方向需要有可供分配的剩余空间，才能明显观察 <code>center</code>、<code>space-between</code> 等效果。</li>
<li><code>align-content: stretch</code> 拉伸的是 Flex 行，项目是否随之拉伸还受到 <code>align-items</code> 和项目尺寸的影响。</li>
</ol></section><section><h2>align-items 和 align-content 的区别<a href="#align-items-和-align-content-的区别"><span>#</span></a></h2><p>这是 Flex 布局中比较容易混淆的两个属性。</p>

<table><thead><tr><th>对比</th><th><code>align-items</code></th><th><code>align-content</code></th></tr></thead><tbody><tr><td>主要控制对象</td><td>每条 Flex 行内的项目</td><td>整体的 Flex 行</td></tr><tr><td>作用方向</td><td>交叉轴</td><td>交叉轴</td></tr><tr><td>是否要求多行</td><td>否</td><td>是</td></tr><tr><td>典型用途</td><td>项目垂直居中</td><td>多行内容整体垂直居中</td></tr></tbody></table><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>flex-flow: </span><span>row</span><span> </span><span>wrap</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>height: </span><span><span>300</span><span>px</span></span><span>;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>  </span><span>/* 每一行内部项目居中 */</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>align-items: </span><span>center</span><span>;</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>  </span><span>/* 所有行作为整体居中 */</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>align-content: </span><span>center</span><span>;</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>两者可以同时设置，作用并不冲突。</p></section><section><h2>记忆方式<a href="#记忆方式"><span>#</span></a></h2><ul>
<li><code>flex-direction</code>：决定往哪个方向排。</li>
<li><code>flex-wrap</code>：决定排不下是否换行。</li>
<li><code>flex-flow</code>：前面两个属性的简写。</li>
<li><code>justify-content</code>：控制主轴上的对齐。</li>
<li><code>align-items</code>：控制交叉轴上每行项目的对齐。</li>
<li><code>align-content</code>：控制交叉轴上多行项目的整体分布。</li>
</ul><p>实际开发中，最常使用的是 <code>flex-direction</code>、<code>justify-content</code>、<code>align-items</code> 和 <code>flex-wrap</code>。其中 <code>align-content</code> 通常在多行布局中才需要重点考虑。</p></section></section>
<section><h1>Flex项目的属性<a href="#flex项目的属性"><span>#</span></a></h1><section><h2>排列顺序：order<a href="#排列顺序order"><span>#</span></a></h2><p><code>order</code> 用于控制 Flex 项目的视觉排列顺序，数值越小，排列越靠前。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>order: </span><span>0</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>0</code></td><td>默认值</td></tr><tr><td>正整数</td><td>数值越大，排列越靠后</td></tr><tr><td>负整数</td><td>数值越小，排列越靠前</td></tr></tbody></table><p>示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item1</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>order: </span><span>2</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>.item2</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>order: </span><span>0</span><span>;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>.item3</span><span> {</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>order: </span><span>-1</span><span>;</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意： <code>order</code> 只影响视觉顺序，不会改变 HTML 中的 DOM 顺序，也不会相应改变键盘焦点和通常的屏幕阅读器阅读顺序，因此不应该用它替代有语义要求的内容排序。</p></section><section><h2>放大比例：flex-grow<a href="#放大比例flex-grow"><span>#</span></a></h2><p><code>flex-grow</code> 用于控制 Flex 项目如何分配主轴方向上的剩余空间。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>flex-grow: </span><span>0</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>0</code></td><td>默认值，不主动分配剩余空间</td></tr><tr><td><code>1</code></td><td>参与剩余空间分配</td></tr><tr><td><code>2</code></td><td>在其他条件相同的情况下，分得 <code>1</code> 的两倍剩余空间</td></tr><tr><td>其他非负数</td><td>按增长因子分配剩余空间</td></tr></tbody></table><p>示例：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>width: </span><span><span>500</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>.item</span><span> {</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>flex-basis: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>.item1</span><span> {</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>flex-grow: </span><span>1</span><span>;</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>.item2</span><span> {</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>flex-grow: </span><span>2</span><span>;</span></div></div><div><div><div>16</div></div><div><span>}</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>.item3</span><span> {</span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>flex-grow: </span><span>1</span><span>;</span></div></div><div><div><div>20</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>三个项目的基础宽度都是 <code>100px</code>，容器宽度 <code>500px</code>，剩余空间为 <code>200px</code>。增长因子比例为 <code>1 : 2 : 1</code>，所以剩余空间分别分配 <code>50px</code>、<code>100px</code>、<code>50px</code>。</p><p>注意：</p><ul>
<li><code>flex-grow</code> 分配的是剩余空间，并不是直接决定最终宽度比例。</li>
<li>只有主轴有可分配的正剩余空间时，才会发生增长。</li>
<li>实际结果还受 <code>flex-basis</code>、<code>min-width</code>、<code>max-width</code> 等条件影响。</li>
</ul></section><section><h2>缩小比例：flex-shrink<a href="#缩小比例flex-shrink"><span>#</span></a></h2><p><code>flex-shrink</code> 用于控制 Flex 项目在主轴空间不足时如何收缩。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>flex-shrink: </span><span>1</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>1</code></td><td>默认值，允许收缩</td></tr><tr><td><code>0</code></td><td>不参与 Flex 收缩</td></tr><tr><td><code>2</code></td><td>相同基础尺寸等条件下，收缩分配权重是 <code>1</code> 的两倍</td></tr><tr><td>其他非负数</td><td>按收缩因子参与收缩</td></tr></tbody></table><p>示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>width: </span><span><span>450</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>.item</span><span> {</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>width: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>flex-shrink: </span><span>1</span><span>;</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>三个项目的原始宽度合计为 <code>600px</code>，但容器只有 <code>450px</code>。因此，满足收缩条件时，三个项目会分别缩小到 <code>150px</code>。</p><p>如果不希望项目被 Flex 收缩：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>flex-shrink: </span><span>0</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>此时三个项目的宽度不会因 Flex 的收缩算法而减小，可能溢出容器。</p><p>注意：</p><ul>
<li><code>flex-shrink</code> 默认值为 <code>1</code>，这也是 Flex 项目宽度有时小于设置值的原因。</li>
<li>收缩空间按 <code>flex-shrink × flex-basis</code> 等规则计算，并不是单纯按 <code>flex-shrink</code> 数值比例缩小。</li>
<li>Flex 项目默认的 <code>min-width: auto</code> 可能阻止进一步收缩，必要时可设置 <code>min-width: 0</code>。</li>
</ul></section><section><h2>基础尺寸：flex-basis<a href="#基础尺寸flex-basis"><span>#</span></a></h2><p><code>flex-basis</code> 用于<strong>指定 Flex 项目</strong>在分配剩余空间或进行收缩之前的<strong>主轴基础尺寸</strong>。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>flex-basis: auto;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>auto</code></td><td>默认值，通常参考主轴方向对应的 <code>width</code> 或 <code>height</code>，否则依据内容确定尺寸</td></tr><tr><td><code>100px</code></td><td>主轴基础尺寸为 <code>100px</code></td></tr><tr><td><code>30%</code></td><td>根据 Flex 容器相应主轴尺寸计算百分比基础尺寸</td></tr><tr><td><code>content</code></td><td>根据项目内容确定基础尺寸</td></tr><tr><td><code>0</code></td><td>基础尺寸设为零，仍受最小尺寸等约束</td></tr></tbody></table><p>示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: flex;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>.item {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>width: 200px;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>flex-basis: 100px;</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>当 <code>flex-direction: row</code> 时，<code>flex-basis: 100px</code> 会优先作为 Flex 项目的主轴基础宽度，而不是使用 <code>width: 200px</code>。</p><p>但最终宽度仍可能因为 Flex 伸缩和尺寸限制而发生变化。</p><p>注意：</p><ul>
<li>主轴水平时，<code>flex-basis</code> 主要对应宽度。</li>
<li>主轴垂直时，<code>flex-basis</code> 主要对应高度。</li>
<li><code>flex-basis</code> 不等于最终尺寸，而是 Flex 布局计算的基础尺寸。</li>
</ul></section><section><h2>简写属性：flex<a href="#简写属性flex"><span>#</span></a></h2><p><code>flex</code> 是 <code>flex-grow</code>、<code>flex-shrink</code> 和 <code>flex-basis</code> 的简写属性。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>flex: 0 1 auto;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>等价于：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>flex-grow: 0;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>flex-shrink: 1;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>flex-basis: auto;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>常见写法</p>

<table><thead><tr><th>写法</th><th>等价含义</th><th>说明</th></tr></thead><tbody><tr><td><code>flex: initial</code></td><td><code>0 1 auto</code></td><td>默认行为，不增长、允许收缩</td></tr><tr><td><code>flex: none</code></td><td><code>0 0 auto</code></td><td>不增长、不收缩</td></tr><tr><td><code>flex: auto</code></td><td><code>1 1 auto</code></td><td>基于自动基础尺寸进行伸缩</td></tr><tr><td><code>flex: 1</code></td><td>浏览器中通常展开为 <code>1 1 0%</code></td><td>参与弹性空间分配</td></tr><tr><td><code>flex: 2</code></td><td>浏览器中通常展开为 <code>2 1 0%</code></td><td>xxxxxxxxxx /* 网站 Banner <em>/.banner {  height: 400px;  background: url(“/images/banner.jpg”) center / cover no-repeat;}​/</em> 卡片渐变背景 <em>/.card {  background: linear-gradient(135deg, #667eea, #764ba2);}​/</em> 渐变文字 */.title {  background: linear-gradient(to right, #00c6ff, #0072ff);  background-clip: text;  color: transparent;}css</td></tr><tr><td><code>flex: 1 1 200px</code></td><td><code>1 1 200px</code></td><td>基础尺寸 200px，可增长、可收缩</td></tr></tbody></table></section><section><h2>单独对齐方式：align-self<a href="#单独对齐方式align-self"><span>#</span></a></h2><p><code>align-self</code> 用于控制单个 Flex 项目在交叉轴方向上的对齐方式，可以覆盖 Flex 容器设置的 <code>align-items</code>。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.item {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>align-self: auto;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>auto</code></td><td>默认值，采用父级 <code>align-items</code> 的对齐方式</td></tr><tr><td><code>normal</code></td><td>在普通 Flex 场景中通常表现为 <code>stretch</code></td></tr><tr><td><code>stretch</code></td><td>满足条件时沿交叉轴拉伸</td></tr><tr><td><code>flex-start</code></td><td>交叉轴起点对齐</td></tr><tr><td><code>flex-end</code></td><td>交叉轴终点对齐</td></tr><tr><td><code>center</code></td><td>交叉轴居中</td></tr><tr><td><code>baseline</code></td><td>基线对齐</td></tr></tbody></table><p>示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: </span><span>flex</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>height: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>align-items: </span><span>flex-start</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>.item2</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>align-self: </span><span>center</span><span>;</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>.item3</span><span> {</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>align-self: </span><span>flex-end</span><span>;</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意：</p><ul>
<li><code>align-self</code> 控制交叉轴，不能直接控制主轴上的单个项目对齐。</li>
<li><code>align-self: auto</code> 是采用父容器的对齐方式，并不是通过 CSS 属性继承实现的。</li>
<li>若项目在交叉轴上存在 <code>auto</code> 外边距，可能覆盖 <code>align-self</code> 的对齐效果。</li>
</ul></section><section><h2>Flex 项目属性总结<a href="#flex-项目属性总结"><span>#</span></a></h2>

<table><thead><tr><th>属性</th><th>作用</th><th>默认值</th></tr></thead><tbody><tr><td><code>order</code></td><td>控制项目视觉排列顺序</td><td><code>0</code></td></tr><tr><td><code>flex-grow</code></td><td>控制正剩余空间的分配</td><td><code>0</code></td></tr><tr><td><code>flex-shrink</code></td><td>控制空间不足时的收缩</td><td><code>1</code></td></tr><tr><td><code>flex-basis</code></td><td>指定伸缩计算前的基础尺寸</td><td><code>auto</code></td></tr><tr><td><code>flex</code></td><td>前面三个伸缩属性的简写</td><td><code>0 1 auto</code></td></tr><tr><td><code>align-self</code></td><td>控制单个项目交叉轴对齐</td><td><code>auto</code></td></tr></tbody></table><p>实际开发应该重点掌握什么？</p><p>这六个属性可以分为四类：</p><ul>
<li>顺序控制：<code>order</code></li>
<li>弹性尺寸控制：<code>flex-grow</code>、<code>flex-shrink</code>、<code>flex-basis</code>、<code>flex</code></li>
<li>单独对齐：<code>align-self</code></li>
</ul><p>其中，日常开发最值得重点掌握的是 <code>flex</code>、<code>flex-shrink</code> 和 <code>align-self</code>。</p><p>尤其需要理解：<code>flex-grow</code> 分配剩余空间，<code>flex-shrink</code> 处理空间不足，<code>flex-basis</code> 提供计算的基础尺寸。 这三个属性共同决定 Flex 项目在主轴方向上的最终尺寸，而不是彼此独立地控制宽高。</p></section></section>
<section><h1>Flex实战<a href="#flex实战"><span>#</span></a></h1><section><h2>圣杯布局<a href="#圣杯布局"><span>#</span></a></h2><p>github代码仓库：<a href="https://github.com/youzi177/css-layout-lab" target="_blank">https://github.com/youzi177/css-layout-lab</a></p></section><section><h2>慕课网首页改造<a href="#慕课网首页改造"><span>#</span></a></h2><p>github代码仓库：<a href="https://github.com/youzi177/css-layout-lab" target="_blank">https://github.com/youzi177/css-layout-lab</a></p></section></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026101301css3-liu-shi-bu-ju/</id>
      <title type="text">CSS3流式布局</title>
      <published>2026-10-13T08:22:52.000Z</published>
      <updated>2026-10-13T08:22:52.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026101301css3-liu-shi-bu-ju/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>前言<a href="#前言"><span>#</span></a></h1><p>在学习CSS的布局之前，需要知道的一点是，不是一种布局，一个测量单位从头用尾，而是视情况使用，结合使用才是最终方案，每个布局和测量单位都有不同应用场景，而非谁淘汰谁，当然这其中会存在一些新方案和旧方案，比如rem和vw布局，在以前的项目中，可能会用到rem，但是现在新项目推荐使用vw，因为rem需要使用js动态计算，而vw是相对于视口计算，少了js，页面性能就更好，所以rem布局可以了解认识使用，但是新项目采用vw方案，理清思路之后，学习第一个布局流式布局，流体布局并不是一个完全独立新知识，所以这里会用一个demo演示，再后续的布局中，也会基于这个修改</p></section>
<section><h1>仿慕课网首页<a href="#仿慕课网首页"><span>#</span></a></h1><section><h2>页面结构布局<a href="#页面结构布局"><span>#</span></a></h2><p>基础骨架和<code>reset.css</code></p><div><div>index.htmlreset.css</div><div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!</span><span>DOCTYPE</span><span> </span><span>html</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>html</span><span> </span><span>lang</span><span>=</span><span>"en"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;</span><span>head</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>&lt;</span><span>meta</span><span> </span><span>charset</span><span>=</span><span>"UTF-8"</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>&lt;</span><span>meta</span><span> </span><span>name</span><span>=</span><span>"viewport"</span><span> </span><span>content</span><span>=</span><span>"width=device-width, initial-scale=1.0"</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>&lt;</span><span>title</span><span>&gt;仿慕课网首页-流体布局&lt;/</span><span>title</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>&lt;</span><span>link</span><span> </span><span>rel</span><span>=</span><span>"stylesheet"</span><span> </span><span>href</span><span>=</span><span>"../../../styles/reset.css"</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>9</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>10</div></div><div><span>  </span><span>&lt;!-- 头部 --&gt;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>&lt;</span><span>header</span><span> </span><span>class</span><span>=</span><span>"header-layout"</span><span>&gt;头部&lt;/</span><span>header</span><span>&gt;</span></div></div><div><div><div>12</div></div><div><span>  </span><span>&lt;!-- 主体 --&gt;</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"main-layout"</span><span>&gt;</span></div></div><div><div><div>14</div></div><div><span>    </span><span>&lt;!-- 幻灯片 --&gt;</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"slider-layout"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>16</div></div><div><span>    </span><span>&lt;!-- 免费课程 --&gt;</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"course-layout"</span><span>&gt;免费课程&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>18</div></div><div><span>    </span><span>&lt;!-- 实战课程 --&gt;</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"course-layout"</span><span>&gt;实战课程&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>21</div></div><div><span>  </span><span>&lt;!-- 标签栏 --&gt;</span></div></div><div><div><div>22</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"tabbar-layout"</span><span>&gt;标签栏&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>23</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div><div><div><div>24</div></div><div><span>&lt;/</span><span>html</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></div><div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>*</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>padding: </span><span>0</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>margin: </span><span>0</span><span>;</span></div></div><div><div><div>4</div></div><div><span>  </span><span>/* 防止盒子溢出 */</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>box-sizing: </span><span>border-box</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>outline: </span><span>0</span><span>;</span></div></div><div><div><div>7</div></div><div><span>  </span><span>/* 取消点击的时候高亮 */</span></div></div><div><div><div>8</div></div><div><span>  </span><span>-webkit-tap-highlight-color</span><span><span>: </span><span>transparent</span><span>;</span></span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div><span>a</span><span> {</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>text-decoration: </span><span>none</span><span>;</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div><span>li</span><span> {</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>list-style: </span><span>none</span><span>;</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div><div><div><div>16</div></div><div><span>img</span><span> {</span></div></div><div><div><div>17</div></div><div><span>  </span><span>/* display: block; */</span></div></div><div><div><div>18</div></div><div><span>  </span><span>/* 图片铺满容器 */</span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>vertical-align: </span><span>top</span><span>;</span></div></div><div><div><div>20</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></div></div><p>布局layout样式</p><div><div><div><figure><figcaption><span>layout.css</span><span>展开</span><span>收起</span></figcaption><pre><code><div><div><div>1</div></div><div><span>.header-layout</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>position: </span><span>fixed</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>left: </span><span>0</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>top: </span><span>0</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>height: </span><span><span>48</span><span>px</span></span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>background-color: </span><span>red</span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>border-bottom: </span><span><span>1</span><span>px</span></span><span><span> </span><span>solid</span><span> </span></span><span>#</span><span>e8e8e8</span><span>;</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>.main-layout</span><span> {</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>padding: </span><span><span>48</span><span>px</span></span><span> </span><span>0</span><span> </span><span><span>48</span><span>px</span></span><span> </span><span>0</span><span>;</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>.slider-layout</span><span> {</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>height: </span><span><span>134</span><span>px</span></span><span>;</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>background-color: </span><span>green</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>  </span></span><span>margin-bottom: </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>19</div></div><div><span>}</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>.course-layout</span><span> {</span></div></div><div><div><div>22</div></div><div><span><span>  </span></span><span>height: </span><span><span>382</span><span>px</span></span><span>;</span></div></div><div><div><div>23</div></div><div><span><span>  </span></span><span>background-color: </span><span>gray</span><span>;</span></div></div><div><div><div>24</div></div><div><span><span>  </span></span><span>margin-bottom: </span><span><span>10</span><span>px</span></span><span>;</span></div></div><div><div><div>25</div></div><div><span>}</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>.tabbar-layout</span><span> {</span></div></div><div><div><div>28</div></div><div><span><span>  </span></span><span>position: </span><span>fixed</span><span>;</span></div></div><div><div><div>29</div></div><div><span><span>  </span></span><span>left: </span><span>0</span><span>;</span></div></div><div><div><div>30</div></div><div><span><span>  </span></span><span>bottom: </span><span>0</span><span>;</span></div></div><div><div><div>31</div></div><div><span><span>  </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>32</div></div><div><span><span>  </span></span><span>height: </span><span><span>48</span><span>px</span></span><span>;</span></div></div><div><div><div>33</div></div><div><span><span>  </span></span><span>background-color: </span><span>yellow</span><span>;</span></div></div><div><div><div>34</div></div><div><span><span>  </span></span><span>box-shadow: </span><span>0</span><span> </span><span><span>-4</span><span>px</span></span><span> </span><span><span>4</span><span>px</span></span><span> </span><span>rgba</span><span>(</span><span>0</span><span>, </span><span>0</span><span>, </span><span>0</span><span>, </span><span>0.15</span><span>);</span></div></div><div><div><div>35</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h2>头部<a href="#头部"><span>#</span></a></h2><div><div>index.htmlheader.css</div><div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>  </span><span>&lt;!-- 头部 --&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>header</span><span> </span><span>class</span><span>=</span><span>"header-layout"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"header"</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>      </span><span>&lt;!-- logo --&gt;</span></div></div><div><div><div>5</div></div><div><span><span>      </span></span><span>&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>""</span><span> </span><span>class</span><span>=</span><span>"header-logo"</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>        </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"../../../public/images/logo.png"</span><span> </span><span>alt</span><span>=</span><span>"logo"</span><span> </span><span>class</span><span>=</span><span>"header-logo-img"</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span><span>      </span></span><span>&lt;/</span><span>a</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span>      </span><span>&lt;!-- 下拉框按钮 --&gt;</span></div></div><div><div><div>9</div></div><div><span><span>      </span></span><span>&lt;</span><span>button</span><span> </span><span>id</span><span>=</span><span>"header-toggle"</span><span> </span><span>class</span><span>=</span><span>"header-toggle"</span><span>&gt;</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>&lt;</span><span>span</span><span> </span><span>class</span><span>=</span><span>"header-toggle-bar"</span><span>&gt;&lt;/</span><span>span</span><span>&gt;</span></div></div><div><div><div>11</div></div><div><span><span>        </span></span><span>&lt;</span><span>span</span><span> </span><span>class</span><span>=</span><span>"header-toggle-bar"</span><span>&gt;&lt;/</span><span>span</span><span>&gt;</span></div></div><div><div><div>12</div></div><div><span><span>        </span></span><span>&lt;</span><span>span</span><span> </span><span>class</span><span>=</span><span>"header-toggle-bar"</span><span>&gt;&lt;/</span><span>span</span><span>&gt;</span></div></div><div><div><div>13</div></div><div><span><span>      </span></span><span>&lt;/</span><span>button</span><span>&gt;</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>&lt;/</span><span>header</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></div><div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.header</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>height: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>background-color: </span><span>#</span><span>fff</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>padding: </span><span>0</span><span> </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>.header-logo</span><span> {</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>float: </span><span>left</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>height: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>.header-logo-img</span><span> {</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>height: </span><span><span>30</span><span>px</span></span><span>;</span></div></div><div><div><div>15</div></div><div><span>  </span><span>/* 居中=48-9-9-30，总高度48，图30，上外边距9，下外边距刚好也是9 */</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>margin-top: </span><span><span>9</span><span>px</span></span><span>;</span></div></div><div><div><div>17</div></div><div><span>}</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>.header-toggle</span><span> {</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>float: </span><span>right</span><span>;</span></div></div><div><div><div>21</div></div><div><span><span>  </span></span><span>padding: </span><span><span>10</span><span>px</span></span><span>;</span></div></div><div><div><div>22</div></div><div><span><span>  </span></span><span>background-color: </span><span>transparent</span><span>;</span></div></div><div><div><div>23</div></div><div><span><span>  </span></span><span>border: </span><span>none</span><span>;</span></div></div><div><div><div>24</div></div><div><span><span>  </span></span><span>border-radius: </span><span><span>4</span><span>px</span></span><span>;</span></div></div><div><div><div>25</div></div><div><span><span>  </span></span><span>margin-top: </span><span><span>4</span><span>px</span></span><span>;</span></div></div><div><div><div>26</div></div><div><span>}</span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span>.header-toggle-bar</span><span> {</span></div></div><div><div><div>29</div></div><div><span><span>  </span></span><span>display: </span><span>block</span><span>;</span></div></div><div><div><div>30</div></div><div><span><span>  </span></span><span>width: </span><span><span>24</span><span>px</span></span><span>;</span></div></div><div><div><div>31</div></div><div><span><span>  </span></span><span>height: </span><span><span>4</span><span>px</span></span><span>;</span></div></div><div><div><div>32</div></div><div><span><span>  </span></span><span>background-color: </span><span>#</span><span>363636</span><span>;</span></div></div><div><div><div>33</div></div><div><span><span>  </span></span><span>border-radius: </span><span><span>2</span><span>px</span></span><span>;</span></div></div><div><div><div>34</div></div><div><span>}</span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span>.header-toggle-bar</span><span> </span><span>+</span><span> </span><span>.header-toggle-bar</span><span> {</span></div></div><div><div><div>37</div></div><div><span><span>  </span></span><span>margin-top: </span><span><span>4</span><span>px</span></span><span>;</span></div></div><div><div><div>38</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></div></div></section><section><h2>主体部分<a href="#主体部分"><span>#</span></a></h2><p>幻灯片部分</p><div><div>index.htmlslider.css</div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span> </span><span>&lt;!-- 幻灯片 --&gt;</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"slider-layout"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>      </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"../../../public/images/slider/1.jpg"</span><span> </span><span>alt</span><span>=</span><span>""</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div></div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span> </span><span>.slider-layout</span><span> </span><span>img</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>      </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></div></div><p>实战免费课程部分</p><div><div>index.htmlslider.css</div><div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>    </span><span>&lt;!-- 免费课程 --&gt;</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"course-layout"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>      </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"course"</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>        </span></span><span>&lt;</span><span>h2</span><span> </span><span>class</span><span>=</span><span>"course-title"</span><span>&gt;免费课程&lt;/</span><span>h2</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>&lt;</span><span>ul</span><span> </span><span>class</span><span>=</span><span>"course-list"</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>          </span></span><span>&lt;</span><span>li</span><span> </span><span>class</span><span>=</span><span>"course-item"</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span><span>            </span></span><span>&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"javascript:;"</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-pic"</span><span>&gt;</span></div></div><div><div><div>9</div></div><div><span><span>                </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"../../../public/images/course_free/1.jpg"</span><span> </span><span>alt</span><span>=</span><span>""</span><span> </span><span>class</span><span>=</span><span>"course-img"</span><span>&gt;</span></div></div><div><div><div>10</div></div><div><span><span>              </span></span><span>&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>11</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-name"</span><span>&gt;初始HTML5+CSS3 - 2026升级版&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>12</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-price"</span><span>&gt;免费&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>13</div></div><div><span><span>            </span></span><span>&lt;/</span><span>a</span><span>&gt;</span></div></div><div><div><div>14</div></div><div><span><span>          </span></span><span>&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>15</div></div><div><span><span>          </span></span><span>&lt;</span><span>li</span><span> </span><span>class</span><span>=</span><span>"course-item"</span><span>&gt;</span></div></div><div><div><div>16</div></div><div><span><span>            </span></span><span>&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"javascript:;"</span><span>&gt;</span></div></div><div><div><div>17</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-pic"</span><span>&gt;</span></div></div><div><div><div>18</div></div><div><span><span>                </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"../../../public/images/course_free/2.jpg"</span><span> </span><span>alt</span><span>=</span><span>""</span><span> </span><span>class</span><span>=</span><span>"course-img"</span><span>&gt;</span></div></div><div><div><div>19</div></div><div><span><span>              </span></span><span>&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>20</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-name"</span><span>&gt;初始HTML5+CSS3 - 2026升级版&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>21</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-price"</span><span>&gt;免费&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>22</div></div><div><span><span>            </span></span><span>&lt;/</span><span>a</span><span>&gt;</span></div></div><div><div><div>23</div></div><div><span><span>          </span></span><span>&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>24</div></div><div><span><span>          </span></span><span>&lt;</span><span>li</span><span> </span><span>class</span><span>=</span><span>"course-item"</span><span>&gt;</span></div></div><div><div><div>25</div></div><div><span><span>            </span></span><span>&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"javascript:;"</span><span>&gt;</span></div></div><div><div><div>26</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-pic"</span><span>&gt;</span></div></div><div><div><div>27</div></div><div><span><span>                </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"../../../public/images/course_free/3.jpg"</span><span> </span><span>alt</span><span>=</span><span>""</span><span> </span><span>class</span><span>=</span><span>"course-img"</span><span>&gt;</span></div></div><div><div><div>28</div></div><div><span><span>              </span></span><span>&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>29</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-name"</span><span>&gt;初始HTML5+CSS3 - 2026升级版&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>30</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-price"</span><span>&gt;免费&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>31</div></div><div><span><span>            </span></span><span>&lt;/</span><span>a</span><span>&gt;</span></div></div><div><div><div>32</div></div><div><span><span>          </span></span><span>&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>33</div></div><div><span><span>          </span></span><span>&lt;</span><span>li</span><span> </span><span>class</span><span>=</span><span>"course-item"</span><span>&gt;</span></div></div><div><div><div>34</div></div><div><span><span>            </span></span><span>&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"javascript:;"</span><span>&gt;</span></div></div><div><div><div>35</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-pic"</span><span>&gt;</span></div></div><div><div><div>36</div></div><div><span><span>                </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"../../../public/images/course_free/4.jpg"</span><span> </span><span>alt</span><span>=</span><span>""</span><span> </span><span>class</span><span>=</span><span>"course-img"</span><span>&gt;</span></div></div><div><div><div>37</div></div><div><span><span>              </span></span><span>&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>38</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-name"</span><span>&gt;初始HTML5+CSS3 - 2026升级版&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>39</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-price"</span><span>&gt;免费&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>40</div></div><div><span><span>            </span></span><span>&lt;/</span><span>a</span><span>&gt;</span></div></div><div><div><div>41</div></div><div><span><span>          </span></span><span>&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>42</div></div><div><span><span>        </span></span><span>&lt;/</span><span>ul</span><span>&gt;</span></div></div><div><div><div>43</div></div><div><span><span>      </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>44</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>45</div></div><div><span>    </span><span>&lt;!-- 实战课程 --&gt;</span></div></div><div><div><div>46</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"course-layout"</span><span>&gt;</span></div></div><div><div><div>47</div></div><div><span><span>      </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"course"</span><span>&gt;</span></div></div><div><div><div>48</div></div><div><span><span>        </span></span><span>&lt;</span><span>h2</span><span> </span><span>class</span><span>=</span><span>"course-title"</span><span>&gt;实战课程&lt;/</span><span>h2</span><span>&gt;</span></div></div><div><div><div>49</div></div><div><span><span>        </span></span><span>&lt;</span><span>ul</span><span> </span><span>class</span><span>=</span><span>"course-list"</span><span>&gt;</span></div></div><div><div><div>50</div></div><div><span><span>          </span></span><span>&lt;</span><span>li</span><span> </span><span>class</span><span>=</span><span>"course-item"</span><span>&gt;</span></div></div><div><div><div>51</div></div><div><span><span>            </span></span><span>&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"javascript:;"</span><span>&gt;</span></div></div><div><div><div>52</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-pic"</span><span>&gt;</span></div></div><div><div><div>53</div></div><div><span><span>                </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"../../../public/images/course_coding/1.jpg"</span><span> </span><span>alt</span><span>=</span><span>""</span><span> </span><span>class</span><span>=</span><span>"course-img"</span><span>&gt;</span></div></div><div><div><div>54</div></div><div><span><span>              </span></span><span>&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>55</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-name"</span><span>&gt;初始HTML5+CSS3 - 2026升级版&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>56</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-price"</span><span>&gt;实战&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>57</div></div><div><span><span>            </span></span><span>&lt;/</span><span>a</span><span>&gt;</span></div></div><div><div><div>58</div></div><div><span><span>          </span></span><span>&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>59</div></div><div><span><span>          </span></span><span>&lt;</span><span>li</span><span> </span><span>class</span><span>=</span><span>"course-item"</span><span>&gt;</span></div></div><div><div><div>60</div></div><div><span><span>            </span></span><span>&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"javascript:;"</span><span>&gt;</span></div></div><div><div><div>61</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-pic"</span><span>&gt;</span></div></div><div><div><div>62</div></div><div><span><span>                </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"../../../public/images/course_coding/2.jpg"</span><span> </span><span>alt</span><span>=</span><span>""</span><span> </span><span>class</span><span>=</span><span>"course-img"</span><span>&gt;</span></div></div><div><div><div>63</div></div><div><span><span>              </span></span><span>&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>64</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-name"</span><span>&gt;初始HTML5+CSS3 - 2026升级版&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>65</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-price"</span><span>&gt;实战&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>66</div></div><div><span><span>            </span></span><span>&lt;/</span><span>a</span><span>&gt;</span></div></div><div><div><div>67</div></div><div><span><span>          </span></span><span>&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>68</div></div><div><span><span>          </span></span><span>&lt;</span><span>li</span><span> </span><span>class</span><span>=</span><span>"course-item"</span><span>&gt;</span></div></div><div><div><div>69</div></div><div><span><span>            </span></span><span>&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"javascript:;"</span><span>&gt;</span></div></div><div><div><div>70</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-pic"</span><span>&gt;</span></div></div><div><div><div>71</div></div><div><span><span>                </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"../../../public/images/course_coding/3.jpg"</span><span> </span><span>alt</span><span>=</span><span>""</span><span> </span><span>class</span><span>=</span><span>"course-img"</span><span>&gt;</span></div></div><div><div><div>72</div></div><div><span><span>              </span></span><span>&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>73</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-name"</span><span>&gt;初始HTML5+CSS3 - 2026升级版&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>74</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-price"</span><span>&gt;实战&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>75</div></div><div><span><span>            </span></span><span>&lt;/</span><span>a</span><span>&gt;</span></div></div><div><div><div>76</div></div><div><span><span>          </span></span><span>&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>77</div></div><div><span><span>          </span></span><span>&lt;</span><span>li</span><span> </span><span>class</span><span>=</span><span>"course-item"</span><span>&gt;</span></div></div><div><div><div>78</div></div><div><span><span>            </span></span><span>&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"javascript:;"</span><span>&gt;</span></div></div><div><div><div>79</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-pic"</span><span>&gt;</span></div></div><div><div><div>80</div></div><div><span><span>                </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"../../../public/images/course_coding/4.png"</span><span> </span><span>alt</span><span>=</span><span>""</span><span> </span><span>class</span><span>=</span><span>"course-img"</span><span>&gt;</span></div></div><div><div><div>81</div></div><div><span><span>              </span></span><span>&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>82</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-name"</span><span>&gt;初始HTML5+CSS3 - 2026升级版&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>83</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-price"</span><span>&gt;实战&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>84</div></div><div><span><span>            </span></span><span>&lt;/</span><span>a</span><span>&gt;</span></div></div><div><div><div>85</div></div><div><span><span>          </span></span><span>&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>86</div></div><div><span><span>          </span></span><span>&lt;</span><span>li</span><span> </span><span>class</span><span>=</span><span>"course-item"</span><span>&gt;</span></div></div><div><div><div>87</div></div><div><span><span>            </span></span><span>&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"javascript:;"</span><span>&gt;</span></div></div><div><div><div>88</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-pic"</span><span>&gt;</span></div></div><div><div><div>89</div></div><div><span><span>                </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"../../../public/images/course_coding/5.png"</span><span> </span><span>alt</span><span>=</span><span>""</span><span> </span><span>class</span><span>=</span><span>"course-img"</span><span>&gt;</span></div></div><div><div><div>90</div></div><div><span><span>              </span></span><span>&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>91</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-name"</span><span>&gt;初始HTML5+CSS3 - 2026升级版&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>92</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-price"</span><span>&gt;实战&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>93</div></div><div><span><span>            </span></span><span>&lt;/</span><span>a</span><span>&gt;</span></div></div><div><div><div>94</div></div><div><span><span>          </span></span><span>&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>95</div></div><div><span><span>          </span></span><span>&lt;</span><span>li</span><span> </span><span>class</span><span>=</span><span>"course-item"</span><span>&gt;</span></div></div><div><div><div>96</div></div><div><span><span>            </span></span><span>&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"javascript:;"</span><span>&gt;</span></div></div><div><div><div>97</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-pic"</span><span>&gt;</span></div></div><div><div><div>98</div></div><div><span><span>                </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"../../../public/images/course_coding/6.png"</span><span> </span><span>alt</span><span>=</span><span>""</span><span> </span><span>class</span><span>=</span><span>"course-img"</span><span>&gt;</span></div></div><div><div><div>99</div></div><div><span><span>              </span></span><span>&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>100</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-name"</span><span>&gt;初始HTML5+CSS3 - 2026升级版&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>101</div></div><div><span><span>              </span></span><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"course-price"</span><span>&gt;实战&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>102</div></div><div><span><span>            </span></span><span>&lt;/</span><span>a</span><span>&gt;</span></div></div><div><div><div>103</div></div><div><span><span>          </span></span><span>&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>104</div></div><div><span><span>        </span></span><span>&lt;/</span><span>ul</span><span>&gt;</span></div></div><div><div><div>105</div></div><div><span><span>      </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>106</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></div><div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>    </span><span>.course</span><span> {</span></div></div><div><div><div>2</div></div><div><span>      </span><span>/* 清除浮动 */</span></div></div><div><div><div>3</div></div><div><span><span>      </span></span><span>overflow: </span><span>auto</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>      </span></span><span>font-size: </span><span><span>14</span><span>px</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>    </span><span>.course-title</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>      </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>      </span></span><span>padding: </span><span>0</span><span> </span><span>0</span><span> </span><span><span>10</span><span>px</span></span><span> </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>      </span></span><span>color: </span><span>#</span><span>191919</span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>      </span></span><span>font-size: </span><span><span>16</span><span>px</span></span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>    </span><span>.course-list</span><span> {</span></div></div><div><div><div>15</div></div><div><span><span>      </span></span><span>padding-right: </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>    </span><span>.course-item</span><span> {</span></div></div><div><div><div>19</div></div><div><span><span>      </span></span><span>float: </span><span>left</span><span>;</span></div></div><div><div><div>20</div></div><div><span><span>      </span></span><span>width: </span><span><span>50</span><span>%</span></span><span>;</span></div></div><div><div><div>21</div></div><div><span><span>      </span></span><span>padding: </span><span>0</span><span> </span><span>0</span><span> </span><span><span>10</span><span>px</span></span><span> </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>    </span><span>.course-pic</span><span> {</span></div></div><div><div><div>25</div></div><div><span><span>      </span></span><span>margin-bottom: </span><span><span>6</span><span>px</span></span><span>;</span></div></div><div><div><div>26</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span>    </span><span>.course-img</span><span> {</span></div></div><div><div><div>29</div></div><div><span>      </span><span>/* 相对于父容器的100% */</span></div></div><div><div><div>30</div></div><div><span><span>      </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>31</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>32</div></div><div>
</div></div><div><div><div>33</div></div><div><span>    </span><span>.course-name</span><span> {</span></div></div><div><div><div>34</div></div><div><span><span>      </span></span><span>height: </span><span><span>40</span><span>px</span></span><span>;</span></div></div><div><div><div>35</div></div><div><span><span>      </span></span><span>line-height: </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>36</div></div><div><span><span>      </span></span><span>margin-bottom: </span><span><span>4</span><span>px</span></span><span>;</span></div></div><div><div><div>37</div></div><div><span><span>      </span></span><span>color: </span><span>#</span><span>4d4d4d</span><span>;</span></div></div><div><div><div>38</div></div><div><span>      </span><span>/* 多行文字省略 */</span></div></div><div><div><div>39</div></div><div><span><span>      </span></span><span>overflow: </span><span>hidden</span><span>;</span></div></div><div><div><div>40</div></div><div><span><span>      </span></span><span>text-overflow: </span><span>ellipsis</span><span>;</span></div></div><div><div><div>41</div></div><div><span><span>      </span></span><span>display: </span><span>-webkit-box</span><span>;</span></div></div><div><div><div>42</div></div><div><span>      </span><span>-webkit-line-clamp</span><span>: </span><span>2</span><span>;</span></div></div><div><div><div>43</div></div><div><span><span>      </span></span><span>line-clamp: </span><span>2</span><span>;</span></div></div><div><div><div>44</div></div><div><span>      </span><span>-webkit-box-orient</span><span><span>: </span><span>vertical</span><span>;</span></span></div></div><div><div><div>45</div></div><div><span><span>      </span></span><span>white-space: </span><span>normal</span><span> </span><span>!important</span><span>;</span></div></div><div><div><div>46</div></div><div><span><span>      </span></span><span>word-wrap: </span><span>break-word</span><span>;</span></div></div><div><div><div>47</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>48</div></div><div>
</div></div><div><div><div>49</div></div><div><span>    </span><span>.course-price</span><span> {</span></div></div><div><div><div>50</div></div><div><span><span>      </span></span><span>color: </span><span>#</span><span>e93b3b</span><span>;</span></div></div><div><div><div>51</div></div><div><span><span>    </span></span><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></div></div></section><section><h2>标签栏<a href="#标签栏"><span>#</span></a></h2><p>标签栏部分</p><div><div>index.htmltabbar.css</div><div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>  </span><span>&lt;!-- 标签栏 --&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"tabbar-layout"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"tabbar"</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>      </span></span><span>&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"javascript:;"</span><span> </span><span>class</span><span>=</span><span>"tabbar-item tabbar-item-active"</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>&lt;</span><span>i</span><span> </span><span>class</span><span>=</span><span>"iconfont icon-home"</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>        </span></span><span>&lt;/</span><span>i</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span><span>        </span></span><span>&lt;</span><span>span</span><span>&gt;首页&lt;/</span><span>span</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span><span>      </span></span><span>&lt;/</span><span>a</span><span>&gt;</span></div></div><div><div><div>9</div></div><div><span><span>      </span></span><span>&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"javascript:;"</span><span> </span><span>class</span><span>=</span><span>"tabbar-item "</span><span>&gt;</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>&lt;</span><span>i</span><span> </span><span>class</span><span>=</span><span>"iconfont icon-search"</span><span>&gt;</span></div></div><div><div><div>11</div></div><div><span><span>        </span></span><span>&lt;/</span><span>i</span><span>&gt;</span></div></div><div><div><div>12</div></div><div><span><span>        </span></span><span>&lt;</span><span>span</span><span>&gt;搜索&lt;/</span><span>span</span><span>&gt;</span></div></div><div><div><div>13</div></div><div><span><span>      </span></span><span>&lt;/</span><span>a</span><span>&gt;</span></div></div><div><div><div>14</div></div><div><span><span>      </span></span><span>&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"javascript:;"</span><span> </span><span>class</span><span>=</span><span>"tabbar-item "</span><span>&gt;</span></div></div><div><div><div>15</div></div><div><span><span>        </span></span><span>&lt;</span><span>i</span><span> </span><span>class</span><span>=</span><span>"iconfont icon-personal"</span><span>&gt;</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>&lt;/</span><span>i</span><span>&gt;</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>&lt;</span><span>span</span><span>&gt;我的&lt;/</span><span>span</span><span>&gt;</span></div></div><div><div><div>18</div></div><div><span><span>      </span></span><span>&lt;/</span><span>a</span><span>&gt;</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></div><div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.tabbar</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>height: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>background-color: </span><span>#</span><span>f6f6f6</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>14</span><span>px</span></span><span>;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>.tabbar-item</span><span> {</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>float: </span><span>left</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>width: </span><span><span>33.333333</span><span>%</span></span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>height: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>color: </span><span>#</span><span>c2cfcc</span><span>;</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>text-align: </span><span>center</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>padding-top: </span><span><span>3</span><span>px</span></span><span>;</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>.tabbar-item-active</span><span> {</span></div></div><div><div><div>18</div></div><div><span><span>  </span></span><span>background-color: </span><span>#</span><span>e7f3f0</span><span>;</span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>color: </span><span>#</span><span>00b38a</span><span>;</span></div></div><div><div><div>20</div></div><div><span>}</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>.tabbar-item</span><span> </span><span>.iconfont</span><span> {</span></div></div><div><div><div>23</div></div><div><span><span>  </span></span><span>display: </span><span>block</span><span>;</span></div></div><div><div><div>24</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>25</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></div></div></section><section><h2>layout样式<a href="#layout样式"><span>#</span></a></h2><div><div><div><figure><figcaption><span>layout.css</span><span>展开</span><span>收起</span></figcaption><pre><code><div><div><div>1</div></div><div><span>.header-layout</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>position: </span><span>fixed</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>left: </span><span>0</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>top: </span><span>0</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>height: </span><span><span>48</span><span>px</span></span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>background-color: </span><span>red</span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>border-bottom: </span><span><span>1</span><span>px</span></span><span><span> </span><span>solid</span><span> </span></span><span>#</span><span>e8e8e8</span><span>;</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>.main-layout</span><span> {</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>padding: </span><span><span>48</span><span>px</span></span><span> </span><span>0</span><span> </span><span><span>48</span><span>px</span></span><span> </span><span>0</span><span>;</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>.slider-layout</span><span> {</span></div></div><div><div><div>16</div></div><div><span>  </span><span>/* height: 134px;</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>background-color: green; */</span></div></div><div><div><div>18</div></div><div><span><span>  </span></span><span>margin-bottom: </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>19</div></div><div><span>}</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>.course-layout</span><span> {</span></div></div><div><div><div>22</div></div><div><span>  </span><span>/* height: 382px;</span></div></div><div><div><div>23</div></div><div><span><span>  </span></span><span>background-color: gray; */</span></div></div><div><div><div>24</div></div><div><span><span>  </span></span><span>margin-bottom: </span><span><span>10</span><span>px</span></span><span>;</span></div></div><div><div><div>25</div></div><div><span>}</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>.tabbar-layout</span><span> {</span></div></div><div><div><div>28</div></div><div><span><span>  </span></span><span>position: </span><span>fixed</span><span>;</span></div></div><div><div><div>29</div></div><div><span><span>  </span></span><span>left: </span><span>0</span><span>;</span></div></div><div><div><div>30</div></div><div><span><span>  </span></span><span>bottom: </span><span>0</span><span>;</span></div></div><div><div><div>31</div></div><div><span><span>  </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>32</div></div><div><span><span>  </span></span><span>height: </span><span><span>48</span><span>px</span></span><span>;</span></div></div><div><div><div>33</div></div><div><span><span>  </span></span><span>background-color: </span><span>yellow</span><span>;</span></div></div><div><div><div>34</div></div><div><span><span>  </span></span><span>box-shadow: </span><span>0</span><span> </span><span><span>-4</span><span>px</span></span><span> </span><span><span>4</span><span>px</span></span><span> </span><span>rgba</span><span>(</span><span>0</span><span>, </span><span>0</span><span>, </span><span>0</span><span>, </span><span>0.15</span><span>);</span></div></div><div><div><div>35</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>
<section><h1>总结<a href="#总结"><span>#</span></a></h1><p>流体布局主要使用%单位布局，不是只能使用%单位布局，也可以使用其他单位，比如px；图片一般只设置宽度或者高度,不要同时设置，这样可以等比例缩放，不失真</p></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026101001css3-zhong-kai-fa-zhong-de-chang-yong-dan-wei/</id>
      <title type="text">CSS3中开发中的常用单位</title>
      <published>2026-10-10T02:02:21.000Z</published>
      <updated>2026-10-10T02:02:21.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026101001css3-zhong-kai-fa-zhong-de-chang-yong-dan-wei/"/>
      <summary type="text">学习CSS3中开发中的常用单位</summary>
      <content type="html"><![CDATA[<section><h1>CSS3 常用长度单位<a href="#css3-常用长度单位"><span>#</span></a></h1><p>CSS 中的长度单位主要分为两类：</p><ul>
<li>绝对长度单位：如 <code>px</code>，不直接依赖父元素的尺寸。</li>
<li>相对长度单位：如 <code>%</code>、<code>em</code>、<code>rem</code>、<code>vw</code>、<code>vh</code> 等，根据不同的参照对象计算实际大小。</li>
</ul></section>
<section><h1>px（像素）<a href="#px像素"><span>#</span></a></h1><p><code>px</code> 是 CSS 中最常用的长度单位，表示 CSS 像素。</p><section><h2>基本使用<a href="#基本使用"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>300</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>height: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>16</span><span>px</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>padding: </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>border: </span><span><span>1</span><span>px</span></span><span><span> </span><span>solid</span><span> </span></span><span>black</span><span>;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>特点：</p><ul>
<li>数值明确，容易控制元素尺寸。</li>
<li>不依赖父元素的宽度或字体大小。</li>
<li>适合边框、图标、固定尺寸元素、细节间距等。</li>
</ul></section><section><h2>px 不等于物理像素<a href="#px-不等于物理像素"><span>#</span></a></h2><p>CSS 中的 <code>1px</code> 不一定对应屏幕上的一个物理像素。例如，在设备像素比（DPR）为 2 的情况下，正常缩放时：<code>1 CSS px</code> 通常对应 <code>2 × 2</code> 个物理像素。因此，<code>px</code> 不是永远固定的物理尺寸。</p></section><section><h2>开发场景<a href="#开发场景"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.card</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>320</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>padding: </span><span><span>16</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>border-radius: </span><span><span>8</span><span>px</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>border: </span><span><span>1</span><span>px</span></span><span><span> </span><span>solid</span><span> </span></span><span>#</span><span>ddd</span><span>;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>px</code> 适合需要精确控制尺寸的场景，但大量使用固定宽高可能导致小屏幕溢出，因此响应式开发通常需要搭配其他单位。</p></section></section>
<section><h1>百分号（%）<a href="#百分号"><span>#</span></a></h1><p><code>%</code> 是相对单位，通常根据相关属性对应的包含块尺寸计算，而不是所有属性都相对于父元素的同一个尺寸。</p><section><h2>基本使用<a href="#基本使用-1"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;div </span><span>class="parent"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;div </span><span>class="child"</span><span>&gt;</span><span>&lt;</span><span>/div&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;/div&gt;</span></div></div><div><div><div>4</div></div><div><span>.parent</span><span> {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>width: </span><span><span>500</span><span>px</span></span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>height: </span><span><span>300</span><span>px</span></span><span>;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>.child</span><span> {</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>width: </span><span><span>50</span><span>%</span></span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>height: </span><span><span>50</span><span>%</span></span><span>;</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>计算结果：</p><ul>
<li>子元素宽度：<code>500 × 50% = 250px</code></li>
<li>子元素高度：<code>300 × 50% = 150px</code></li>
</ul></section><section><h2>不同属性的百分比参照对象<a href="#不同属性的百分比参照对象"><span>#</span></a></h2>

<table><thead><tr><th>属性</th><th>百分比主要参照</th></tr></thead><tbody><tr><td><code>width</code></td><td>包含块宽度</td></tr><tr><td><code>height</code></td><td>包含块高度（需要满足相应的高度计算条件）</td></tr><tr><td><code>padding</code></td><td>包含块宽度</td></tr><tr><td><code>margin</code></td><td>包含块宽度</td></tr><tr><td><code>font-size</code></td><td>父元素字体大小</td></tr><tr><td><code>transform: translateX()</code></td><td>元素自身的参考盒宽度</td></tr><tr><td><code>transform: translateY()</code></td><td>元素自身的参考盒高度</td></tr></tbody></table><p>注意，<code>padding-top: 10%</code> 通常也是根据包含块的宽度计算，而不是高度。</p></section><section><h2>开发场景<a href="#开发场景-1"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>80</span><span>%</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>max-width: </span><span><span>1200</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>margin: </span><span>0</span><span><span> </span><span>auto</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>适合：</p><ul>
<li>流式布局。</li>
<li>容器宽度自适应。</li>
<li>子元素占据父容器一定比例。</li>
</ul></section></section>
<section><h1>em<a href="#em"><span>#</span></a></h1><p><code>em</code> 是相对字体大小的长度单位。</p><section><h2>基本规则<a href="#基本规则"><span>#</span></a></h2><ul>
<li>用在 <code>font-size</code> 上：相对于父元素计算后的字体大小。</li>
<li>用在其他长度属性上：相对于当前元素计算后的字体大小。</li>
</ul></section><section><h2>基本使用<a href="#基本使用-2"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.parent</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>.child</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>1.5</span><span>em</span></span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>padding: </span><span><span>2</span><span>em</span></span><span>;</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>计算过程：</p><ul>
<li><code>.child</code> 字体大小：<code>20 × 1.5 = 30px</code></li>
<li><code>.child</code> 内边距：<code>30 × 2 = 60px</code></li>
</ul><p>虽然都使用 <code>em</code>，但因为属性不同，计算参照对象也不同。</p></section><section><h2>em的嵌套问题<a href="#em的嵌套问题"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;div </span><span>class="box"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>  </span><span>第一层</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;div </span><span>class="box"</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>    </span><span>第二层</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>&lt;div </span><span>class="box"</span><span>&gt;</span><span>第三层&lt;</span><span>/div&gt;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>&lt;/div&gt;</span></div></div><div><div><div>7</div></div><div><span>&lt;/div&gt;</span></div></div><div><div><div>8</div></div><div><span>body</span><span> {</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>16</span><span>px</span></span><span>;</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>1.5</span><span>em</span></span><span>;</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>嵌套计算结果：</p>

<table><thead><tr><th>层级</th><th>字体大小</th></tr></thead><tbody><tr><td>第一层</td><td>24px</td></tr><tr><td>第二层</td><td>36px</td></tr><tr><td>第三层</td><td>54px</td></tr></tbody></table><p>这就是 <code>em</code> 容易出现字体逐层放大的原因。</p></section><section><h2>开发场景<a href="#开发场景-2"><span>#</span></a></h2><p><code>em</code> 适合希望元素的间距、尺寸跟随自身字体大小变化的组件。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.button</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>16</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>padding: </span><span><span>0.5</span><span>em</span></span><span> </span><span><span>1</span><span>em</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>border-radius: </span><span><span>0.5</span><span>em</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>当按钮字体大小变化时，内边距和圆角也会按比例变化。</p></section></section>
<section><h1>rem<a href="#rem"><span>#</span></a></h1><p><code>rem</code> 是相对于根元素 <code>&lt;html&gt;</code> 的字体大小计算的单位。</p><section><h2>基本使用<a href="#基本使用-3"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>html</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>16</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>width: </span><span><span>20</span><span>rem</span></span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>height: </span><span><span>10</span><span>rem</span></span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>1.5</span><span>rem</span></span><span>;</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>计算结果：</p><ul>
<li><code>20rem = 320px</code></li>
<li><code>10rem = 160px</code></li>
<li><code>1.5rem = 24px</code></li>
</ul></section><section><h2>rem 与 em 的区别<a href="#rem-与-em-的区别"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>html</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>16</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>.parent</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>.child</span><span> {</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>2</span><span>em</span></span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>padding: </span><span><span>2</span><span>rem</span></span><span>;</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li><code>2em = 40px</code>，相对于父元素字体大小计算。</li>
<li><code>2rem = 32px</code>，相对于根元素字体大小计算。</li>
</ul><p><code>rem</code> 不会像 <code>em</code> 那样因为普通父元素的字体设置而不断累积放大。</p></section><section><h2>rem 的响应式应用<a href="#rem-的响应式应用"><span>#</span></a></h2><p>通过修改根元素的字体大小，可以统一调整使用 <code>rem</code> 的尺寸。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>html</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>16</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>.card</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>width: </span><span><span>20</span><span>rem</span></span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>padding: </span><span><span>1.5</span><span>rem</span></span><span>;</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>@media</span><span> (max-width: </span><span><span>600</span><span>px</span></span><span>) {</span></div></div><div><div><div>11</div></div><div><span>  </span><span>html</span><span> {</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>font-size: </span><span><span>14</span><span>px</span></span><span>;</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意：这种做法仅改变使用 <code>rem</code> 的尺寸，不代表页面自动完成响应式布局。另外，修改根字号也会影响使用 <code>rem</code> 的文字大小，需要考虑可读性。</p></section><section><h2>开发场景<a href="#开发场景-3"><span>#</span></a></h2><p>适合：</p><ul>
<li>全局字体大小。</li>
<li>组件内外边距。</li>
<li>统一间距系统。</li>
<li>需要跟随根字体大小调整的元素尺寸。</li>
</ul></section></section>
<section><h1>vw/vh/vmax/vmin<a href="#vwvhvmaxvmin"><span>#</span></a></h1><p>这四种单位都相对于**视口（Viewport）**计算，而不是父元素。</p><section><h2>vw（视口宽度）<a href="#vw视口宽度"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>1vw = 视口宽度的 1%</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>假设视口宽度为 <code>1000px</code>：</p><ul>
<li><code>1vw = 10px</code></li>
<li><code>50vw = 500px</code></li>
<li><code>100vw = 1000px</code></li>
</ul><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: 50vw;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>无论父元素宽度多少，元素的指定宽度始终根据视口宽度计算。</p></section><section><h2>vh（视口高度）<a href="#vh视口高度"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>1vh = 视口高度的 1%</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>假设视口高度为 <code>800px</code>：</p><ul>
<li><code>1vh = 8px</code></li>
<li><code>50vh = 400px</code></li>
<li><code>100vh = 800px</code></li>
</ul><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.hero {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>height: 100vh;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>适合首页首屏、全屏背景等场景。</p><p>注意：移动端浏览器工具栏会影响可见区域，现代开发中需要真正贴合动态可见高度时，可以考虑 <code>100dvh</code>。</p></section><section><h2>vmax（视口较大边）<a href="#vmax视口较大边"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>1vmax = max(视口宽度, 视口高度) × 1%</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>vmin（视口较小边）<a href="#vmin视口较小边"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>1vmin = min(视口宽度, 视口高度) × 1%</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>例如，视口为 <code>1200 × 800px</code> 时：</p>

<table><thead><tr><th>单位</th><th>参照</th><th>结果</th></tr></thead><tbody><tr><td><code>1vw</code></td><td>宽度 1200px</td><td>12px</td></tr><tr><td><code>1vh</code></td><td>高度 800px</td><td>8px</td></tr><tr><td><code>1vmax</code></td><td>较大边 1200px</td><td>12px</td></tr><tr><td><code>1vmin</code></td><td>较小边 800px</td><td>8px</td></tr></tbody></table></section><section><h2>开发场景<a href="#开发场景-4"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/* 全屏首屏 */</span></div></div><div><div><div>2</div></div><div><span>.hero</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>min-height: </span><span><span>100</span><span>dvh</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>/* 根据视口宽度调整标题大小 */</span></div></div><div><div><div>7</div></div><div><span>.title</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>font-size: </span><span>clamp</span><span>(</span><span><span>24</span><span>px</span></span><span>, </span><span><span>4</span><span>vw</span></span><span>, </span><span><span>48</span><span>px</span></span><span>);</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>/* 始终保持正方形 */</span></div></div><div><div><div>12</div></div><div><span>.square</span><span> {</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>width: </span><span><span>30</span><span>vmin</span></span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>height: </span><span><span>30</span><span>vmin</span></span><span>;</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>/* 根据视口较大边创建背景圆形 */</span></div></div><div><div><div>18</div></div><div><span>.circle</span><span> {</span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>width: </span><span><span>50</span><span>vmax</span></span><span>;</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>height: </span><span><span>50</span><span>vmax</span></span><span>;</span></div></div><div><div><div>21</div></div><div><span><span>  </span></span><span>border-radius: </span><span><span>50</span><span>%</span></span><span>;</span></div></div><div><div><div>22</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>其中 <code>vmin</code> 很适合需要同时考虑横屏和竖屏的场景。</p></section></section>
<section><h1>常用单位总结<a href="#常用单位总结"><span>#</span></a></h1>

<table><thead><tr><th>单位</th><th>参照对象</th><th>常见用途</th></tr></thead><tbody><tr><td><code>px</code></td><td>CSS 像素</td><td>边框、图标、固定尺寸</td></tr><tr><td><code>%</code></td><td>取决于属性</td><td>容器宽度、流式布局</td></tr><tr><td><code>em</code></td><td>当前或父元素字体大小</td><td>组件内部比例、按钮</td></tr><tr><td><code>rem</code></td><td>根元素字体大小</td><td>字体、全局间距系统</td></tr><tr><td><code>vw</code></td><td>视口宽度</td><td>视口相关尺寸、流体字号</td></tr><tr><td><code>vh</code></td><td>视口高度</td><td>全屏布局、首屏区域</td></tr><tr><td><code>vmax</code></td><td>视口较大边</td><td>大型背景、装饰元素</td></tr><tr><td><code>vmin</code></td><td>视口较小边</td><td>自适应正方形、圆形</td></tr></tbody></table></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026100903css3-zhong-de-shi-kou-viewport/</id>
      <title type="text">CSS3中的视口viewport</title>
      <published>2026-10-09T07:04:33.000Z</published>
      <updated>2026-10-09T07:04:33.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026100903css3-zhong-de-shi-kou-viewport/"/>
      <summary type="text">学习移动Web开发中的视口viewpor</summary>
      <content type="html"><![CDATA[<section><h1>视口概念<a href="#视口概念"><span>#</span></a></h1><section><h2>什么是视口（Viewport）<a href="#什么是视口viewport"><span>#</span></a></h2><p>视口（Viewport）是浏览器中用于显示网页内容的区域。 它决定了网页能够使用多大的空间进行布局。简单理解：</p><ul>
<li>屏幕（Screen）：设备的整个物理显示区域。</li>
<li>视口（Viewport）：浏览器提供给网页显示内容的区域。</li>
<li>网页（Document）：网页的完整内容，可能超出视口，需要滚动才能查看。</li>
</ul><p>视口不等于整个屏幕，网页内容也不一定局限于视口高度。</p><p><img alt="" /></p></section><section><h2>视口的分类<a href="#视口的分类"><span>#</span></a></h2><p>在移动端开发中，主要涉及两种视口。</p>

<table><thead><tr><th>类型</th><th>说明</th></tr></thead><tbody><tr><td>布局视口（Layout Viewport）</td><td>浏览器用于计算网页布局的区域</td></tr><tr><td>视觉视口（Visual Viewport）</td><td>用户当前实际看到的网页区域</td></tr></tbody></table><p>例如：在手机浏览器中放大网页时，布局视口的宽度通常不变，而视觉视口会变小，因为用户只能看到网页的一部分。</p></section><section><h2>CSS中的视口单位<a href="#css中的视口单位"><span>#</span></a></h2><p>CSS提供了基于视口大小计算的长度单位。</p>

<table><thead><tr><th>单位</th><th>含义</th></tr></thead><tbody><tr><td><code>vw</code></td><td>视口宽度的1%</td></tr><tr><td><code>vh</code></td><td>视口高度的1%</td></tr><tr><td><code>vmin</code></td><td>视口宽高较小值的1%</td></tr><tr><td><code>vmax</code></td><td>视口宽高较大值的1%</td></tr><tr><td><code>dvh</code></td><td>动态视口高度的1%</td></tr><tr><td><code>svh</code></td><td>小视口高度的1%</td></tr><tr><td><code>lvh</code></td><td>大视口高度的1%</td></tr></tbody></table><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>50</span><span>vw</span></span><span>;       </span><span>/* 视口宽度的50% */</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>height: </span><span><span>30</span><span>vh</span></span><span>;      </span><span>/* 视口高度的30% */</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>min-height: </span><span><span>100</span><span>dvh</span></span><span>; </span><span>/* 适应移动端动态视口 */</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>假设视口为 1200 × 800 CSS像素，那么 <code>50vw = 600px</code>，<code>30vh = 240px</code>。</p><p>注意：<code>vw</code> 和 <code>vh</code> 是相对于视口计算的，不是相对于父元素计算的。另外，移动端浏览器地址栏显示、隐藏时，<code>dvh</code> 比传统 <code>vh</code> 更适合需要跟随可见区域变化的全屏布局。</p></section></section>
<section><h1>如何设置viewport<a href="#如何设置viewport"><span>#</span></a></h1><section><h2>使用meta标签设置<a href="#使用meta标签设置"><span>#</span></a></h2><p>在HTML文档的 <code>&lt;head&gt;</code> 中，通过 <code>meta</code> 标签配置移动端视口。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>meta</span></div></div><div><div><div>2</div></div><div><span>  </span><span>name</span><span>=</span><span>"viewport"</span></div></div><div><div><div>3</div></div><div><span>  </span><span>content</span><span>=</span><span>"width=device-width, initial-scale=1.0"</span></div></div><div><div><div>4</div></div><div><span>/&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这是现代响应式网页最常用的视口配置。</p><p>属性解释：</p>

<table><thead><tr><th>属性</th><th>作用</th></tr></thead><tbody><tr><td><code>width=device-width</code></td><td>设置布局视口宽度为设备的CSS像素宽度</td></tr><tr><td><code>initial-scale=1.0</code></td><td>设置页面初始缩放比例为1</td></tr><tr><td><code>minimum-scale</code></td><td>设置允许的最小缩放比例</td></tr><tr><td><code>maximum-scale</code></td><td>设置允许的最大缩放比例</td></tr><tr><td><code>user-scalable</code></td><td>控制是否允许用户手动缩放</td></tr></tbody></table><p>通常只需要前两个配置，不建议使用 <code>user-scalable=no</code> 限制缩放，因为这可能影响需要放大网页的用户。</p></section><section><h2>为什么要设置viewport？<a href="#为什么要设置viewport"><span>#</span></a></h2><p>早期移动端浏览器为了兼容PC网页，会使用一个较宽的默认布局视口（常见约980 CSS像素），然后把整张网页缩小显示。因此，如果没有正确配置Viewport，可能会导致：</p><ul>
<li>网页在手机上整体缩小。</li>
<li>文字和按钮过小。</li>
<li>响应式媒体查询无法按照预期工作。</li>
</ul><p>设置之后，网页就能按照设备对应的CSS像素宽度正常布局。</p></section><section><h2>完整HTML示例<a href="#完整html示例"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!</span><span>doctype</span><span> </span><span>html</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>html</span><span> </span><span>lang</span><span>=</span><span>"zh-CN"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>head</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>meta</span><span> </span><span>charset</span><span>=</span><span>"UTF-8"</span><span> /&gt;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>&lt;</span><span>meta</span></div></div><div><div><div>7</div></div><div><span>      </span><span>name</span><span>=</span><span>"viewport"</span></div></div><div><div><div>8</div></div><div><span>      </span><span>content</span><span>=</span><span>"width=device-width, initial-scale=1.0"</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>/&gt;</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>&lt;</span><span>title</span><span>&gt;Viewport示例&lt;/</span><span>title</span><span>&gt;</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>14</div></div><div><span>      </span><span>.box</span><span> {</span></div></div><div><div><div>15</div></div><div><span><span>        </span></span><span>width: </span><span><span>50</span><span>vw</span></span><span>;</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>height: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>background-color: </span><span>skyblue</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>      </span><span>@media</span><span> (max-width: </span><span><span>768</span><span>px</span></span><span>) {</span></div></div><div><div><div>21</div></div><div><span>        </span><span>.box</span><span> {</span></div></div><div><div><div>22</div></div><div><span><span>          </span></span><span>width: </span><span><span>100</span><span>%</span></span><span>;</span></div></div><div><div><div>23</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>24</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>26</div></div><div><span><span>  </span></span><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span><span>  </span></span><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>29</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>30</div></div><div><span><span>  </span></span><span>&lt;/</span><span>body</span><span>&gt;</span></div></div><div><div><div>31</div></div><div><span>&lt;/</span><span>html</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>效果：</p><ul>
<li>视口宽度大于768px时，盒子宽度为视口的50%。</li>
<li>视口宽度小于或等于768px时，盒子宽度为父元素内容区域的100%。</li>
</ul><p>注意：<code>meta viewport</code> 属于HTML配置，不是CSS属性，但它会直接影响CSS响应式布局的表现。</p></section></section>
<section><h1>通过JS获取视口<a href="#通过js获取视口"><span>#</span></a></h1><p>JavaScript提供了多种获取视口尺寸的方法。</p><section><h2>window.innerWidth / innerHeight<a href="#windowinnerwidth--innerheight"><span>#</span></a></h2><p>获取浏览器布局视口的宽度和高度。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 获取视口宽度</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>width</span><span> </span><span>=</span><span><span> </span><span>window</span><span>.</span></span><span>innerWidth</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>// 获取视口高度</span></div></div><div><div><div>5</div></div><div><span>const</span><span> </span><span>height</span><span> </span><span>=</span><span><span> </span><span>window</span><span>.</span></span><span>innerHeight</span><span>;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>width</span><span>, </span><span>height</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>innerWidth</code> 和 <code>innerHeight</code> 包含视口内可能存在的滚动条所占空间。</p></section><section><h2>document.documentElement.clientWidth / clientHeight<a href="#documentdocumentelementclientwidth--clientheight"><span>#</span></a></h2><p>获取HTML根元素的可见内容区域尺寸。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>width</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>documentElement</span><span>.</span><span>clientWidth</span><span>;</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>height</span><span> </span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>documentElement</span><span>.</span><span>clientHeight</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>width</span><span>, </span><span>height</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>与 <code>innerWidth</code> 的主要区别是：<code>clientWidth</code> 通常不包括传统滚动条占用的宽度。</p></section><section><h2>window.visualViewport<a href="#windowvisualviewport"><span>#</span></a></h2><p>获取当前视觉视口尺寸，在移动端缩放等场景下尤其有用。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>const</span><span> </span><span>width</span><span> </span><span>=</span><span><span> </span><span>window</span><span>.</span></span><span>visualViewport</span><span>.</span><span>width</span><span>;</span></div></div><div><div><div>2</div></div><div><span>const</span><span> </span><span>height</span><span> </span><span>=</span><span><span> </span><span>window</span><span>.</span></span><span>visualViewport</span><span>.</span><span>height</span><span>;</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span><span>console</span><span>.</span></span><span>log</span><span><span>(</span><span>width</span><span>, </span><span>height</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其中 <code>visualViewport</code> 的 <code>width</code> 和 <code>height</code> 可以随着页面缩放、可见区域变化而改变。</p></section><section><h2>监听视口大小变化<a href="#监听视口大小变化"><span>#</span></a></h2><p>使用 <code>resize</code> 事件，在浏览器窗口大小发生变化时执行代码。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>window</span><span>.</span></span><span>addEventListener</span><span>(</span><span>"resize"</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"视口宽度:"</span><span><span>, </span><span>window</span><span>.</span></span><span>innerWidth</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span>(</span><span>"视口高度:"</span><span><span>, </span><span>window</span><span>.</span></span><span>innerHeight</span><span>);</span></div></div><div><div><div>4</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果需要监听移动端视觉视口变化：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>window</span><span>.</span></span><span>visualViewport</span><span>?.</span><span>addEventListener</span><span>(</span><span>"resize"</span><span>, () </span><span>=&gt;</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>window</span><span>.</span></span><span>visualViewport</span><span>.</span><span>width</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>console</span><span>.</span><span>log</span><span><span>(</span><span>window</span><span>.</span></span><span>visualViewport</span><span>.</span><span>height</span><span>);</span></div></div><div><div><div>4</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>常见获取方式对比<a href="#常见获取方式对比"><span>#</span></a></h2>

<table><thead><tr><th>JS属性</th><th>获取内容</th><th>典型用途</th></tr></thead><tbody><tr><td><code>window.innerWidth</code></td><td>布局视口宽度</td><td>获取页面可用宽度</td></tr><tr><td><code>window.innerHeight</code></td><td>布局视口高度</td><td>获取页面可用高度</td></tr><tr><td><code>document.documentElement.clientWidth</code></td><td>排除传统滚动条的根元素可见宽度</td><td>布局尺寸计算</td></tr><tr><td><code>document.documentElement.clientHeight</code></td><td>根元素可见高度</td><td>页面高度计算</td></tr><tr><td><code>window.visualViewport.width</code></td><td>视觉视口宽度</td><td>移动端缩放适配</td></tr><tr><td><code>window.visualViewport.height</code></td><td>视觉视口高度</td><td>软键盘、缩放适配</td></tr><tr><td><code>screen.width</code></td><td>设备屏幕宽度</td><td>获取屏幕信息，不等于视口</td></tr></tbody></table></section></section>
<section><h1>总结<a href="#总结"><span>#</span></a></h1>

<table><thead><tr><th>知识点</th><th>核心内容</th></tr></thead><tbody><tr><td>视口概念</td><td>浏览器用于显示网页内容的区域</td></tr><tr><td>设置viewport</td><td><code>&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;</code></td></tr><tr><td>CSS视口单位</td><td><code>vw</code>、<code>vh</code>、<code>dvh</code> 等</td></tr><tr><td>JS获取布局视口</td><td><code>window.innerWidth</code>、<code>window.innerHeight</code></td></tr><tr><td>JS获取视觉视口</td><td><code>window.visualViewport</code></td></tr><tr><td>监听视口变化</td><td><code>resize</code> 事件</td></tr></tbody></table><p>实际开发中： 使用 <code>meta viewport</code> 配合 CSS 媒体查询、Flex、Grid 和视口单位就能完成绝大多数响应式布局。只有需要进行动态尺寸计算、Canvas绘制、特殊移动端适配时，才需要通过JavaScript获取视口尺寸。</p></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026100902css3-zhong-de-transition-shu-xing-guo-du-yu-dong-hua/</id>
      <title type="text">CSS3中的transition属性过渡与动画</title>
      <published>2026-10-09T00:51:37.000Z</published>
      <updated>2026-10-09T00:51:37.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026100902css3-zhong-de-transition-shu-xing-guo-du-yu-dong-hua/"/>
      <summary type="text">学习CSS3中的transition属性过渡与动画</summary>
      <content type="html"><![CDATA[<section><h1>前言<a href="#前言"><span>#</span></a></h1><p>CSS3 中，**过渡（Transition）和动画（Animation）**都能让元素产生动态效果，但两者的使用场景不同。</p><ul>
<li>过渡：让元素从一种样式平滑变化到另一种样式，通常需要触发条件。</li>
<li>动画：通过关键帧定义一系列样式变化，可以自动播放，也可以循环播放。</li>
</ul></section>
<section><h1>过渡的基本使用<a href="#过渡的基本使用"><span>#</span></a></h1><section><h2>什么是过渡<a href="#什么是过渡"><span>#</span></a></h2><p>CSS 过渡（Transition）用于控制元素的样式从一个状态变化到另一个状态时的过程，而不是瞬间完成变化。</p><p>例如，鼠标移入盒子时，让背景颜色在 1 秒内逐渐从红色变为蓝色。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>.box {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>width: 100px;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>height: 100px;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>background-color: red;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>transition: background-color 1s;</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>.box:hover {</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>background-color: blue;</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>没有 <code>transition</code> 时，颜色立即改变；添加之后，颜色会平滑变化。</p></section><section><h2>transition 的基本属性<a href="#transition-的基本属性"><span>#</span></a></h2>

<table><thead><tr><th>属性</th><th>作用</th><th>示例</th></tr></thead><tbody><tr><td><code>transition-property</code></td><td>指定需要过渡的属性</td><td><code>width</code></td></tr><tr><td><code>transition-duration</code></td><td>设置过渡持续时间</td><td><code>1s</code></td></tr><tr><td><code>transition-timing-function</code></td><td>设置过渡的速度曲线</td><td><code>ease</code></td></tr><tr><td><code>transition-delay</code></td><td>设置过渡开始前的等待时间</td><td><code>0.5s</code></td></tr><tr><td><code>transition</code></td><td>以上属性的简写</td><td><code>all 1s ease</code></td></tr></tbody></table><p><strong>transition-property</strong>：指定哪些 CSS 属性需要执行过渡。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>transition-property: width;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div><span> </span><span>/* 多个属性可以使用逗号分隔  */</span></div></div><div><div><div>5</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>transition-property: width, background-color;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div><span> </span><span>/* 使用 all 表示所有可过渡的属性 */</span></div></div><div><div><div>9</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>transition-property: </span><span>all</span><span>;</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意：并非所有 CSS 属性都可以平滑过渡，例如 <code>display: none</code> 到 <code>display: block</code> 在普通情况下不会产生连续的过渡效果。</p><p>**transition-duration：**设置过渡持续时间，单位为 <code>s</code> 或 <code>ms</code>。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>transition-duration: </span><span><span>1</span><span>s</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li><code>1s</code>：1 秒</li>
<li><code>500ms</code>：500 毫秒</li>
<li><code>0.5s</code>：0.5 秒</li>
</ul><p>**transition-delay：**设置过渡开始前的延迟时间。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>transition-delay: </span><span><span>0.5</span><span>s</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>表示触发状态变化后，等待 0.5 秒才开始过渡</p><p><strong>transition 简写</strong></p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>transition: 属性 持续时间 缓动函数 延迟时间;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>transition: width </span><span><span>1</span><span>s</span></span><span><span> </span><span>ease</span><span> </span></span><span><span>0.5</span><span>s</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>表示宽度变化时，延迟 0.5 秒，然后使用 <code>ease</code> 曲线执行 1 秒的过渡。</p><p>还可以设置多个属性：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>transition:</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>width </span><span><span>1</span><span>s</span></span><span><span> </span><span>ease</span><span>,</span></span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>background-color </span><span><span>0.5</span><span>s</span></span><span><span> </span><span>linear</span><span>,</span></span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>transform </span><span><span>0.3</span><span>s</span></span><span><span> </span><span>ease</span><span>;</span></span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>过渡完整示例<a href="#过渡完整示例"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.container</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>width: </span><span><span>260</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>height: </span><span><span>160</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>padding: </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>box-sizing: </span><span>border-box</span><span>;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>width: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>height: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>background-color: </span><span>red</span><span>;</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>border-radius: </span><span>0</span><span>;</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>transition:</span></div></div><div><div><div>15</div></div><div><span><span>        </span></span><span>transform </span><span><span>0.6</span><span>s</span></span><span><span> </span><span>ease</span><span>,</span></span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>background-color </span><span><span>0.6</span><span>s</span></span><span><span> </span><span>ease</span><span>,</span></span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>border-radius </span><span><span>0.6</span><span>s</span></span><span><span> </span><span>ease</span><span>;</span></span></div></div><div><div><div>18</div></div><div><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span><span>.container</span><span>:hover</span></span><span> </span><span>.box</span><span> {</span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>transform: </span><span>translateX</span><span>(</span><span><span>100</span><span>px</span></span><span>) </span><span>rotate</span><span>(</span><span><span>30</span><span>deg</span></span><span>);</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>background-color: </span><span>blue</span><span>;</span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>border-radius: </span><span><span>50</span><span>%</span></span><span>;</span></div></div><div><div><div>24</div></div><div><span>}</span></div></div><div><div><div>25</div></div><div><span>&lt;div </span><span>class="container"</span><span>&gt;</span></div></div><div><div><div>26</div></div><div><span><span>  </span></span><span>&lt;div </span><span>class="box"</span><span>&gt;</span><span>&lt;</span><span>/div&gt;</span></div></div><div><div><div>27</div></div><div><span>&lt;/div&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>开发注意：</p><ul>
<li><code>transition</code> 通常写在元素的基础样式中，而不是只写在 <code>:hover</code> 中，这样移入和移出时都能平滑过渡。</li>
<li>现代开发中，优先使用 <code>transform</code> 和 <code>opacity</code> 实现位移、缩放与淡入淡出，通常性能更好。</li>
<li>过渡不只能够通过 <code>:hover</code> 触发，也能通过 <code>:focus</code>、修改 class、JavaScript 修改样式等方式触发。</li>
<li>当元素需要发生较大位移、旋转或缩放时，尽量不要让正在运动的元素自己承担 <code>:hover</code> 触发条件。 这是 CSS 过渡动画中很典型的交互陷阱。</li>
</ul></section></section>
<section><h1>过渡的缓动效果<a href="#过渡的缓动效果"><span>#</span></a></h1><p><strong>什么是缓动效果</strong>：缓动效果通过 <code>transition-timing-function</code> 控制过渡过程中变化的快慢。例如，同样是 1 秒完成 200px 位移，可以匀速移动，也可以先快后慢。</p><p><strong>常见缓动函数</strong></p>

<table><thead><tr><th>属性值</th><th>作用</th></tr></thead><tbody><tr><td><code>ease</code></td><td>默认值，先加速后减速</td></tr><tr><td><code>linear</code></td><td>匀速变化</td></tr><tr><td><code>ease-in</code></td><td>慢速开始，逐渐加速</td></tr><tr><td><code>ease-out</code></td><td>快速开始，逐渐减速</td></tr><tr><td><code>ease-in-out</code></td><td>慢速开始，慢速结束</td></tr><tr><td><code>cubic-bezier()</code></td><td>自定义贝塞尔曲线</td></tr><tr><td><code>steps()</code></td><td>将过渡划分成离散步骤</td></tr></tbody></table><p><strong>cubic-bezier() 自定义缓动</strong>：<code>cubic-bezier()</code> 用于自定义三次贝塞尔缓动曲线。</p><p>语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>transition-timing-function: cubic-bezier(x1, y1, x2, y2);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其中四个参数表示两个控制点的坐标，<code>x1</code> 和 <code>x2</code> 必须在 0～1 之间。</p><p>常见预设对应的曲线：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/* 匀速 */</span></div></div><div><div><div>2</div></div><div><span>linear</span></div></div><div><div><div>3</div></div><div><span>/* 等效于 */</span></div></div><div><div><div>4</div></div><div><span>cubic-bezier(0, 0, 1, 1);</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>/* 默认缓动 */</span></div></div><div><div><div>7</div></div><div><span>ease</span></div></div><div><div><div>8</div></div><div><span>/* 等效于 */</span></div></div><div><div><div>9</div></div><div><span>cubic-bezier(0.25, 0.1, 0.25, 1);</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>/* 慢速开始 */</span></div></div><div><div><div>12</div></div><div><span>ease-in</span></div></div><div><div><div>13</div></div><div><span>/* 等效于 */</span></div></div><div><div><div>14</div></div><div><span>cubic-bezier(0.42, 0, 1, 1);</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>/* 快速开始，慢速结束 */</span></div></div><div><div><div>17</div></div><div><span>ease-out</span></div></div><div><div><div>18</div></div><div><span>/* 等效于 */</span></div></div><div><div><div>19</div></div><div><span>cubic-bezier(0, 0, 0.58, 1);</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>实际开发中，不需要手动推导贝塞尔曲线。可以使用 <a href="https://cubic-bezier.com/" target="_blank">cubic-bezier.com</a> 可视化调试。</p><section><h2>steps() 步进函数<a href="#steps-步进函数"><span>#</span></a></h2><p><code>steps()</code> 让变化以离散的步骤完成，而不是连续、平滑地变化。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>transition: transform </span><span><span>2</span><span>s</span></span><span> </span><span>steps</span><span>(</span><span>4</span><span>, </span><span>end</span><span>);</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>.box</span><span>:hover</span></span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>transform: </span><span>translateX</span><span>(</span><span><span>200</span><span>px</span></span><span>);</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>表示在 2 秒内分 4 步完成位移。</p><p>常用于逐帧效果、数字跳动、打字机效果等场景。</p></section></section>
<section><h1>动画的定义和调用<a href="#动画的定义和调用"><span>#</span></a></h1><section><h2>什么是 CSS 动画<a href="#什么是-css-动画"><span>#</span></a></h2><p>CSS 动画（Animation）使用 <code>@keyframes</code> 定义关键帧，然后使用 <code>animation</code> 属性将动画应用到元素。与过渡不同，动画可以不依赖状态改变而自动执行，也可以循环播放。</p></section><section><h2>使用 @keyframes 定义动画<a href="#使用-keyframes-定义动画"><span>#</span></a></h2><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@keyframes</span><span><span> </span><span>动画名称</span><span> {</span></span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>from {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>/* 初始状态 */</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>to {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>/* 结束状态 */</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@keyframes</span><span><span> </span><span>move</span><span> {</span></span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>from {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>transform: </span><span>translateX</span><span>(</span><span>0</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>to {</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>transform: </span><span>translateX</span><span>(</span><span><span>200</span><span>px</span></span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>也可以使用百分比定义多个关键帧：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@keyframes</span><span><span> </span><span>move</span><span> {</span></span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>0% {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>transform: </span><span>translateX</span><span>(</span><span>0</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>50% {</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>transform: </span><span>translateX</span><span>(</span><span><span>100</span><span>px</span></span><span>);</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>100% {</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>transform: </span><span>translateX</span><span>(</span><span><span>200</span><span>px</span></span><span>);</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这里的 <code>0%</code>、<code>50%</code>、<code>100%</code> 表示动画时间进度，而不是元素位置的百分比。</p></section><section><h2>使用 animation 调用动画<a href="#使用-animation-调用动画"><span>#</span></a></h2><p>定义动画后，需要通过 <code>animation</code> 将动画应用到元素。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>animation-name: move;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>animation-duration: 2s;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>表示元素执行名为 <code>move</code> 的动画，持续时间 2 秒。</p><p><strong>animation 的常用属性</strong></p>

<table><thead><tr><th>属性</th><th>作用</th><th>示例</th></tr></thead><tbody><tr><td><code>animation-name</code></td><td>动画名称</td><td><code>move</code></td></tr><tr><td><code>animation-duration</code></td><td>动画持续时间</td><td><code>2s</code></td></tr><tr><td><code>animation-timing-function</code></td><td>动画缓动曲线</td><td><code>ease</code></td></tr><tr><td><code>animation-delay</code></td><td>动画延迟时间</td><td><code>1s</code></td></tr><tr><td><code>animation-iteration-count</code></td><td>动画播放次数</td><td><code>3</code>、<code>infinite</code></td></tr><tr><td><code>animation-direction</code></td><td>动画播放方向</td><td><code>alternate</code></td></tr><tr><td><code>animation-fill-mode</code></td><td>动画前后应用的样式</td><td><code>forwards</code></td></tr><tr><td><code>animation-play-state</code></td><td>动画播放状态</td><td><code>paused</code>、<code>running</code></td></tr><tr><td><code>animation</code></td><td>动画简写属性</td><td><code>move 2s ease infinite</code></td></tr></tbody></table><p><strong>animation-iteration-count</strong>：控制动画播放次数。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>animation-iteration-count: </span><span>3</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>表示播放 3 次。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>animation-iteration-count: </span><span>infinite</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>表示无限循环。</p><p><strong>animation-direction</strong>：控制动画播放方向。</p>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>normal</code></td><td>正常播放，默认值</td></tr><tr><td><code>reverse</code></td><td>反向播放</td></tr><tr><td><code>alternate</code></td><td>正向、反向交替播放</td></tr><tr><td><code>alternate-reverse</code></td><td>反向、正向交替播放</td></tr></tbody></table><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>animation-direction: </span><span>alternate</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>第一次从起点到终点，第二次从终点返回起点。</p><p><strong>animation-fill-mode</strong>：控制动画执行前和结束后，是否应用关键帧中的样式。</p>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>none</code></td><td>默认值，不额外保留关键帧样式</td></tr><tr><td><code>forwards</code></td><td>结束后保留最后执行的关键帧样式</td></tr><tr><td><code>backwards</code></td><td>延迟等待阶段应用起始关键帧样式</td></tr><tr><td><code>both</code></td><td>同时具有 forwards 和 backwards 的效果</td></tr></tbody></table><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>animation: </span><span>move</span><span> </span><span><span>2</span><span>s</span></span><span><span> </span><span>ease</span><span> </span><span>forwards</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>动画结束之后，元素继续保持动画结束时的视觉状态。</p><p>注意：<code>forwards</code> 不会真正修改元素的普通 CSS 属性值，只是让动画效果继续参与样式计算。</p><p><strong>animation-play-state</strong>：控制动画播放或暂停。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>animation-play-state: </span><span>running</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>.box</span><span>:hover</span></span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>animation-play-state: </span><span>paused</span><span>;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>鼠标移入时暂停动画，移出后继续播放。</p><p><strong>animation 简写</strong></p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>animation: 名称 时长 缓动函数 延迟 次数 方向 填充模式;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>animation: </span><span>move</span><span> </span><span><span>2</span><span>s</span></span><span><span> </span><span>ease</span><span> </span></span><span><span>0.5</span><span>s</span></span><span><span> </span><span>infinite</span><span> </span><span>alternate</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>表示调用 <code>move</code> 动画，延迟 0.5 秒，执行 2 秒，无限循环，并交替播放方向。多个动画也可以一起使用：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>animation:</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>move</span><span> </span><span><span>2</span><span>s</span></span><span><span> </span><span>ease</span><span> </span><span>infinite</span><span> </span><span>alternate</span><span>,</span></span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>fade </span><span><span>1</span><span>s</span></span><span><span> </span><span>linear</span><span> </span><span>infinite</span><span> </span><span>alternate</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h1>动画完整示例<a href="#动画完整示例"><span>#</span></a></h1><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>height: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>background-color: </span><span>blue</span><span>;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>animation: </span><span>move</span><span> </span><span><span>2.5</span><span>s</span></span><span><span> </span><span>ease-in-out</span><span> </span><span>infinite</span><span> </span><span>alternate</span><span>;</span></span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>@keyframes</span><span><span> </span><span>move</span><span> {</span></span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>0% {</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>transform: </span><span>translateX</span><span>(</span><span>0</span><span>) </span><span>rotate</span><span>(</span><span>0</span><span>);</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>background-color: </span><span>blue</span><span>;</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>50% {</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>transform: </span><span>translateX</span><span>(</span><span><span>100</span><span>px</span></span><span>) </span><span>rotate</span><span>(</span><span><span>90</span><span>deg</span></span><span>);</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>background-color: </span><span>purple</span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>100% {</span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>transform: </span><span>translateX</span><span>(</span><span><span>200</span><span>px</span></span><span>) </span><span>rotate</span><span>(</span><span><span>180</span><span>deg</span></span><span>);</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>background-color: </span><span>green</span><span>;</span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>border-radius: </span><span><span>50</span><span>%</span></span><span>;</span></div></div><div><div><div>24</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>25</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h1>实际开发中的常见动画<a href="#实际开发中的常见动画"><span>#</span></a></h1><section><h2>淡入动画<a href="#淡入动画"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@keyframes</span><span><span> </span><span>fadeIn</span><span> {</span></span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>from {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>opacity: </span><span>0</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>to {</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>opacity: </span><span>1</span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>animation: fadeIn </span><span><span>0.5</span><span>s</span></span><span><span> </span><span>ease-out</span><span>;</span></span></div></div><div><div><div>13</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>旋转加载动画<a href="#旋转加载动画"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@keyframes</span><span><span> </span><span>rotate</span><span> {</span></span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>to {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>transform: </span><span>rotate</span><span>(</span><span><span>360</span><span>deg</span></span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>.loading</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>animation: rotate </span><span><span>1</span><span>s</span></span><span><span> </span><span>linear</span><span> </span><span>infinite</span><span>;</span></span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>上下浮动动画<a href="#上下浮动动画"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@keyframes</span><span><span> </span><span>float</span><span> {</span></span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>0%,</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>100% {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>transform: </span><span>translateY</span><span>(</span><span>0</span><span>);</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>50% {</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>transform: </span><span>translateY</span><span>(</span><span><span>-15</span><span>px</span></span><span>);</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>animation: float </span><span><span>2</span><span>s</span></span><span><span> </span><span>ease-in-out</span><span> </span><span>infinite</span><span>;</span></span></div></div><div><div><div>14</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h1>总结<a href="#总结"><span>#</span></a></h1><p><strong>Transition 与 Animation 的区别</strong></p>

<table><thead><tr><th>对比</th><th>Transition（过渡）</th><th>Animation（动画）</th></tr></thead><tbody><tr><td>是否需要触发</td><td>通常需要状态变化</td><td>可以自动执行</td></tr><tr><td>定义方式</td><td><code>transition</code></td><td><code>@keyframes</code> + <code>animation</code></td></tr><tr><td>变化过程</td><td>两个状态间的过渡</td><td>可以定义多个关键帧</td></tr><tr><td>循环播放</td><td>不直接支持循环次数</td><td>支持 <code>infinite</code></td></tr><tr><td>播放方向</td><td>随状态变化决定</td><td>支持方向设置</td></tr><tr><td>暂停控制</td><td>无专门暂停属性</td><td><code>animation-play-state</code></td></tr><tr><td>典型场景</td><td>按钮悬停、菜单展开</td><td>Loading、呼吸灯、循环动效</td></tr></tbody></table><p><strong>开发建议</strong></p><p>在 Vue3、React 等现代前端项目中，通常按照以下方式选择：</p><ul>
<li>按钮 Hover、导航栏高亮、卡片悬浮：使用 <code>transition</code>。</li>
<li>Loading 加载、循环旋转、呼吸灯：使用 <code>animation</code>。</li>
<li>弹窗进入退出、组件显示隐藏：通常通过组件状态切换配合 CSS 过渡或动画实现。</li>
<li>复杂的连续交互、精细时间轴控制：可以考虑 Web Animations API 或专门的动画库。</li>
</ul><p><strong>核心记忆：</strong></p><p><code>transition</code> 负责两个状态之间的平滑变化，<code>@keyframes</code> 负责定义动画过程，<code>animation</code> 负责调用和控制动画。</p><p>掌握这三者，以及 <code>ease</code>、<code>duration</code>、<code>delay</code> 和 <code>transform</code> 的组合，就足以完成大多数常见网页交互动效。</p></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026100901css3-zhong-de-transform-shu-xing-2d3d-zhuan-huan/</id>
      <title type="text">CSS3中的transform属性2D3D转换</title>
      <published>2026-10-09T00:18:45.000Z</published>
      <updated>2026-10-09T00:18:45.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026100901css3-zhong-de-transform-shu-xing-2d3d-zhuan-huan/"/>
      <summary type="text">学习CSS3中的transform属性2D3D转换</summary>
      <content type="html"><![CDATA[<section><h1>前言<a href="#前言"><span>#</span></a></h1><p>CSS 的 Transform（转换） 用于改变元素的视觉位置、角度、大小和形状，而不改变元素原本在文档流中占据的空间。主要分为两类：</p><ul>
<li>2D 转换：在平面上移动、旋转、缩放、倾斜。</li>
<li>3D 转换：在三维空间中移动、旋转、缩放，实现透视和立体效果。</li>
</ul></section>
<section><h1>旋转变形<a href="#旋转变形"><span>#</span></a></h1><p>旋转变形用于让元素围绕某个中心点进行旋转。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>transform: rotate(角度);</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>rotate(45deg)</code></td><td>顺时针旋转 45°</td></tr><tr><td><code>rotate(-45deg)</code></td><td>逆时针旋转 45°</td></tr><tr><td><code>rotate(90deg)</code></td><td>顺时针旋转 90°</td></tr><tr><td><code>rotate(180deg)</code></td><td>顺时针旋转 180°</td></tr><tr><td><code>rotate(360deg)</code></td><td>顺时针旋转一圈</td></tr></tbody></table><p>代码示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>height: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>background-color: </span><span>red</span><span>;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>transform: </span><span>rotate</span><span>(</span><span><span>45</span><span>deg</span></span><span>);</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><section><h2>设置旋转中心点<a href="#设置旋转中心点"><span>#</span></a></h2><p>默认情况下，元素围绕自身中心旋转。</p><p>可以使用 <code>transform-origin</code> 修改旋转中心。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>transform-origin: </span><span>center</span><span> </span><span>center</span><span>; </span><span>/* 默认中心 */</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>transform: </span><span>rotate</span><span>(</span><span><span>45</span><span>deg</span></span><span>);</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>常见属性值：</p>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>center</code></td><td>中心点，默认值</td></tr><tr><td><code>top left</code></td><td>左上角</td></tr><tr><td><code>top right</code></td><td>右上角</td></tr><tr><td><code>bottom left</code></td><td>左下角</td></tr><tr><td><code>bottom right</code></td><td>右下角</td></tr><tr><td><code>50% 50%</code></td><td>中心点</td></tr><tr><td><code>0 0</code></td><td>左上角</td></tr></tbody></table><p>注意：<code>transform-origin</code> 不仅影响旋转，也会影响缩放、斜切等变形效果。</p></section></section>
<section><h1>缩放变形<a href="#缩放变形"><span>#</span></a></h1><p>缩放变形用于放大或缩小元素。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>transform: scale(x, y);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li><code>x</code>：水平方向的缩放倍数。</li>
<li><code>y</code>：垂直方向的缩放倍数。</li>
<li>只传一个参数时，两个方向采用相同的缩放倍数。</li>
</ul>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>scale(1)</code></td><td>原始大小</td></tr><tr><td><code>scale(1.5)</code></td><td>放大至 1.5 倍</td></tr><tr><td><code>scale(0.5)</code></td><td>缩小至 0.5 倍</td></tr><tr><td><code>scale(2, 1)</code></td><td>宽度变为 2 倍，高度不变</td></tr><tr><td><code>scaleX(2)</code></td><td>仅水平方向放大 2 倍</td></tr><tr><td><code>scaleY(0.5)</code></td><td>仅垂直方向缩小一半</td></tr><tr><td><code>scale(-1, 1)</code></td><td>水平镜像翻转</td></tr></tbody></table><p>代码示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>height: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>background-color: </span><span>red</span><span>;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>transform: </span><span>scale</span><span>(</span><span>1.5</span><span>);</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><section><h2>缩放与 width、height 的区别<a href="#缩放与-widthheight-的区别"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/* 修改元素布局尺寸 */</span></div></div><div><div><div>2</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>width: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>height: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>/* 仅改变视觉大小 */</span></div></div><div><div><div>8</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>width: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>height: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>transform: </span><span>scale</span><span>(</span><span>2</span><span>);</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>两种方法视觉上都可能得到 200px × 200px 的盒子，但它们有本质区别：</p><ul>
<li><code>width</code>、<code>height</code>：改变元素布局尺寸，可能影响其他元素的排列。</li>
<li><code>scale()</code>：不会改变元素原有的布局占位。</li>
</ul><p><strong>实际应用： 图片悬停放大、按钮交互、卡片放大动画等。</strong></p></section></section>
<section><h1>斜切变形<a href="#斜切变形"><span>#</span></a></h1><p>斜切变形用于让元素沿水平或垂直方向发生倾斜。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>transform: skew(x角度, y角度);</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>skew(20deg)</code></td><td>水平方向斜切 20°</td></tr><tr><td><code>skew(20deg, 10deg)</code></td><td>水平和垂直方向同时斜切</td></tr><tr><td><code>skewX(20deg)</code></td><td>仅沿 X 轴方向斜切</td></tr><tr><td><code>skewY(20deg)</code></td><td>仅沿 Y 轴方向斜切</td></tr><tr><td><code>skewX(-20deg)</code></td><td>沿 X 轴反向斜切</td></tr></tbody></table><p>代码示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>height: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>background-color: </span><span>red</span><span>;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>transform: </span><span>skewX</span><span>(</span><span><span>20</span><span>deg</span></span><span>);</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><section><h2>skewX 与 skewY 的区别<a href="#skewx-与-skewy-的区别"><span>#</span></a></h2><ul>
<li><code>skewX()</code>：改变元素不同高度处的水平偏移，使左右边倾斜。</li>
<li><code>skewY()</code>：改变元素不同水平位置处的垂直偏移，使上下边倾斜。</li>
</ul><p>注意：<code>skew()</code> 是斜切，不是旋转。斜切通常会改变元素原有的角度和形状，而旋转会保持其形状不变。</p><p>实际应用： 倾斜按钮背景、装饰卡片、几何图形、特殊视觉效果等。</p></section></section>
<section><h1>位移变形<a href="#位移变形"><span>#</span></a></h1><p>位移变形用于让元素沿 X 轴或 Y 轴移动。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>transform: translate(x, y);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li><code>x</code>：水平方向位移，正数向右，负数向左。</li>
<li><code>y</code>：垂直方向位移，正数向下，负数向上。</li>
</ul>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>translate(50px, 20px)</code></td><td>向右 50px，向下 20px</td></tr><tr><td><code>translateX(100px)</code></td><td>向右移动 100px</td></tr><tr><td><code>translateX(-100px)</code></td><td>向左移动 100px</td></tr><tr><td><code>translateY(50px)</code></td><td>向下移动 50px</td></tr><tr><td><code>translateY(-50px)</code></td><td>向上移动 50px</td></tr><tr><td><code>translate(50%, 50%)</code></td><td>向右、向下各移动自身对应尺寸的 50%</td></tr></tbody></table><p>代码示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>height: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>background-color: </span><span>red</span><span>;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>transform: </span><span>translate</span><span>(</span><span><span>50</span><span>px</span></span><span>, </span><span><span>20</span><span>px</span></span><span>);</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><section><h3>1. translate 百分比的计算规则<a href="#1-translate-百分比的计算规则"><span>#</span></a></h3><p>这一点非常重要。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>height: </span><span><span>100</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>transform: </span><span>translate</span><span>(</span><span><span>50</span><span>%</span></span><span>, </span><span><span>50</span><span>%</span></span><span>);</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>结果：</p><ul>
<li>水平位移：200 × 50% = 100px。</li>
<li>垂直位移：100 × 50% = 50px。</li>
</ul><p>translate 的百分比通常是相对于元素自身的尺寸，而不是父元素。 这里讨论的是普通 HTML 元素默认的变形参考盒。</p></section><section><h2>使用 translate 实现绝对定位居中<a href="#使用-translate-实现绝对定位居中"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.parent</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>position: </span><span>relative</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>width: </span><span><span>500</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>height: </span><span><span>500</span><span>px</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>.child</span><span> {</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>position: </span><span>absolute</span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>top: </span><span><span>50</span><span>%</span></span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>left: </span><span><span>50</span><span>%</span></span><span>;</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>transform: </span><span>translate</span><span>(</span><span><span>-50</span><span>%</span></span><span>, </span><span><span>-50</span><span>%</span></span><span>);</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>原理：</p><ol>
<li><code>top: 50%</code>：让子元素的顶部移动到父元素高度的 50% 处。</li>
<li><code>left: 50%</code>：让子元素的左侧移动到父元素宽度的 50% 处。</li>
<li><code>translate(-50%, -50%)</code>：再向左、向上移动子元素自身宽高的一半。</li>
</ol><p>这样就实现了水平和垂直居中。</p><p>现代开发中，如果只是实现普通容器居中，通常使用 Flex 或 Grid 更简单。</p></section></section>
<section><h1>3D旋转<a href="#3d旋转"><span>#</span></a></h1><p>前面介绍的旋转、缩放、斜切和位移主要属于 2D 变形。3D 变形在原有 X、Y 轴的基础上引入 Z 轴（深度方向）。</p><section><h2>rotateX：绕 X 轴旋转<a href="#rotatex绕-x-轴旋转"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>transform: </span><span>rotateX</span><span>(</span><span><span>45</span><span>deg</span></span><span>);</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>元素围绕水平轴旋转，可以理解为上下翻转的效果。</p></section><section><h2>rotateY：绕 Y 轴旋转<a href="#rotatey绕-y-轴旋转"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>transform: </span><span>rotateY</span><span>(</span><span><span>45</span><span>deg</span></span><span>);</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>元素围绕垂直轴旋转，可以理解为左右翻转的效果。</p></section><section><h2>rotateZ：绕 Z 轴旋转<a href="#rotatez绕-z-轴旋转"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>transform: </span><span>rotateZ</span><span>(</span><span><span>45</span><span>deg</span></span><span>);</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>元素围绕垂直于屏幕的轴旋转。</p><p>在常见的平面元素上，<code>rotateZ(45deg)</code> 的视觉效果与 <code>rotate(45deg)</code> 相同。</p></section><section><h2>rotate3d：自定义旋转轴<a href="#rotate3d自定义旋转轴"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>transform: rotate3d(x, y, z, angle);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>前三个参数指定旋转轴的方向，最后一个参数指定旋转角度。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/* 绕 X 轴 */</span></div></div><div><div><div>2</div></div><div><span>transform: rotate3d(1, 0, 0, 45deg);</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>/* 绕 Y 轴 */</span></div></div><div><div><div>5</div></div><div><span>transform: rotate3d(0, 1, 0, 45deg);</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>/* 绕 Z 轴 */</span></div></div><div><div><div>8</div></div><div><span>transform: rotate3d(0, 0, 1, 45deg);</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>/* 绕 X、Y 都有分量的斜轴 */</span></div></div><div><div><div>11</div></div><div><span>transform: rotate3d(1, 1, 0, 45deg);</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>perspective：设置透视距离<a href="#perspective设置透视距离"><span>#</span></a></h2><p>单纯使用 3D 旋转，并不一定能看到明显的立体效果。</p><p>通常需要配合 <code>perspective</code> 实现透视。</p><p>代码示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;div </span><span>class="scene"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;div </span><span>class="box"</span><span>&gt;</span><span>3D BOX&lt;</span><span>/div&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;/div&gt;</span></div></div><div><div><div>4</div></div><div><span>.scene</span><span> {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>perspective: </span><span><span>800</span><span>px</span></span><span>;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>width: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>height: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>background-color: </span><span>red</span><span>;</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>transform: </span><span>rotateY</span><span>(</span><span><span>45</span><span>deg</span></span><span>);</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>perspective</code> 表示观察者与投影平面之间的距离：</p><ul>
<li><code>perspective: 400px</code>：透视效果较强。</li>
<li><code>perspective: 800px</code>：透视效果相对柔和。</li>
<li><code>perspective: 1500px</code>：透视效果较弱。</li>
</ul><p>需要注意，示例使用的是父元素的 <code>perspective</code> 属性。如果改用 <code>transform: perspective(800px) rotateY(45deg)</code>，透视函数和旋转函数都写在元素自身的 <code>transform</code> 中。</p><p>另外，制作嵌套 3D 场景时，还经常需要：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>transform-style: preserve-3d;</span></div></div><div><div><div>2</div></div><div><span>backface-visibility: hidden;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>分别用于保留子元素的 3D 空间关系、隐藏元素朝向背面的表面。</p></section></section>
<section><h1>transform 组合使用<a href="#transform-组合使用"><span>#</span></a></h1><p>前面五种变形并不是只能单独使用，还可以组合。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>transform: </span><span>translateX</span><span>(</span><span><span>100</span><span>px</span></span><span>) </span><span>rotate</span><span>(</span><span><span>45</span><span>deg</span></span><span>) </span><span>scale</span><span>(</span><span>1.5</span><span>);</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>该代码组合了位移、旋转和缩放。</p><p>但是要注意：变形函数的顺序非常重要。</p><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/* 位移距离不会被 scale 放大 */</span></div></div><div><div><div>2</div></div><div><span>transform: translateX(100px) scale(2);</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>/* 位移效果也会被 scale 放大 */</span></div></div><div><div><div>5</div></div><div><span>transform: scale(2) translateX(100px);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>理解时，可以把变形函数视为从右向左依次作用于元素。调换函数的顺序，最终效果可能完全不同。</p><p>另外，同一规则中连续书写两个 <code>transform</code> 声明，不会自动合并：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>transform: </span><span>rotate</span><span>(</span><span><span>45</span><span>deg</span></span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>transform: </span><span>scale</span><span>(</span><span>1.5</span><span>);</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>最终只会应用 <code>scale(1.5)</code>，因为后面的声明覆盖了前面的声明。</p></section>
<section><h1>总结：CSS3 变形属性速记<a href="#总结css3-变形属性速记"><span>#</span></a></h1>

<table><thead><tr><th>类型</th><th>函数</th><th>主要用途</th></tr></thead><tbody><tr><td>旋转</td><td><code>rotate()</code></td><td>2D 平面旋转</td></tr><tr><td>缩放</td><td><code>scale()</code></td><td>水平、垂直同时缩放</td></tr><tr><td>缩放</td><td><code>scaleX()</code></td><td>水平缩放</td></tr><tr><td>缩放</td><td><code>scaleY()</code></td><td>垂直缩放</td></tr><tr><td>斜切</td><td><code>skew()</code></td><td>水平、垂直斜切</td></tr><tr><td>斜切</td><td><code>skewX()</code></td><td>水平斜切</td></tr><tr><td>斜切</td><td><code>skewY()</code></td><td>垂直斜切</td></tr><tr><td>位移</td><td><code>translate()</code></td><td>水平、垂直位移</td></tr><tr><td>位移</td><td><code>translateX()</code></td><td>水平位移</td></tr><tr><td>位移</td><td><code>translateY()</code></td><td>垂直位移</td></tr><tr><td>3D 旋转</td><td><code>rotateX()</code></td><td>绕 X 轴旋转</td></tr><tr><td>3D 旋转</td><td><code>rotateY()</code></td><td>绕 Y 轴旋转</td></tr><tr><td>3D 旋转</td><td><code>rotateZ()</code></td><td>绕 Z 轴旋转</td></tr><tr><td>3D 旋转</td><td><code>rotate3d()</code></td><td>绕自定义 3D 轴旋转</td></tr><tr><td>辅助属性</td><td><code>transform-origin</code></td><td>设置变形中心点</td></tr><tr><td>辅助属性</td><td><code>perspective</code></td><td>设置透视距离</td></tr><tr><td>辅助属性</td><td><code>transform-style</code></td><td>控制子元素是否保留 3D 空间关系</td></tr><tr><td>辅助属性</td><td><code>backface-visibility</code></td><td>控制背面是否可见</td></tr></tbody></table><p>实际开发中，最值得优先掌握的是 <code>translate()</code>、<code>scale()</code> 和 <code>rotate()</code>。 它们在按钮交互、图片展示、卡片动画、抽屉菜单等场景中很常见。</p><p>最后要区分两个概念：</p><ul>
<li><code>transform</code>：决定元素变成什么样。</li>
<li><code>transition</code>：决定元素从原始状态变成目标状态时如何平滑过渡。</li>
</ul><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>transition: transform </span><span><span>0.3</span><span>s</span></span><span><span> </span><span>ease</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>.box</span><span>:hover</span></span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>transform: </span><span>translateY</span><span>(</span><span><span>-10</span><span>px</span></span><span>) </span><span>scale</span><span>(</span><span>1.05</span><span>);</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>鼠标悬停时，盒子会在 0.3 秒内向上移动 10px，并放大到 1.05 倍。这就是现代网页中非常常见的卡片悬停交互效果。</p></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026100804css3-bei-jing-yu-jian-bian/</id>
      <title type="text">CSS3背景与渐变</title>
      <published>2026-10-08T12:31:57.000Z</published>
      <updated>2026-10-08T12:31:57.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026100804css3-bei-jing-yu-jian-bian/"/>
      <summary type="text">学习CSS3背景与渐变</summary>
      <content type="html"><![CDATA[<section><h1>背景颜色基础知识<a href="#背景颜色基础知识"><span>#</span></a></h1><p>使用 <code>background-color</code> 设置元素的背景颜色。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background-color: </span><span>red</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>常用属性值：</p>

<table><thead><tr><th>属性值</th><th>说明</th><th>示例</th></tr></thead><tbody><tr><td>颜色名称</td><td>使用英文颜色名称</td><td><code>red</code></td></tr><tr><td>HEX</td><td>十六进制颜色</td><td><code>#ff0000</code></td></tr><tr><td>RGB</td><td>红、绿、蓝三通道</td><td><code>rgb(255 0 0)</code></td></tr><tr><td>RGBA</td><td>RGB 颜色与透明度</td><td><code>rgba(255, 0, 0, 0.5)</code></td></tr><tr><td>HSL</td><td>色相、饱和度、亮度</td><td><code>hsl(0 100% 50%)</code></td></tr><tr><td><code>transparent</code></td><td>完全透明</td><td><code>transparent</code></td></tr></tbody></table><p>注意：</p><ul>
<li><code>background-color</code> 默认值是 <code>transparent</code>。</li>
<li>背景颜色不会被子元素直接继承。</li>
<li>背景颜色通常覆盖元素的内容区、内边距和边框区域，但实际绘制范围可以由 <code>background-clip</code> 控制。</li>
</ul></section>
<section><h1>背景图片基础知识<a href="#背景图片基础知识"><span>#</span></a></h1><p>使用 <code>background-image</code> 设置元素的背景图片。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>width: </span><span><span>500</span><span>px</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>height: </span><span><span>300</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>background-image: </span><span>url</span><span>(</span><span>"/images/bg.jpg"</span><span>);</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>none</code></td><td>不使用背景图片，默认值</td></tr><tr><td><code>url()</code></td><td>指定背景图片地址</td></tr><tr><td><code>linear-gradient()</code></td><td>线性渐变背景</td></tr><tr><td><code>radial-gradient()</code></td><td>径向渐变背景</td></tr></tbody></table><p>背景图片与背景颜色同时使用：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background-color: </span><span>#</span><span>eee</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>background-image: </span><span>url</span><span>(</span><span>"/images/bg.jpg"</span><span>);</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>图片绘制在背景颜色上方，透明的图片区域可以显示下方的背景颜色。</p><p>注意： 背景图片默认会按照原始尺寸显示，并且平铺重复，不会自动铺满容器。</p></section>
<section><h1>背景图片的重复模式<a href="#背景图片的重复模式"><span>#</span></a></h1><p>使用 <code>background-repeat</code> 控制背景图片是否重复。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background-image: </span><span>url</span><span>(</span><span>"/images/bg.jpg"</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>background-repeat: </span><span>no-repeat</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>repeat</code></td><td>水平和垂直重复，默认值</td></tr><tr><td><code>no-repeat</code></td><td>不重复</td></tr><tr><td><code>repeat-x</code></td><td>只沿水平方向重复</td></tr><tr><td><code>repeat-y</code></td><td>只沿垂直方向重复</td></tr><tr><td><code>space</code></td><td>完整图片均匀排列，尽可能分配间距</td></tr><tr><td><code>round</code></td><td>调整图片尺寸，让重复图片刚好铺满</td></tr></tbody></table><p>在现代网页开发中，背景图通常搭配 <code>no-repeat</code>，例如网站 Banner、卡片背景等。小纹理背景则可以使用 <code>repeat</code>。</p></section>
<section><h1>背景尺寸<a href="#背景尺寸"><span>#</span></a></h1><p>使用 <code>background-size</code> 设置背景图片的显示尺寸。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background-image: </span><span>url</span><span>(</span><span>"/images/bg.jpg"</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>background-size: </span><span>cover</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>auto</code></td><td>保持图片原始尺寸或自动比例，默认值</td></tr><tr><td><code>cover</code></td><td>保持比例，覆盖整个容器，可能裁掉部分图片</td></tr><tr><td><code>contain</code></td><td>保持比例，完整显示图片，可能留白</td></tr><tr><td><code>100% 100%</code></td><td>强制填满容器，可能导致图片变形</td></tr><tr><td><code>200px 100px</code></td><td>指定宽度和高度</td></tr><tr><td><code>50% auto</code></td><td>宽度为背景定位区域的 50%，高度自动等比缩放</td></tr></tbody></table><p>实际开发中，最常使用的是：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.banner</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background-size: </span><span>cover</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>background-repeat: </span><span>no-repeat</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>背景裁切<a href="#背景裁切"><span>#</span></a></h1><p>使用 <code>background-clip</code> 控制背景的绘制范围。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background-color: </span><span>skyblue</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>background-clip: </span><span>padding-box</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>border-box</code></td><td>背景绘制到边框区域，默认值</td></tr><tr><td><code>padding-box</code></td><td>背景只绘制到内边距边缘，不延伸到边框区域</td></tr><tr><td><code>content-box</code></td><td>背景只绘制在内容区域</td></tr><tr><td><code>text</code></td><td>背景通过文字形状显示</td></tr></tbody></table><p>文字渐变的典型用法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.title</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background: </span><span>linear-gradient</span><span><span>(to </span><span>right</span><span>, </span></span><span>red</span><span>, </span><span>blue</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>background-clip: </span><span>text</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>color: </span><span>transparent</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意：<code>background-clip</code> 控制的是背景绘制区域，并不是直接调整图片的大小。另外还有 <code>background-origin</code>，用于控制背景图片定位时的参考区域，默认是 <code>padding-box</code>。不要和 <code>background-clip</code> 混淆</p></section>
<section><h1>背景固定<a href="#背景固定"><span>#</span></a></h1><p>使用 <code>background-attachment</code> 控制背景图片如何随着滚动发生变化。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background-image: </span><span>url</span><span>(</span><span>"/images/bg.jpg"</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>background-attachment: </span><span>fixed</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>scroll</code></td><td>背景跟随元素移动，不随元素内部内容滚动，默认值</td></tr><tr><td><code>fixed</code></td><td>背景相对视口固定</td></tr><tr><td><code>local</code></td><td>背景随元素内部的滚动内容一起移动</td></tr></tbody></table><p>常见用法：页面固定背景</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>body</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background-image: </span><span>url</span><span>(</span><span>"/images/bg.jpg"</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>background-size: </span><span>cover</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>background-attachment: </span><span>fixed</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>页面滚动时，背景相对于浏览器视口保持固定，可以实现一些固定背景视觉效果。</p><p>注意：<code>fixed</code> 在部分移动端浏览器中存在兼容性和显示行为差异，正式项目中需要测试。</p></section>
<section><h1>背景图片位置<a href="#背景图片位置"><span>#</span></a></h1><p>使用 <code>background-position</code> 控制背景图片在元素中的位置。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background-image: </span><span>url</span><span>(</span><span>"/images/bg.jpg"</span><span>);</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>background-position: </span><span>center</span><span> </span><span>center</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>left top</code></td><td>左上角，默认位置</td></tr><tr><td><code>center center</code></td><td>水平、垂直居中</td></tr><tr><td><code>right bottom</code></td><td>右下角</td></tr><tr><td><code>center top</code></td><td>水平居中，垂直顶部</td></tr><tr><td><code>50% 50%</code></td><td>水平、垂直居中</td></tr><tr><td><code>20px 40px</code></td><td>按水平、垂直偏移量定位</td></tr><tr><td><code>right 20px bottom 10px</code></td><td>距右边 20px，距底部 10px</td></tr></tbody></table><p>重点： <code>background-position: 50% 50%</code> 并不是把图片左上角放在容器中心，而是让图片自身的 50% 位置与容器的 50% 位置对齐，从而实现居中。</p><p>背景图通常会搭配下面的写法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background-size: </span><span>cover</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>background-position: </span><span>center</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>background-repeat: </span><span>no-repeat</span><span>;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>background综合属性<a href="#background综合属性"><span>#</span></a></h1><p><code>background</code> 是复合属性，可以在一条 CSS 声明中设置多个背景属性。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background: </span><span>#</span><span>eee</span><span> </span><span>url</span><span>(</span><span>"/images/bg.jpg"</span><span><span>) </span><span>center</span><span> / </span><span>cover</span><span> </span><span>no-repeat</span><span> </span><span>fixed</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这条代码相当于：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background-color: </span><span>#</span><span>eee</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>background-image: </span><span>url</span><span>(</span><span>"/images/bg.jpg"</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>background-position: </span><span>center</span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>background-size: </span><span>cover</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>background-repeat: </span><span>no-repeat</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>background-attachment: </span><span>fixed</span><span>;</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>常用背景属性汇总：</p>

<table><thead><tr><th>属性</th><th>作用</th><th>默认值</th></tr></thead><tbody><tr><td><code>background-color</code></td><td>背景颜色</td><td><code>transparent</code></td></tr><tr><td><code>background-image</code></td><td>背景图片</td><td><code>none</code></td></tr><tr><td><code>background-repeat</code></td><td>图片重复</td><td><code>repeat</code></td></tr><tr><td><code>background-size</code></td><td>图片尺寸</td><td><code>auto auto</code></td></tr><tr><td><code>background-clip</code></td><td>背景裁切</td><td><code>border-box</code></td></tr><tr><td><code>background-attachment</code></td><td>背景滚动行为</td><td><code>scroll</code></td></tr><tr><td><code>background-position</code></td><td>图片位置</td><td><code>0% 0%</code></td></tr><tr><td><code>background-origin</code></td><td>背景定位区域</td><td><code>padding-box</code></td></tr></tbody></table><p>注意三个问题：</p><ol>
<li><code>background</code> 不要求所有值遵循唯一固定顺序，但 <code>background-size</code> 必须紧跟在 <code>background-position</code> 后面，并使用 <code>/</code> 分隔。</li>
<li>使用 <code>background</code> 简写会重置未指定的背景子属性。</li>
<li>可以使用逗号设置多个背景图层，前面声明的图层显示在上方。</li>
</ol><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background:</span></div></div><div><div><div>3</div></div><div><span>    </span><span>linear-gradient</span><span><span>(to </span><span>right</span><span>, </span></span><span>#</span><span>0008</span><span><span>, </span><span>transparent</span><span>),</span></span></div></div><div><div><div>4</div></div><div><span>    </span><span>url</span><span>(</span><span>"/images/bg.jpg"</span><span><span>) </span><span>center</span><span> / </span><span>cover</span><span> </span><span>no-repeat</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这段代码在背景图片上覆盖了一层半透明渐变，常用于 Banner 上的文字可读性处理。</p></section>
<section><h1>线性渐变<a href="#线性渐变"><span>#</span></a></h1><p>使用 <code>linear-gradient()</code> 创建沿某个方向逐渐变化的颜色背景。</p><p>注意：<code>linear-gradient()</code> 是 CSS 图像函数，而不是独立的 CSS 属性。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background-image: linear-gradient(to right, red, blue);</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>渐变方向</strong></p>

<table><thead><tr><th>方向</th><th>说明</th></tr></thead><tbody><tr><td><code>to right</code></td><td>从左到右</td></tr><tr><td><code>to left</code></td><td>从右到左</td></tr><tr><td><code>to bottom</code></td><td>从上到下，默认</td></tr><tr><td><code>to top</code></td><td>从下到上</td></tr><tr><td><code>to bottom right</code></td><td>从左上到右下</td></tr><tr><td><code>45deg</code></td><td>使用角度指定渐变方向</td></tr></tbody></table><p>角度规则：<code>0deg</code> 指向上方、<code>90deg</code> 指向右方、<code>180deg</code> 指向下方、<code>270deg</code> 指向左方。</p><p><strong>多颜色渐变</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background: </span><span>linear-gradient</span><span>(</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>to </span><span>right</span><span>,</span></div></div><div><div><div>4</div></div><div><span>    </span><span>red</span><span>,</span></div></div><div><div><div>5</div></div><div><span>    </span><span>yellow</span><span>,</span></div></div><div><div><div>6</div></div><div><span>    </span><span>green</span><span>,</span></div></div><div><div><div>7</div></div><div><span>    </span><span>blue</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>);</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>指定颜色位置</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background: </span><span>linear-gradient</span><span>(</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>to </span><span>right</span><span>,</span></div></div><div><div><div>4</div></div><div><span>    </span><span>red</span><span> </span><span><span>0</span><span>%</span></span><span>,</span></div></div><div><div><div>5</div></div><div><span>    </span><span>yellow</span><span> </span><span><span>30</span><span>%</span></span><span>,</span></div></div><div><div><div>6</div></div><div><span>    </span><span>blue</span><span> </span><span><span>100</span><span>%</span></span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>);</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li><code>red 0%</code>：红色位于渐变起点。</li>
<li><code>yellow 30%</code>：黄色位于渐变路径的 30% 位置。</li>
<li><code>blue 100%</code>：蓝色位于渐变终点。</li>
</ul></section>
<section><h1>径向渐变<a href="#径向渐变"><span>#</span></a></h1><p>使用 <code>radial-gradient()</code> 创建从某个中心点向四周扩散的渐变。</p><p>基本语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background: </span><span>radial-gradient</span><span>(</span><span>red</span><span>, </span><span>blue</span><span>);</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>与线性渐变不同，径向渐变的颜色并不是沿直线变化，而是向周围扩散。</p><p><strong>常用属性值</strong></p>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>circle</code></td><td>圆形渐变</td></tr><tr><td><code>ellipse</code></td><td>椭圆形渐变，默认形状</td></tr><tr><td><code>at center</code></td><td>渐变中心位于元素中心，默认</td></tr><tr><td><code>at top left</code></td><td>渐变中心位于左上角</td></tr><tr><td><code>at 30% 70%</code></td><td>自定义渐变中心位置</td></tr><tr><td><code>closest-side</code></td><td>渐变末端到距离中心最近的边</td></tr><tr><td><code>farthest-side</code></td><td>渐变末端到距离中心最远的边</td></tr><tr><td><code>closest-corner</code></td><td>渐变末端到距离中心最近的角</td></tr><tr><td><code>farthest-corner</code></td><td>渐变末端到距离中心最远的角，默认</td></tr></tbody></table><p><strong>自定义径向渐变</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>background: </span><span>radial-gradient</span><span>(</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>circle</span><span> at </span><span><span>30</span><span>%</span></span><span> </span><span><span>40</span><span>%</span></span><span>,</span></div></div><div><div><div>4</div></div><div><span>    </span><span>red</span><span> </span><span><span>0</span><span>%</span></span><span>,</span></div></div><div><div><div>5</div></div><div><span>    </span><span>yellow</span><span> </span><span><span>40</span><span>%</span></span><span>,</span></div></div><div><div><div>6</div></div><div><span>    </span><span>blue</span><span> </span><span><span>100</span><span>%</span></span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>);</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>代码说明：</p><ul>
<li><code>circle</code>：渐变形状为圆形。</li>
<li><code>at 30% 40%</code>：渐变中心位于水平 30%、垂直 40% 的位置。</li>
<li><code>red 0%</code>：中心起点为红色。</li>
<li><code>yellow 40%</code>：渐变路径的 40% 位置为黄色。</li>
<li><code>blue 100%</code>：终点为蓝色。</li>
</ul></section>
<section><h1>总结：CSS 背景属性速记<a href="#总结css-背景属性速记"><span>#</span></a></h1>

<table><thead><tr><th>需求</th><th>推荐写法</th></tr></thead><tbody><tr><td>设置背景颜色</td><td><code>background-color: #fff</code></td></tr><tr><td>设置背景图片</td><td><code>background-image: url(...)</code></td></tr><tr><td>禁止背景重复</td><td><code>background-repeat: no-repeat</code></td></tr><tr><td>图片完整显示</td><td><code>background-size: contain</code></td></tr><tr><td>图片铺满容器</td><td><code>background-size: cover</code></td></tr><tr><td>只在内容区域绘制背景</td><td><code>background-clip: content-box</code></td></tr><tr><td>固定背景</td><td><code>background-attachment: fixed</code></td></tr><tr><td>图片水平垂直居中</td><td><code>background-position: center</code></td></tr><tr><td>背景综合设置</td><td><code>background: url(...) center / cover no-repeat</code></td></tr><tr><td>线性渐变</td><td><code>linear-gradient(to right, red, blue)</code></td></tr><tr><td>径向渐变</td><td><code>radial-gradient(circle, red, blue)</code></td></tr></tbody></table><p>实际开发最值得优先掌握的组合：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/* 网站 Banner */</span></div></div><div><div><div>2</div></div><div><span>.banner</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>height: </span><span><span>400</span><span>px</span></span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>background: </span><span>url</span><span>(</span><span>"/images/banner.jpg"</span><span><span>) </span><span>center</span><span> / </span><span>cover</span><span> </span><span>no-repeat</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>/* 卡片渐变背景 */</span></div></div><div><div><div>8</div></div><div><span>.card</span><span> {</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>background: </span><span>linear-gradient</span><span>(</span><span><span>135</span><span>deg</span></span><span>, </span><span>#</span><span>667eea</span><span>, </span><span>#</span><span>764ba2</span><span>);</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>/* 渐变文字 */</span></div></div><div><div><div>13</div></div><div><span>.title</span><span> {</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>background: </span><span>linear-gradient</span><span><span>(to </span><span>right</span><span>, </span></span><span>#</span><span>00c6ff</span><span>, </span><span>#</span><span>0072ff</span><span>);</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>background-clip: </span><span>text</span><span>;</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>color: </span><span>transparent</span><span>;</span></div></div><div><div><div>17</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026100803css3-bian-kuang-yuan-jiao-yin-ying-shu-xing/</id>
      <title type="text">CSS3边框圆角阴影属性</title>
      <published>2026-10-08T10:54:15.000Z</published>
      <updated>2026-10-08T10:54:15.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026100803css3-bian-kuang-yuan-jiao-yin-ying-shu-xing/"/>
      <summary type="text">学习CSS3边框圆角阴影等属性</summary>
      <content type="html"><![CDATA[<section><h1>边框<a href="#边框"><span>#</span></a></h1><p><strong>边框的三要素</strong>：border属性需要三个要素：线宽度-线型- 线颜色</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>border: 1px solid red;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>线型属性值</strong></p>

<table><thead><tr><th>线型值</th><th>意义</th></tr></thead><tbody><tr><td>solid</td><td>实线</td></tr><tr><td>dashed</td><td>虚线</td></tr><tr><td>dotted</td><td>点状线</td></tr></tbody></table><p><strong>边框的三要素小属性</strong></p>

<table><thead><tr><th>小属性</th><th>意义</th></tr></thead><tbody><tr><td>border-width</td><td>线宽</td></tr><tr><td>border-style</td><td>线型</td></tr><tr><td>border-color</td><td>线颜色</td></tr></tbody></table><p><strong>四个方向的边框</strong></p>

<table><thead><tr><th>小属性</th><th>意义</th></tr></thead><tbody><tr><td>border-top</td><td>上边框</td></tr><tr><td>border-right</td><td>右边框</td></tr><tr><td>border-bottom</td><td>下边框</td></tr><tr><td>border-left</td><td>左边框</td></tr></tbody></table><p><strong>四个方向边框的三要素小属性</strong></p>

<table><thead><tr><th>小属性</th><th>意义</th></tr></thead><tbody><tr><td>border-top-width</td><td>上边框宽度</td></tr><tr><td>border-top-style</td><td>上边框线型</td></tr><tr><td>border-top-color</td><td>上边框颜色</td></tr><tr><td>border-right-width</td><td>右边框宽度</td></tr><tr><td>border-right-style</td><td>右边框线型</td></tr><tr><td>border-right-color</td><td>右边框颜色</td></tr><tr><td>border-bottom-width</td><td>下边框宽度</td></tr><tr><td>border-bottom-style</td><td>下边框线型</td></tr><tr><td>border-bottom-color</td><td>下边框颜色</td></tr><tr><td>border-left-width</td><td>左边框宽度</td></tr><tr><td>border-left-style</td><td>左边框线型</td></tr><tr><td>border-left-color</td><td>左边框颜色</td></tr></tbody></table><p><strong>去掉边框</strong>：border-left: none;属性即可去掉左边框，以此类推</p><section><h2>利用边框制作三角形<a href="#利用边框制作三角形"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!</span><span>DOCTYPE</span><span> </span><span>html</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>html</span><span> </span><span>lang</span><span>=</span><span>"en"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;</span><span>head</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>meta</span><span> </span><span>charset</span><span>=</span><span>"UTF-8"</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>&lt;</span><span>meta</span><span> </span><span>name</span><span>=</span><span>"viewport"</span><span> </span><span>content</span><span>=</span><span>"width=device-width, initial-scale=1.0"</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>&lt;</span><span>title</span><span>&gt;Document&lt;/</span><span>title</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span>        </span><span>.triangle</span><span> {</span></div></div><div><div><div>9</div></div><div><span><span>            </span></span><span>width: </span><span>0</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>            </span></span><span>height: </span><span>0</span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>            </span></span><span>border-left: </span><span><span>50</span><span>px</span></span><span><span> </span><span>solid</span><span> </span><span>transparent</span><span>;</span></span></div></div><div><div><div>12</div></div><div><span><span>            </span></span><span>border-right: </span><span><span>50</span><span>px</span></span><span><span> </span><span>solid</span><span> </span><span>transparent</span><span>;</span></span></div></div><div><div><div>13</div></div><div><span><span>            </span></span><span>border-bottom: </span><span><span>100</span><span>px</span></span><span><span> </span><span>solid</span><span> </span></span><span>red</span><span>;</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>16</div></div><div><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>17</div></div><div><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"triangle"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>19</div></div><div><span>&lt;/</span><span>body</span><span>&gt;</span></div></div><div><div><div>20</div></div><div><span>&lt;/</span><span>html</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>
<section><h1>圆角<a href="#圆角"><span>#</span></a></h1><ul>
<li>
<p>border-radius属性的值通常为px单位，表示圆角的半径</p>
</li>
<li>
<p>border-radius属性可以单独设置四个圆角：左上-右上-右下-左下</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>border-radius: 10px 20px 30px 40px;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>圆角小属性</p>

<table><thead><tr><th>小属性</th><th>意义</th></tr></thead><tbody><tr><td>border-top-left-radius</td><td>左上角</td></tr><tr><td>border-top-right-radius</td><td>右上角</td></tr><tr><td>border-bottom-left-radius</td><td>左下角</td></tr><tr><td>border-bottom-right-radius</td><td>右下角</td></tr></tbody></table>
</li>
<li>
<p>border-radius属性的值也可以用百分比做单位，表示圆角 起始于每条边的哪里</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>border-radius: 20%;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p><strong>正圆形</strong>：正方形盒子如果设置的border-radius属性为50%，就是正 圆形</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>border-radius: 50%;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h1>盒子阴影<a href="#盒子阴影"><span>#</span></a></h1><p><strong>box-shadow属性</strong>：box-shadow属性用来实现盒子的阴影：x偏移-y偏移-模糊量- 颜色</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>box-shadow: 10px 20px 30px rgba(0,0,0,.4);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>阴影延展</strong>：x偏移-y偏移-模糊量- 阴影延展-颜色</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>box-shadow: 10px 20px 30px 40px rgba(0,0,0,.4);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>内阴影</strong>：box-shadow属性值前加inset单词，表示内阴影</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>box-shadow: inset 10px 20px 30px 40px rgba(0,0,0,.4);</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>多阴影</strong>：box-shadow属性值可以用逗号隔开多个，表示携带多个阴影</p></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026100802css3-ding-wei-shu-xing/</id>
      <title type="text">CSS3定位属性</title>
      <published>2026-10-08T02:43:25.000Z</published>
      <updated>2026-10-08T02:43:25.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026100802css3-ding-wei-shu-xing/"/>
      <summary type="text">学习CSS3定位属性</summary>
      <content type="html"><![CDATA[<section><h1>相对定位<a href="#相对定位"><span>#</span></a></h1><p><strong>概念</strong></p><ul>
<li>相对定位：盒子可以<strong>相对自己原来的位置进行位置调整</strong>，称为相对定位；</li>
<li>关键词：position: relative;</li>
<li>left 向右移动；right向左移动；top向下移动； bottom向上移动；值可以为负数，即往规定方向相反移动</li>
<li>相对定位的元素，会在“<strong>老家留坑”，本质上仍然是在原来 的位置</strong>，只不过渲染在新的地方而已，渲染的图形可以比喻 成“<strong>影子</strong>”，不会对页面其他元素产生任何影响</li>
</ul><p><strong>相对定位的用途</strong></p><ul>
<li>相对定位用来微调元素位置</li>
<li>相对定位的元素，可以当做绝对定位的参考盒子</li>
</ul></section>
<section><h1>绝对定位<a href="#绝对定位"><span>#</span></a></h1><p><strong>概念：</strong></p><ul>
<li>
<p>绝对定位：盒子可以在浏览器中以坐标进行位置精准描述， 拥有自己的绝对位置</p>
</li>
<li>
<p>关键词：position: absolute;</p>
</li>
<li>
<p>left 到左边的距离；right到右边的距离；top到上边的距离 ； bottom到下边的距离；值可以为负数，即往规定方向相反移动</p>
</li>
<li>
<p>绝对定位的元素脱离标准文档流，将释放自己的位置，对其 他元素不会产生任何干扰，而是对它们进行压盖</p>
</li>
<li>
<p>脱离标准文档流的方法：浮动、绝对定位、固定定位</p>
</li>
<li>
<p><strong>绝对定位的参考盒子：<strong>并不是永远以浏览器作为基准点，会以自己祖先元素中，<strong>离自己最近的拥有定 位属性的盒子，当做基准点</strong>。这个盒子</strong>通常是相对定位</strong>的， 所以这个性质也叫作“子绝父相”</p>
</li>
<li>
<p>绝对定位的盒子垂直居中是一个非常实用的技术</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>position: absolute;</span></div></div><div><div><div>2</div></div><div><span>top: 50%;</span></div></div><div><div><div>3</div></div><div><span>margin-top: -自己高度一半;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>绝对定位的用途</strong></p><ul>
<li>绝对定位用来制作“压盖” 、 “遮罩”效果</li>
<li>绝对定位用来结合CSS精灵使用</li>
<li>绝对定位可以结合JS实现动画</li>
</ul></section>
<section><h1>固定定位<a href="#固定定位"><span>#</span></a></h1><p><strong>概念：</strong></p><ul>
<li>
<p>固定定位：不管页面如何卷动，它永远固定在那里</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>position: fixed;</span></div></div><div><div><div>2</div></div><div><span>top: 100px;</span></div></div><div><div><div>3</div></div><div><span>left: 100px;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>固定定位注意事项</strong></p><ul>
<li>固定定位只能以页面为参考点，没有子固父相这个性质</li>
<li>固定定位脱离标准文档流</li>
</ul><p><strong>固定定位的用途</strong></p><ul>
<li>固定定位的用途：“返回顶部”、“楼层导航”</li>
</ul></section>
<section><h1>总结<a href="#总结"><span>#</span></a></h1><p>相对定位是相对自己定位，并且会占用原来位置；</p><p>绝对定位首先会参考离自己最近的定位元素做定位，如果没有就按照浏览器左上角开始定位，绝对定位会放弃自己原来位置</p><p>固定定位就是一直固定的位置，无论浏览器怎么滚动都是在一个位置</p></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026100801css3-fu-dong-shu-xing/</id>
      <title type="text">CSS3浮动属性</title>
      <published>2026-10-08T00:16:36.000Z</published>
      <updated>2026-10-08T00:16:36.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026100801css3-fu-dong-shu-xing/"/>
      <summary type="text">学习CSS 浮动：从基本原理到 BFC 与清除浮动</summary>
      <content type="html"><![CDATA[<section><h1>写在前面的话<a href="#写在前面的话"><span>#</span></a></h1><p>CSS 浮动（Float）最初主要用于实现图文混排，后来也被广泛用于网页布局。随着 Flexbox 和 Grid 的普及，浮动已经不再是现代网页布局的首选方案，但它仍然值得学习，因为它涉及 CSS 中几个重要概念：<strong>普通文档流、文字环绕、BFC 和高度塌陷</strong>。</p></section>
<section><h1>浮动的基本概念<a href="#浮动的基本概念"><span>#</span></a></h1><section><h2>什么是浮动？<a href="#什么是浮动"><span>#</span></a></h2><p>浮动是 CSS 提供的一种布局机制，通过 <code>float</code> 属性，使元素向其包含块的左侧或右侧移动，并允许周围的行内内容环绕它。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>float: </span><span>left</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>float</code> 常见属性值：</p>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>none</code></td><td>不浮动，默认值</td></tr><tr><td><code>left</code></td><td>向左浮动</td></tr><tr><td><code>right</code></td><td>向右浮动</td></tr></tbody></table><p>浮动元素会<strong>脱离普通文档流</strong>，但并<strong>不是完全不受布局规则约束</strong>。</p></section><section><h2>浮动元素的特点<a href="#浮动元素的特点"><span>#</span></a></h2><p>浮动主要具有以下几个特点：</p><ol>
<li><strong>脱离普通文档流</strong>：不再按照普通块级元素的布局方式占据空间。</li>
<li><strong>可以横向排列</strong>：多个浮动元素在空间足够时可以并排。</li>
<li><strong>具有文字环绕效果</strong>：周围的行内内容会避开浮动元素。</li>
<li><strong>受到布局规则约束</strong>：不能随意覆盖前面已经布局的元素。</li>
<li><strong>可能造成父元素高度塌陷</strong>：浮动元素不会按普通流的方式撑开父元素。</li>
</ol></section><section><h2>示例：浮动元素横向排列<a href="#示例浮动元素横向排列"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"c1"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"c2"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"c3"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span>.box {</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>width: 600px;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>border: 1px solid #000;</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>.box &gt; div {</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>width: 200px;</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>height: 200px;</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>float: left;</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>.box .c1 { background: orange; }</span></div></div><div><div><div>18</div></div><div><span>.box .c2 { background: blue; }</span></div></div><div><div><div>19</div></div><div><span>.box .c3 { background: green; }</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>三个元素全部设置 <code>float: left</code>，并且父容器宽度足够，因此它们会横向排列。</p><p>如果取消 <code>.c1</code> 的浮动：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> </span><span>.c1</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>float: </span><span>none</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>那么 <code>.c1</code> 会正常占据第一行，后面的 <code>.c2</code> 和 <code>.c3</code> 则在其下方浮动排列。</p><p>这是因为<strong>浮动元素虽然脱离普通文档流，但仍然受到前面元素位置的约束</strong>。这与后续的绝对定位的脱离文档流不一样</p></section><section><h2>浮动与普通文档流的区别<a href="#浮动与普通文档流的区别"><span>#</span></a></h2><p>普通块级元素通常按照从上到下的顺序排列。</p><p>而浮动元素会向左或向右移动，直到遇到容器边界、其他浮动元素，或者受到布局规则的限制。</p><p>需要注意：<strong>脱离普通文档流，不等于脱离所有布局规则。</strong></p><p>例如：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"normal"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"float"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>.normal {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>width: 200px;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>height: 200px;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>background: orange;</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>.float {</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>width: 200px;</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>height: 200px;</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>background: blue;</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>float: left;</span></div></div><div><div><div>16</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>蓝色盒子不会直接覆盖黄色盒子，而是从黄色盒子的下方开始浮动。但是，如果浮动元素后面出现普通块级元素，后者的盒子<strong>可能与浮动元素重叠</strong>，因为普通块级盒子的布局不会为浮动元素预留普通流空间。</p><p>上面说的是可能发生重叠，原因是：浮动元素脱离普通文档流，后面的普通块级盒子会忽略它占据的空间，但文字会避开它。主要区分是盒子还是文字</p></section><section><h2>浮动实现文字环绕<a href="#浮动实现文字环绕"><span>#</span></a></h2><p>文字环绕是浮动最典型的使用场景。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"c1"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>        </span></span><span>这是一段文章内容，当图片设置向左浮动后， 文字会自动围绕图片排列。</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>当文字超过图片高度时，</span></div></div><div><div><div>6</div></div><div><span><span>        </span></span><span>后面的文字会恢复占据完整的行宽。这是一段文章内容，当图片设置向左浮动后，</span></div></div><div><div><div>7</div></div><div><span><span>        </span></span><span>文字会自动围绕图片排列。 当文字超过图片高度时，</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>后面的文字会恢复占据完整的行宽。这是一段文章内容，当图片设置向左浮动后，</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>文字会自动围绕图片排列。 当文字超过图片高度时，</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>后面的文字会恢复占据完整的行宽。这是一段文章内容，当图片设置向左浮动后，</span></div></div><div><div><div>11</div></div><div><span><span>        </span></span><span>文字会自动围绕图片排列。 当文字超过图片高度时，</span></div></div><div><div><div>12</div></div><div><span><span>        </span></span><span>后面的文字会恢复占据完整的行宽。这是一段文章内容，当图片设置向左浮动后，</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>文字会自动围绕图片排列。 当文字超过图片高度时，</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>后面的文字会恢复占据完整的行宽。这是一段文章内容，当图片设置向左浮动后，</span></div></div><div><div><div>15</div></div><div><span><span>        </span></span><span>文字会自动围绕图片排列。 当文字超过图片高度时，</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>后面的文字会恢复占据完整的行宽。这是一段文章内容，当图片设置向左浮动后，</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>文字会自动围绕图片排列。 当文字超过图片高度时，</span></div></div><div><div><div>18</div></div><div><span><span>        </span></span><span>后面的文字会恢复占据完整的行宽。这是一段文章内容，当图片设置向左浮动后，</span></div></div><div><div><div>19</div></div><div><span><span>        </span></span><span>文字会自动围绕图片排列。 当文字超过图片高度时，</span></div></div><div><div><div>20</div></div><div><span><span>        </span></span><span>后面的文字会恢复占据完整的行宽。</span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>22</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>23</div></div><div><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>24</div></div><div><span>    </span><span>*</span><span> {</span></div></div><div><div><div>25</div></div><div><span><span>        </span></span><span>margin: </span><span>0</span><span>;</span></div></div><div><div><div>26</div></div><div><span><span>        </span></span><span>padding: </span><span>0</span><span>;</span></div></div><div><div><div>27</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>28</div></div><div><span>    </span><span>.box</span><span> {</span></div></div><div><div><div>29</div></div><div><span><span>        </span></span><span>width: </span><span><span>600</span><span>px</span></span><span>;</span></div></div><div><div><div>30</div></div><div><span><span>        </span></span><span>height: </span><span><span>400</span><span>px</span></span><span>;</span></div></div><div><div><div>31</div></div><div><span><span>        </span></span><span>border: </span><span><span>1</span><span>px</span></span><span><span> </span><span>solid</span><span> </span></span><span>#</span><span>000</span><span>;</span></div></div><div><div><div>32</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>33</div></div><div>
</div></div><div><div><div>34</div></div><div><span>    </span><span>.box</span><span> </span><span>&gt;</span><span> </span><span>div</span><span> {</span></div></div><div><div><div>35</div></div><div><span><span>        </span></span><span>width: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>36</div></div><div><span><span>        </span></span><span>height: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>37</div></div><div><span><span>        </span></span><span>float: </span><span>left</span><span>;</span></div></div><div><div><div>38</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>39</div></div><div>
</div></div><div><div><div>40</div></div><div><span>    </span><span>.box</span><span> </span><span>.c1</span><span> {</span></div></div><div><div><div>41</div></div><div><span><span>        </span></span><span>background: </span><span>orange</span><span>;</span></div></div><div><div><div>42</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>43</div></div><div>
</div></div><div><div><div>44</div></div><div><span>    </span><span>.box</span><span> </span><span>p</span><span> {</span></div></div><div><div><div>45</div></div><div><span><span>        </span></span><span>border: </span><span><span>1</span><span>px</span></span><span><span> </span><span>solid</span><span> </span></span><span>red</span><span>;</span></div></div><div><div><div>46</div></div><div><span><span>        </span></span><span>line-height: </span><span><span>20</span><span>px</span></span><span>;</span></div></div><div><div><div>47</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>48</div></div><div><span>&lt;/</span><span>style</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>这里需要理解一个细节：</p><ul>
<li><code>p</code> 的<strong>块级盒子</strong>不一定避开浮动元素。通过给p盒子加上边框可以观察到，p这个块级盒子，有一部分是被重叠的</li>
<li><code>p</code> <strong>内部的文字行</strong>会避开浮动元素。</li>
<li>当文字排到浮动元素下方时，就能重新使用整行空间。</li>
</ul><p>这也是为什么浮动能实现自然的图文混排。</p></section></section>
<section><h1>BFC 规范和浏览器差异<a href="#bfc-规范和浏览器差异"><span>#</span></a></h1><section><h2>什么是 BFC？<a href="#什么是-bfc"><span>#</span></a></h2><p>BFC，全称 <strong>Block Formatting Context（块级格式化上下文）</strong>。</p><p>它是 CSS 视觉格式化模型中的一种布局机制，决定了内部块级盒子如何排列，以及如何与浮动元素交互。</p><p>可以简单理解为：</p><p><strong>BFC 为内部元素建立了一套相对独立的块级布局环境。</strong></p><p>它不是一个 CSS 属性，而是一种由特定条件触发的布局机制。</p></section><section><h2>BFC 的主要特点<a href="#bfc-的主要特点"><span>#</span></a></h2>

<table><thead><tr><th>特点</th><th>说明</th></tr></thead><tbody><tr><td>内部布局独立</td><td>内部盒子的布局遵循所在 BFC 的规则</td></tr><tr><td>包含浮动高度</td><td>建立 BFC 的容器会计算内部浮动元素的高度</td></tr><tr><td>避开外部浮动</td><td>BFC 的盒子在空间允许时会避开旁边的浮动</td></tr><tr><td>阻止部分 margin 折叠</td><td>不同 BFC 之间的垂直外边距不会发生折叠</td></tr></tbody></table><p>需要注意，BFC 并不是完全隔离所有 CSS 行为。</p><p>例如，字体和颜色等可继承属性，仍然可以从父元素继承。</p></section><section><h2>如何触发 BFC？<a href="#如何触发-bfc"><span>#</span></a></h2><p>常见方式如下：</p>

<table><thead><tr><th>CSS 写法</th><th>说明</th></tr></thead><tbody><tr><td><code>display: flow-root</code></td><td>专门创建 BFC，推荐（2017年支持）</td></tr><tr><td><code>overflow: hidden</code></td><td>创建 BFC，但可能裁剪溢出内容（上古时期教学经常采用的）</td></tr><tr><td><code>overflow: auto</code></td><td>创建 BFC，可能出现滚动条</td></tr><tr><td><code>float: left/right</code></td><td>浮动元素自身建立 BFC</td></tr><tr><td><code>position: absolute</code></td><td>绝对定位元素建立独立的块级格式化上下文</td></tr><tr><td><code>display: inline-block</code></td><td>建立 BFC</td></tr><tr><td><code>display: flex</code></td><td>创建 Flex 格式化上下文，不是 BFC</td></tr><tr><td><code>display: grid</code></td><td>创建 Grid 格式化上下文，不是 BFC</td></tr></tbody></table><p>注意：Flex 和 Grid 虽然也会建立独立的布局上下文，但它们不是 BFC。</p></section><section><h2>示例：使用 flow-root 创建 BFC<a href="#示例使用-flow-root-创建-bfc"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;div class="box"&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;div class="child"&gt;&lt;/div&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;/div&gt;</span></div></div><div><div><div>4</div></div><div><span>.box {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>display: flow-root;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>border: 1px solid black;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>.child {</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>width: 200px;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>height: 200px;</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>background: orange;</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>float: left;</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>虽然 <code>.child</code> 设置了浮动，但 <code>.box</code> 仍然能够包含浮动元素的高度。这是 <code>flow-root</code> 的重要用途。</p></section><section><h2>BFC 如何避免外部浮动？<a href="#bfc-如何避免外部浮动"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;div class="left"&gt;&lt;/div&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;div class="right"&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>这里是右侧内容</span></div></div><div><div><div>4</div></div><div><span>&lt;/div&gt;</span></div></div><div><div><div>5</div></div><div><span>.left {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>width: 200px;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>height: 150px;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>float: left;</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>background: orange;</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>.right {</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>display: flow-root;</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>background: lightblue;</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p><code>.right</code> 建立了 BFC，因此它的边框盒会避开左侧的浮动元素。如果剩余空间不足以容纳 <code>.right</code>，它可能被放置到浮动元素下方。这与普通块级盒子可能延伸到浮动元素后面的行为不同。</p></section><section><h2>BFC 与浏览器差异<a href="#bfc-与浏览器差异"><span>#</span></a></h2><p>早期浏览器对 CSS 浮动、BFC 和元素尺寸的处理存在较多兼容性问题。</p><p>其中比较典型的是旧版 Internet Explorer 的 <code>hasLayout</code> 机制。</p><p>在 IE6、IE7 中，开发者有时使用：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>zoom: 1;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>触发 <code>hasLayout</code>，从而解决部分浮动和布局异常。但是必须注意：<code>**hasLayout**</code> **并不等于 BFC。**它们是不同的布局机制，只是某些表现存在相似之处。对于现代 Chrome、Firefox、Safari 和 Edge，通常不需要再使用这些旧浏览器兼容技巧。</p><p>实际开发中优先使用：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: flow-root;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>不过，BFC 的具体行为仍然要遵循 CSS 布局规范，不能将它理解成万能的样式隔离机制。</p></section></section>
<section><h1>清除浮动<a href="#清除浮动"><span>#</span></a></h1><section><h2>为什么需要清除浮动？<a href="#为什么需要清除浮动"><span>#</span></a></h2><p>先看一个示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;div class="box"&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;div class="child"&gt;&lt;/div&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;/div&gt;</span></div></div><div><div><div>4</div></div><div><span>.box {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>border: 2px solid black;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>.child {</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>width: 200px;</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>height: 200px;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>background: orange;</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>float: left;</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>此时 <code>.child</code> 脱离普通文档流，父元素 <code>.box</code> 不会按照普通块级子元素的方式计算它的高度。</p><p>因此，父元素可能出现高度塌陷。</p><p>所谓高度塌陷，就是：</p><p><strong>父元素没有被内部浮动元素撑开，导致高度小于预期。</strong></p><p>这可能造成后续元素布局异常、背景显示范围不正确，以及边框无法包围浮动元素等问题。</p></section><section><h2>clear 属性<a href="#clear-属性"><span>#</span></a></h2><p>CSS 提供 <code>clear</code> 属性控制元素是否必须避开前面对应方向的浮动元素。</p>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td><code>none</code></td><td>默认值，不清除浮动</td></tr><tr><td><code>left</code></td><td>清除前面的左浮动影响</td></tr><tr><td><code>right</code></td><td>清除前面的右浮动影响</td></tr><tr><td><code>both</code></td><td>清除前面的左右浮动影响</td></tr></tbody></table><p>示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;div class="box"&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;div class="child"&gt;&lt;/div&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;div class="clear"&gt;&lt;/div&gt;</span></div></div><div><div><div>4</div></div><div><span>&lt;/div&gt;</span></div></div><div><div><div>5</div></div><div><span>.child {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>width: 200px;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>height: 200px;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>background: orange;</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>float: left;</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>.clear {</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>clear: both;</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>.clear</code> 会被放置到前面浮动元素的下方。</p><p>因为它仍然处于普通文档流中，父容器能够获得相应高度。</p><p>但这种方式需要额外添加一个没有实际语义的 HTML 元素，因此并不推荐。</p></section><section><h2>使用伪元素清除浮动<a href="#使用伪元素清除浮动"><span>#</span></a></h2><p>传统开发中经常使用 <code>::after</code> 实现清除浮动。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.clearfix::after {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>content: "";</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>display: block;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>clear: both;</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>使用方式：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;div class="box clearfix"&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;div class="child"&gt;&lt;/div&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;/div&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>它的原理是：</p><ol>
<li>使用 <code>::after</code> 创建一个伪元素。</li>
<li>伪元素作为父元素内部的最后一个子盒子。</li>
<li><code>clear: both</code> 使其避开前面的浮动元素。</li>
<li>父元素因此能够包含相应的高度。</li>
</ol><p>这种方案不需要增加额外的 HTML 标签，兼容性也比较好。</p></section><section><h2>使用 overflow 清除浮动<a href="#使用-overflow-清除浮动"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>overflow: hidden;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>overflow: hidden</code> 能够建立 BFC，使父元素包含内部浮动元素的高度。</p><p>但存在一个问题：</p><p><strong>超出容器的内容可能被裁剪。</strong></p><p>例如，下拉菜单、阴影、绝对定位的装饰等溢出内容可能受到影响。</p><p>因此，不应该为了清除浮动而无条件使用 <code>overflow: hidden</code>。</p></section><section><h2>使用 flow-root 解决高度塌陷<a href="#使用-flow-root-解决高度塌陷"><span>#</span></a></h2><p>现代开发中，更推荐使用：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>display: flow-root;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>它具有几个优点：</p><ul>
<li>创建 BFC。</li>
<li>包含内部浮动元素的高度。</li>
<li>不需要额外 HTML 元素。</li>
<li>不会像 <code>overflow: hidden</code> 一样主动裁剪溢出内容。</li>
<li>语义明确，专门用于建立新的块级格式化上下文。</li>
</ul><p>需要区分两个概念：</p><p><code>**clear: both**</code> <strong>是清除前面浮动对自身位置的影响；</strong><code>**display: flow-root**</code> <strong>是通过创建 BFC，让容器包含内部浮动元素。</strong></p><p>两者可以解决一些相似的布局问题，但原理并不相同。</p></section><section><h2>清除浮动方案对比<a href="#清除浮动方案对比"><span>#</span></a></h2>

<table><thead><tr><th>方法</th><th>原理</th><th>推荐程度</th></tr></thead><tbody><tr><td>额外元素 + <code>clear</code></td><td>让普通流元素避开浮动</td><td>不推荐</td></tr><tr><td><code>::after</code> + <code>clear</code></td><td>利用伪元素清除浮动</td><td>兼容旧项目时使用</td></tr><tr><td><code>overflow: hidden</code></td><td>创建 BFC</td><td>特定场景使用</td></tr><tr><td><code>display: flow-root</code></td><td>创建 BFC 并包含浮动</td><td>现代开发推荐</td></tr></tbody></table><p>示例代码：</p><p>额外元素 + <code>clear: both</code>（不推荐）</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"child"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"clear"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>.box {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>border: 1px solid black;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div><span>.child {</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>width: 200px;</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>height: 200px;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>background: orange;</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>float: left;</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div><div><div><div>14</div></div><div><span>.clear {</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>clear: both;</span></div></div><div><div><div>16</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>原理： 在浮动元素后面添加一个普通块级元素，使用 <code>clear: both</code> 让它移动到浮动元素下方，从而撑开父容器。</p><p>缺点： 需要增加没有实际语义的 HTML 标签。</p><p><code>::after</code> + <code>clear: both</code>（传统推荐）</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box clearfix"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"child"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>.box {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>border: 1px solid black;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>.child {</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>width: 200px;</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>height: 200px;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>background: orange;</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>float: left;</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>.clearfix::after {</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>content: "";</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>display: block;</span></div></div><div><div><div>18</div></div><div><span><span>  </span></span><span>clear: both;</span></div></div><div><div><div>19</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>原理： 通过 <code>::after</code> 在父元素内部创建一个伪元素，再利用 <code>clear: both</code> 撑开父容器。其实就是第一种方式的衍生，把标签换成伪元素了</p><p>优点： 不需要额外的 HTML 标签，兼容性好。</p><p><code>overflow: hidden</code>（特定场景使用）</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"child"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>.box {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>border: 1px solid black;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>overflow: hidden;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>.child {</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>width: 200px;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>height: 200px;</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>background: orange;</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>float: left;</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>原理： <code>overflow: hidden</code> 会创建 BFC，使父元素在计算自动高度时包含内部浮动元素。</p><p>缺点： 超出容器的内容可能被裁剪，比如阴影、下拉菜单等。</p><p><code>display: flow-root</code>（现代推荐）</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"child"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>.box {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>border: 1px solid black;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>display: flow-root;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>.child {</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>width: 200px;</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>height: 200px;</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>background: orange;</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>float: left;</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>原理： 直接创建 BFC，使父元素在计算自动高度时包含内部浮动元素。</p><p>优点： 不需要额外标签或伪元素，也不会因为创建 BFC 而裁剪溢出内容。</p><p>记住两种原理即可：</p><ul>
<li><code>clear</code>：让一个普通流中的盒子避开前面的浮动，借助它撑开父容器。</li>
<li><code>BFC</code>：让父容器在计算自动高度时包含内部浮动元素。</li>
</ul></section></section>
<section><h1>总结<a href="#总结"><span>#</span></a></h1><p>浮动、BFC 和清除浮动之间存在直接联系：</p><ol>
<li><strong>浮动</strong>：让元素向左或向右移动，脱离普通文档流，同时实现文字环绕。</li>
<li><strong>BFC</strong>：规定一组块级盒子的布局行为，能够处理浮动高度包含、外部浮动避让等问题。</li>
<li><strong>清除浮动</strong>：解决浮动引起的布局影响，尤其是父元素高度塌陷问题。</li>
</ol><p>现代开发可以记住以下原则：</p><ul>
<li><strong>页面整体布局</strong>：优先使用 Flexbox 和 Grid。</li>
<li><strong>文章图片文字环绕</strong>：使用 <code>float</code>。</li>
<li><strong>需要清除前面的浮动影响</strong>：使用 <code>clear</code>。</li>
<li><strong>需要父元素包含浮动高度</strong>：优先考虑 <code>display: flow-root</code>。</li>
<li><strong>维护旧项目</strong>：认识 <code>clearfix</code> 和 <code>overflow</code> 等传统处理方式。</li>
</ul><p>浮动并没有过时，只是已经不适合承担整个网页布局的主要职责。理解它的规则，才是学习浮动的真正目的。</p><p><img alt="" /></p></section>
<section><h1>拓展示例<a href="#拓展示例"><span>#</span></a></h1><p>clear: both：</p><ul>
<li>
<p>给<code>.c2</code>增加<code>clear: both;</code>，清除<code>.c1</code>浮动对<code>.c2</code>的影响，顺便撑开了盒子，box2也可以正常写在后面</p>
</li>
<li>
<p>如果取消 clear: both，高度也不会塌陷，但是<code>.c2</code>会被<code>.c1</code>重叠了，不会塌陷是因为被<code>.c2</code>这个没有浮动的盒子撑开并非.c1</p>
</li>
<li>
<p>特别注意的一点：元素是会被重叠，文字不会，这是之前多次提到的</p>
</li>
<li>
<p>假设C2也浮动呢？虽然可以依旧在C2加clear: both，但是此时高度仍然不会被撑起来，所以这里就需要多加dmo节点或者伪元素</p>
</li>
<li>
<p>父盒子的宽度如果不够后面盒子的宽度，后面的盒子就会自动掉到下面</p>
</li>
</ul><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!</span><span>doctype</span><span> </span><span>html</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>html</span><span> </span><span>lang</span><span>=</span><span>"en"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>head</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>meta</span><span> </span><span>charset</span><span>=</span><span>"UTF-8"</span><span> /&gt;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>&lt;</span><span>meta</span><span> </span><span>name</span><span>=</span><span>"viewport"</span><span> </span><span>content</span><span>=</span><span>"width=device-width, initial-scale=1.0"</span><span> /&gt;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>&lt;</span><span>title</span><span>&gt;Document&lt;/</span><span>title</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span>      </span><span>*</span><span> {</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>margin: </span><span>0</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>padding: </span><span>0</span><span>;</span></div></div><div><div><div>11</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>      </span><span>.box</span><span> {</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>width: </span><span><span>400</span><span>px</span></span><span>;</span></div></div><div><div><div>14</div></div><div><span>        </span><span>/* 让内部盒子撑开高度 */</span></div></div><div><div><div>15</div></div><div><span>        </span><span>/* height: 400px; */</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>background-color: </span><span>#</span><span>ccc</span><span>;</span></div></div><div><div><div>17</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>18</div></div><div><span>      </span><span>.c1</span><span> {</span></div></div><div><div><div>19</div></div><div><span><span>        </span></span><span>width: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>20</div></div><div><span><span>        </span></span><span>height: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>21</div></div><div><span><span>        </span></span><span>background-color: </span><span>red</span><span>;</span></div></div><div><div><div>22</div></div><div><span><span>        </span></span><span>float: </span><span>left</span><span>;</span></div></div><div><div><div>23</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>24</div></div><div><span>      </span><span>.c2</span><span> {</span></div></div><div><div><div>25</div></div><div><span><span>        </span></span><span>width: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>26</div></div><div><span><span>        </span></span><span>height: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>27</div></div><div><span><span>        </span></span><span>background-color: </span><span>green</span><span>;</span></div></div><div><div><div>28</div></div><div><span>        </span><span>/* 清除浮动对自己的影响 */</span></div></div><div><div><div>29</div></div><div><span><span>        </span></span><span>clear: </span><span>both</span><span>;</span></div></div><div><div><div>30</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>31</div></div><div><span>      </span><span>.box2</span><span> {</span></div></div><div><div><div>32</div></div><div><span><span>        </span></span><span>width: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>33</div></div><div><span><span>        </span></span><span>height: </span><span><span>200</span><span>px</span></span><span>;</span></div></div><div><div><div>34</div></div><div><span><span>        </span></span><span>background-color: </span><span>blue</span><span>;</span></div></div><div><div><div>35</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>36</div></div><div><span><span>    </span></span><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>37</div></div><div><span><span>  </span></span><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>38</div></div><div><span><span>  </span></span><span>&lt;</span><span>body</span><span>&gt;</span></div></div><div><div><div>39</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box"</span><span>&gt;</span></div></div><div><div><div>40</div></div><div><span><span>      </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"c1"</span><span>&gt;C1左浮动&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>41</div></div><div><span><span>      </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"c2"</span><span>&gt;C2正常&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>42</div></div><div><span><span>      </span></span><span>&lt;</span><span>span</span><span>&gt;span&lt;/</span><span>span</span><span>&gt;</span></div></div><div><div><div>43</div></div><div><span><span>      </span></span><span>&lt;</span><span>span</span><span>&gt;span&lt;/</span><span>span</span><span>&gt;</span></div></div><div><div><div>44</div></div><div><span><span>    </span></span><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>45</div></div><div><span><span>    </span></span><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box2"</span><span>&gt;box2&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>46</div></div><div><span><span>  </span></span><span>&lt;/</span><span>body</span><span>&gt;</span></div></div><div><div><div>47</div></div><div><span>&lt;/</span><span>html</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026100703css3-he-mo-xing/</id>
      <title type="text">CSS3盒模型</title>
      <published>2026-10-07T08:33:56.000Z</published>
      <updated>2026-10-07T08:33:56.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026100703css3-he-mo-xing/"/>
      <summary type="text">学习CSS3盒模型</summary>
      <content type="html"><![CDATA[<section><h1>认识盒模型<a href="#认识盒模型"><span>#</span></a></h1><p><strong>什么是盒模型</strong></p><ul>
<li>所有HTML标签都可以看成矩形盒子，由width、height、 padding、border构成，称为“盒模型”，宽-高-内边距-边框组成，注意：外边距不属于盒子的宽高</li>
</ul><p><strong>width、height不是盒子总宽高</strong></p><ul>
<li>盒子的总宽度 = width + 左右padding + 左右border</li>
<li>盒子的总高度 = height + 上下padding + 上下border</li>
</ul><p><strong>width属性</strong>和<strong>height属性</strong></p><ul>
<li>
<p>width属性表示盒子内容的宽度，height属性表示盒子内容的高度</p>
</li>
<li>
<p>width属性和height属性的单位通常是px，移动端开发也会涉及百分数、 rem等单位</p>
</li>
<li>
<p>当块级元素（div、h系列、li等）没有设置width属性时，它 将自动撑满，但这并不意味着width可以继承</p>
</li>
<li>
<p>盒子的height属性如果不设置，它将自动被其内容撑开，如 果没有内容，则height默认是0</p>
</li>
</ul></section>
<section><h1>padding属性详解<a href="#padding属性详解"><span>#</span></a></h1><ul>
<li>
<p>padding是盒子的内边距，即盒子边框内壁到文字的距离</p>
</li>
<li>
<p>有四个方向的padding，分别用小属性进行设置</p>

<table><thead><tr><th>属性</th><th>意义</th></tr></thead><tbody><tr><td>padding-top</td><td>上padding</td></tr><tr><td>padding-right</td><td>右padding</td></tr><tr><td>padding-bottom</td><td>下padding</td></tr><tr><td>padding-left</td><td>左padding</td></tr></tbody></table>
</li>
</ul><p><strong>padding的多数值写法</strong></p><ul>
<li>padding属性如果用<strong>四个数值</strong>以空格隔开进行设置，分别表 示<strong>上、右、下、左</strong>的padding</li>
<li>padding属性如果用<strong>三个数值</strong>以空格隔开进行设置，分别表 示<strong>上、左右、下</strong>的padding</li>
<li>padding属性如果用<strong>二个数值</strong>以空格隔开进行设置，分别表 示<strong>上下、左右</strong>的padding</li>
</ul></section>
<section><h1>margin属性详解<a href="#margin属性详解"><span>#</span></a></h1><ul>
<li>
<p>margin是盒子的外边距，即盒子和其他盒子之间的距离</p>
</li>
<li>
<p><strong>margin也有四个方向</strong></p>

<table><thead><tr><th>小属性</th><th>意义</th></tr></thead><tbody><tr><td>margin-top</td><td>上margin，“向上踹”</td></tr><tr><td>margin-right</td><td>右margin，“向右踹”</td></tr><tr><td>margin-bottom</td><td>下margin，“向下踹”</td></tr><tr><td>margin-left</td><td>左margin，“向左踹”</td></tr></tbody></table>
</li>
</ul></section>
<section><h1>盒模型计算<a href="#盒模型计算"><span>#</span></a></h1><p><strong>width、height不是盒子总宽高</strong></p><ul>
<li>盒子的总宽度 = width + 左右padding + 左右border</li>
<li>盒子的总高度 = height + 上下padding + 上下border</li>
</ul><p>CSS写的width和height 不是盒子的宽高，而是内容区域 的宽高，如果写padding或者border就会把盒子撑大，这是因为CSS<strong>默认是box-sizing：content-box；</strong></p>

<table><thead><tr><th>属性</th><th>content-box</th><th>border-box</th></tr></thead><tbody><tr><td>width 、height 表示</td><td>content区</td><td>content+padding+border</td></tr><tr><td>padding 会撑大盒子</td><td>会</td><td>不会</td></tr><tr><td>border 会撑大盒子</td><td>会</td><td>不会</td></tr><tr><td>是否默认</td><td>是</td><td>否</td></tr><tr><td>现代开发推荐</td><td>一般不用</td><td>推荐</td></tr></tbody></table><p><strong>box-sizing属性</strong></p><ul>
<li>将盒子添加了box-sizing: border-box; 之后，盒子的width 、height数字就表示盒子实际占有的宽高（不含margin） 了，即padding、border变为“内缩”的，不再“外扩”</li>
<li>box-sizing属性大量应用于移动网页制作中，因为它结合百 分比布局、弹性布局等非常好用，在PC页面开发中使用较少</li>
<li>box-sizing属性兼容到IE9</li>
</ul></section>
<section><h1>盒模型其他属性<a href="#盒模型其他属性"><span>#</span></a></h1><p><strong>行内元素和块级元素的相互转换</strong>：display属性</p>

<table><thead><tr><th>display属性类型</th><th>是否能 并排显示</th><th>是否能 设置宽高</th><th>当不设置width属性时</th><th>举例</th></tr></thead><tbody><tr><td>块级元素</td><td>否</td><td>是</td><td>width自动撑满</td><td>div、section、header、 h系列、li、ul等</td></tr><tr><td>行内元素</td><td>是</td><td>否</td><td>width自动收缩</td><td>a、span、em、b、u、i 等</td></tr></tbody></table><ul>
<li>使用display;即可将元素转为块级元素</li>
<li>使用display;即可将元素转为行内元素，将元素转为行内元素的应用不多见</li>
<li>使用display;即可将元素转为行内块</li>
<li>img和表单元素是特殊的行内块，它们既能够设置宽度高度 ，也能够并排显示</li>
</ul><p><strong>元素的隐藏</strong>：display: none;</p><ul>
<li>使用display: none;可以将元素隐藏，元素将彻底放弃位置，如同没有写它的标签一样，但是dom依然存在</li>
<li>使用visibility: hidden;可以也可以将元素隐藏，但是元素不放弃自己的位置</li>
</ul></section>
<section><h1>拓展盒模型的一些特性<a href="#拓展盒模型的一些特性"><span>#</span></a></h1><p><strong>margin的塌陷</strong></p><ul>
<li>竖直方向的margin有塌陷现象：小的margin会塌陷到大的 margin中，从而margin不叠加，只以大值为准</li>
</ul><p><strong>一些元素有默认的margin和padding</strong></p><ul>
<li>一些元素（比如body、ul、p等）都有默认的margin，在开 始制作网页的时候，要将他们清除</li>
</ul><p><strong>盒子的水平居中</strong></p><ul>
<li>
<p>将盒子左右两边的margin都设置为auto，盒子将水平居中</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>margin: </span><span>0</span><span><span> </span><span>auto</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>文本居中是text-align: center; 和盒子水平居中是两个概念</p>
</li>
<li>
<p>盒子的垂直居中，需要使用绝对定位技术实现</p>
</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026100702css3-san-da-te-xing/</id>
      <title type="text">CSS3三大特性</title>
      <published>2026-10-07T07:06:57.000Z</published>
      <updated>2026-10-07T07:06:57.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026100702css3-san-da-te-xing/"/>
      <summary type="text">学习CSS3三大特性：层叠性、继承性和优先级</summary>
      <content type="html"><![CDATA[<section><h1>CSS三大特性<a href="#css三大特性"><span>#</span></a></h1><p>常说的三大特性分别是层叠性、继承性和优先级，它们的区别如下：</p>

<table><thead><tr><th>特性</th><th>含义</th><th>关键词</th></tr></thead><tbody><tr><td><strong>层叠性</strong></td><td>多个 CSS 样式同时作用于同一个元素时，最终会按照规则决定哪些样式生效</td><td>后来者、冲突</td></tr><tr><td><strong>继承性</strong></td><td>子元素可以继承父元素的部分 CSS 属性</td><td><code>color</code>、<code>font-*</code> 等</td></tr><tr><td><strong>优先级</strong></td><td>当多个选择器都选中同一个元素，并且设置了同一个属性时，比较谁的权重更高</td><td>权重、specificity</td></tr></tbody></table><p>最容易混的是 <strong>层叠性和优先级</strong>，因为它们有一定的关系，多个 CSS 样式同时作用于同一个元素时，最终会按照规则决定哪些样式生效，这个规则就是优先级</p></section>
<section><h1>层叠性<a href="#层叠性"><span>#</span></a></h1><p>说白了就是同一个元素被设置了多个相同属性，一层一层叠加，就是CSS的层叠性。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"content"</span><span>&gt;这是一个div&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>.content {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>color: aqua;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div><span>div {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>background-color: bisque;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这样叠加了color和background-color属性，但是叠加会引诱出另外一个性质：优先级，当一个样式重复叠加的时候，应该生效哪个样式呢，这时候就需要优先级来判断</p></section>
<section><h1>优先级<a href="#优先级"><span>#</span></a></h1><p>叠加性通常会引发样式冲突，到底哪个样式生效，这时候就需要：<strong>选择器权重计算</strong></p><ul>
<li>id权重 &gt; class权重 &gt; 标签权重</li>
<li>复杂选择器可以通过（<strong>id的个数, class的个数, 标签的个数</strong>）的形式，计算权重</li>
</ul><p>那再极端一些，权重一样呢，那就按照后写覆盖先写的，就近原则，直接写在标签内的样式生效-&gt;嵌入页面的生效-&gt;引入的生效</p></section>
<section><h1>继承性<a href="#继承性"><span>#</span></a></h1><p>后代元素可以继承父元素的部分属性：父元素如果有可继承的属性，再其后代都会基础这个属性；<strong>继承属性会沿着 DOM 层级向后代元素传递，不限于直接子元素。</strong></p><p>常见可继承：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>color</span></div></div><div><div><div>2</div></div><div><span>font-size</span></div></div><div><div><div>3</div></div><div><span>font-family</span></div></div><div><div><div>4</div></div><div><span>font-weight</span></div></div><div><div><div>5</div></div><div><span>line-height</span></div></div><div><div><div>6</div></div><div><span>text-align</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026100701css3-wen-ben-yu-zi-ti-shu-xing/</id>
      <title type="text">CSS3文本与字体属性</title>
      <published>2026-10-06T23:00:00.000Z</published>
      <updated>2026-10-06T23:00:00.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026100701css3-wen-ben-yu-zi-ti-shu-xing/"/>
      <summary type="text">学习CSS3中的文本与字体相关属性</summary>
      <content type="html"><![CDATA[<section><h1>前言<a href="#前言"><span>#</span></a></h1><p>CSS3的文本与字体属性算是CSS中基础中的基础，学习文本与字体属性可以修改网页中字体形式和样式，这里的文本与字体是有区别，虽然看着意思差不多，都是在描述文字的样式，它们区别如下：</p><p><strong>字体属性 = 字长什么样。</strong>
<strong>文本属性 = 文字怎么排列、怎么表现。</strong></p>

<table><thead><tr><th>类别</th><th>主要控制什么</th><th>常见属性</th></tr></thead><tbody><tr><td>字体 Font</td><td>字体本身的外观</td><td><code>font-family</code>、<code>font-size</code>、<code>font-weight</code>、<code>font-style</code>、<code>font-variant</code>、<code>font</code></td></tr><tr><td>文本 Text</td><td>文字的排列、间距、装饰、对齐等</td><td><code>color</code>、<code>text-align</code>、<code>text-decoration</code>、<code>text-indent</code>、<code>text-transform</code>、<code>letter-spacing</code>、<code>word-spacing</code>、<code>line-height</code>、<code>text-shadow</code>、<code>white-space</code></td></tr></tbody></table></section>
<section><h1>常用文本样式属性<a href="#常用文本样式属性"><span>#</span></a></h1><p><strong>color属性</strong></p><ul>
<li>color 属性可设置文本内容的前景色</li>
<li>color 属性主要可以用英语单词、十六进制、rgb()、rgba() 等表示法</li>
<li>英语单词表示法，比如 color: red;仅仅用于学习时临时设 置一下颜色，工作时基本不用这样的形式，因为追求精确</li>
</ul><p><strong>color属性 - 十六进制表示法</strong></p><ul>
<li>十六进制表示法是所有设计软件中都通用的颜色表示法，设 计师给我们的设计图上面标注的颜色，通常为十六进制表示</li>
<li>比如十六进制ff就是十进制的255，每种颜色分量都是0~255 的数字</li>
<li>如果颜色值是#aabbcc的形式，可以简写为#abc</li>
<li>黑色是#000，白色是#fff，常见的灰色有#ccc、#333、 #2f2f2f等</li>
</ul><p><strong>color属性 - rgb()表示法</strong></p><ul>
<li>颜色也可以用rgb()表示法</li>
<li>颜色也可以用rgba()表示法，最后一个参数表示透明度，介 于0到1之间，0表示纯透明，1表示纯实心</li>
<li>rgba()表示法从IE9开始兼容</li>
</ul><p><strong>text-decoration属性</strong></p><ul>
<li>
<p>text-decoration属性用于设置文本的修饰线外观的（下划 线、删除线）</p>

<table><thead><tr><th>值</th><th>含义</th></tr></thead><tbody><tr><td><code>none</code></td><td>没有装饰线</td></tr><tr><td><code>underline</code></td><td>下划线</td></tr><tr><td><code>line-through</code></td><td>删除线</td></tr><tr><td><code>overline</code></td><td>上划线</td></tr></tbody></table>
</li>
</ul><p><strong>text-indent属性</strong></p><ul>
<li>text-indent属性定义首行文本内容之前的缩进量，缩进两个 字符应该写作</li>
</ul><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>text-indent: 2em;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>line-height属性</strong></p><ul>
<li>line-height属性用于定义行高</li>
<li>line-heigh属性的单位可以是以px为单位的数值</li>
<li>line-heigh属性也可以是没有单位的数值，表示字号的倍数 ，这是最推荐的写法</li>
<li>line-heigh属性也可以是百分数，表示字号的倍数</li>
</ul><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>line-height: 1;</span></div></div><div><div><div>2</div></div><div><span>line-height: 1px;</span></div></div><div><div><div>3</div></div><div><span>line-height: 50%;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>text-align属性</strong></p><ul>
<li>
<p><code>text-align</code> 用来设置<strong>行内内容在水平方向上的对齐方式</strong>。文字在盒子居中的样式：设置行高=盒子高度，即可实现单行文本垂直居中；设置text-align: center，即可实现文本水平居中</p>

<table><thead><tr><th>值</th><th>含义</th></tr></thead><tbody><tr><td><code>left</code></td><td>左对齐</td></tr><tr><td><code>center</code></td><td>居中对齐</td></tr><tr><td><code>right</code></td><td>右对齐</td></tr><tr><td><code>justify</code></td><td>两端对齐</td></tr><tr><td><code>start</code></td><td>按书写方向的起始侧对齐</td></tr><tr><td><code>end</code></td><td>按书写方向的结束侧对齐</td></tr></tbody></table>
</li>
</ul><p><strong>text-shadow属性</strong></p><ul>
<li>
<p><code>text-shadow</code> 用来给<strong>文字添加阴影</strong>。</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span> </span><span>/* text-shadow: 水平偏移 垂直偏移 模糊半径 阴影颜色; */</span></div></div><div><div><div>2</div></div><div><span>p</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>text-shadow: </span><span><span>2</span><span>px</span></span><span> </span><span><span>2</span><span>px</span></span><span> </span><span><span>4</span><span>px</span></span><span> </span><span>#</span><span>999</span><span>;</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul></section>
<section><h1>常用字体属性<a href="#常用字体属性"><span>#</span></a></h1><p><strong>font-style属性</strong></p><ul>
<li>
<p>font-style属性设置字体的倾斜</p>

<table><thead><tr><th>值</th><th>含义</th></tr></thead><tbody><tr><td><code>normal</code></td><td>正常字体，不倾斜</td></tr><tr><td><code>italic</code></td><td>使用字体自带的斜体样式；<strong>优先使用这个字体专门设计好的“斜体字形”</strong></td></tr><tr><td><code>oblique</code></td><td>把正常字体倾斜显示；把正常字体直接倾斜。</td></tr></tbody></table>
</li>
</ul><p><strong>font-size属性</strong></p><ul>
<li>font-size属性用来设置字号，单位通常为px。还有em、rem单位。</li>
<li>网页文字正文字号通常是16px，浏览器最小支持10px字号</li>
</ul><p><strong>font-weight属性</strong></p><ul>
<li>
<p>font-weight属性设置字体的粗细程度，通常就用normal和 bold两个值</p>

<table><thead><tr><th>值</th><th>含义</th><th>常见对应</th></tr></thead><tbody><tr><td><code>normal</code></td><td>正常粗细</td><td><code>400</code></td></tr><tr><td><code>bold</code></td><td>粗体</td><td><code>700</code></td></tr><tr><td><code>100</code></td><td>很细</td><td>Thin</td></tr><tr><td><code>200</code></td><td>较细</td><td>Extra Light</td></tr><tr><td><code>300</code></td><td>细</td><td>Light</td></tr><tr><td><code>400</code></td><td>正常</td><td>Normal</td></tr><tr><td><code>500</code></td><td>中等</td><td>Medium</td></tr><tr><td><code>600</code></td><td>半粗</td><td>Semi Bold</td></tr><tr><td><code>700</code></td><td>粗体</td><td>Bold</td></tr><tr><td><code>800</code></td><td>很粗</td><td>Extra Bold</td></tr><tr><td><code>900</code></td><td>最粗</td><td>Black</td></tr></tbody></table>
</li>
</ul><p><strong>font-family属性</strong></p><ul>
<li>
<p>font-family属性用于设置字体</p>
</li>
<li>
<p>字体可以是列表形式，一般英语字体放到前面，后面的字体 是前面的字体的“后备”字体（字体名称中有空格，必须用引号包裹）</p>
</li>
<li>
<p>中文字体也可以称呼它们的英语名字</p>
</li>
<li>
<p>字体通常必须是用户计算机中已经安装好的字体，所以一般 来说设置为微软雅黑和宋体较多，设置成其他字体较少</p>
</li>
<li>
<p>如何设置为用户电脑中没有的字体呢？那就必须自己定义新 字体，这就需要我们有字体文件，用户加载网页的时候，会 同时下载这些字体文件</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>font-family: "微软雅黑";</span></div></div><div><div><div>2</div></div><div><span>font-family: serif, "Times New Roman", "微软雅黑";</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>定义字体：字体文件根据操作系统和浏览器不同，有eot、woff2、 woff、ttf、svg文件格式，需要同时有这5种文件；当我们拥有字体文件之后，就可以用@font-face定义字体</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@font-face</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>font-family: </span><span>'字体名称'</span><span>;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>font-display: </span><span>swap</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>src: </span><span>url</span><span>(</span><span>'eot字体文件地址'</span><span>);</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>src: </span><span>url</span><span>(</span><span>'eot字体文件地址'</span><span>) </span><span>format</span><span>(</span><span>'embedded-opentype'</span><span>),</span></div></div><div><div><div>6</div></div><div><span>  </span><span>url</span><span>(</span><span>'woff2字体文件地址'</span><span>) </span><span>format</span><span>(</span><span>'woff2'</span><span>),</span></div></div><div><div><div>7</div></div><div><span>  </span><span>url</span><span>(</span><span>'woff字体文件地址'</span><span>) </span><span>format</span><span>(</span><span>'woff'</span><span>),</span></div></div><div><div><div>8</div></div><div><span>  </span><span>url</span><span>(</span><span>'ttf字体文件地址'</span><span>) </span><span>format</span><span>(</span><span>'truetype'</span><span>),</span></div></div><div><div><div>9</div></div><div><span>  </span><span>url</span><span>(</span><span>'svg字体文件地址'</span><span>) </span><span>format</span><span>(</span><span>'svg'</span><span>);</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p><strong>阿里巴巴普惠体</strong>：阿里巴巴提供了一套免费商用授权的普惠字体，网址 <a href="https://www.iconfont.cn/webfont" target="_blank">https://www.iconfont.cn/webfont</a> ；使用阿里巴巴普惠字体也省去了下载字体的麻烦</p>
</li>
</ul><p><strong>font合写属性</strong></p><ul>
<li>
<p>font属性可以用来作为font-style, font-weight, font-size, line-height和font-family属性的合写</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>font: italic bold 20px/1.5 Arial,"微软雅黑";</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ul><p><strong>font-variant 属性</strong></p><ul>
<li>
<p><code>font-variant</code> 用来设置<strong>字体的变体形式</strong>。</p>

<table><thead><tr><th>属性</th><th>效果</th></tr></thead><tbody><tr><td><code>font-variant: small-caps</code></td><td>小写字母显示为较小的大写字形</td></tr><tr><td><code>text-transform: uppercase</code></td><td>所有字母直接转换成普通大写</td></tr></tbody></table>
</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026100601css3-ji-chu-he-xuan-ze-qi/</id>
      <title type="text">CSS3基础和选择器</title>
      <published>2026-10-06T00:00:00.000Z</published>
      <updated>2026-10-06T00:00:00.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026100601css3-ji-chu-he-xuan-ze-qi/"/>
      <summary type="text">学习CSS3的基础概念和选择器内容</summary>
      <content type="html"><![CDATA[<section><h1>前言<a href="#前言"><span>#</span></a></h1><p>CSS3是前端简单又不简单的知识内容，简单的是语法，不简单的是其选择器，属性和属性值非常多，学好CSS3是网页布局中尤为关键的一步，页面美观，有没有样式冲突Bug，都看CSS3的基础知识是否牢固；</p><p>CSS3可以分为以下几个阶段：基础概念、选择器、文本属性、盒模型、浮动、定位、边框、圆角、背景渐变、2D与3D转换，过渡与动画，当然还有后续的Flex + Grid + 响应式+单位与尺寸，这些在移动Web端讲解。</p><p>学习CSS3不应该背属性和属性值，应该先学结构-&gt;再学布局-&gt;再学视觉-&gt;最后学增强效果，现在学习的就是知识内容，先把基础该学的学完，在深入研究自学，完全不看视频，编写样式，提升更快</p></section>
<section><h1>学习目标<a href="#学习目标"><span>#</span></a></h1><p>本文只学习CSS3的基础概念和选择器部分，熟练掌握选择器有哪些，选择器在日常开发中一般不会用到很复杂，但是至少遇到要看得懂</p></section>
<section><h1>CSS3基础概念<a href="#css3基础概念"><span>#</span></a></h1><p><strong>简介</strong>：CSS（cascading style sheet，层叠式样式表）是用来给 HTML标签添加样式的语言；CSS3是CSS的最新版本，增加了大量的样式、动画、3D特 效和移动端特性等</p><p><strong>CSS使样式和结构分离</strong>：CSS使样式和结构分离，样式和结构不用“杂糅着写”，而 是彼此分开：HTML就负责结构，CSS负责样式；HTML和CSS怎么结合呢？“选择器”就是两者的纽带</p><p><strong>CSS的本质</strong>：CSS就是样式的“清单”，要书写合适的选择器，然后把指 定元素的样式“一条一条罗列”出来；CSS没有加减乘除、与或非、循环、选择、判断，CSS不是 “编程” ，就是简单直接的罗列样式；背诵CSS属性是非常重要的，属性背诵熟练程度决定了做网 页的速度</p><p><strong>CSS的书写位置</strong>：<strong>内嵌式</strong>、<strong>外链式</strong>、<strong>导入式</strong></p><p><strong>基本语法：</strong> 选择器，大括号，KV值；最后一条样式可以不书写分号；可以没有换行</p></section>
<section><h1>标签选择器<a href="#标签选择器"><span>#</span></a></h1><ul>
<li>标签选择器也称元素选择器、类型选择器，它直接使用元素 的标签名当做选择器，将选择页面上所有该种标签</li>
<li>标签选择器将选择页面上所有该种标签，无论这个标签所处 位置的深浅</li>
<li>标签选择器“覆盖面”非常大，所以通常用于标签的初始化</li>
</ul><p>示例：</p><div><figure><figcaption><span>index.html</span></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>    </span><span>h1</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>        </span></span><span>color: </span><span>red</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span>&lt;</span><span>h1</span><span>&gt;我是h1&lt;/</span><span>h1</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span>&lt;</span><span>div</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>&lt;</span><span>h1</span><span>&gt;我是div下的h1&lt;/</span><span>h1</span><span>&gt;</span></div></div><div><div><div>9</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>页面上所有的h1标签字体都会变成红色，所以说“覆盖面”非常大，为什么说初始化呢，因为如果写<code>div h1</code> 这样的选择器，字体就可以自定义颜色，而不是红色，新定义的覆盖之前的</p></section>
<section><h1>id选择器<a href="#id选择器"><span>#</span></a></h1><ul>
<li>标签可以有id属性，是这个标签的唯一标识，同一个页面上不能有相同id的标签</li>
<li>id的名称只能由字母、数字、下划线、短横构成，且不能以 数字开头，字母区分大小写，但习惯上一般为小写字母</li>
<li>CSS选择器可以使用井号#前缀，选择指定id的标签</li>
</ul><p>示例：</p><div><figure><figcaption><span>index.html</span></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>    </span><span>#_para1</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>        </span></span><span>color: </span><span>red</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span>&lt;</span><span>h1</span><span> </span><span>id</span><span>=</span><span>'_para1'</span><span>&gt;我是h1&lt;/</span><span>h1</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span>&lt;</span><span>div</span><span>&gt;</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>&lt;</span><span>h1</span><span>&gt;我是div下的h1&lt;/</span><span>h1</span><span>&gt;</span></div></div><div><div><div>10</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>页面上的“我是h1”就会变成红色字体，关于id选择器有以下几点记住：唯一性，选择器使用井号#前缀和id的名称组成，不能数字开头</p></section>
<section><h1>class选择器<a href="#class选择器"><span>#</span></a></h1><ul>
<li>class属性表示“类名”</li>
<li>类名的命名规范和id的命名规范相同</li>
<li>使用点.前缀选择指定class的标签</li>
<li>多个标签可以使用相同类名 [多（标签）对一（类名）]</li>
<li>同一个标签可以使用属于多个类，类名用空格隔开 [一（标签）对多（类名）]</li>
</ul><p>示例：</p><div><figure><figcaption><span>index.html</span></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>style</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>    </span><span>.para1</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>        </span></span><span>color: </span><span>red</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>    </span><span>.para2</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>        </span></span><span>background-color: </span><span>burlywood</span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>8</div></div><div><span>&lt;/</span><span>style</span><span>&gt;</span></div></div><div><div><div>9</div></div><div><span>&lt;</span><span>h1</span><span> </span><span>class</span><span>=</span><span>'para1 para2'</span><span>&gt;我是h1&lt;/</span><span>h1</span><span>&gt;</span></div></div><div><div><div>10</div></div><div><span>&lt;</span><span>div</span><span>&gt;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>&lt;</span><span>h1</span><span> </span><span>class</span><span>=</span><span>'para1'</span><span>&gt;我是div下的h1&lt;/</span><span>h1</span><span>&gt;</span></div></div><div><div><div>12</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>页面字体都是红色，但是只有“我是h1”有背景颜色，这就是class的应用</p></section>
<section><h1>复合选择器<a href="#复合选择器"><span>#</span></a></h1><p>复合选择器可以分为以下三种：</p>

<table><thead><tr><th>选择器名称</th><th>示例</th><th>示例的意义</th><th>说明</th></tr></thead><tbody><tr><td>后代选择器</td><td>.box .spec</td><td>选择类名为box的标签内部的类 名为spec的标签</td><td>特点就是空格</td></tr><tr><td>交集选择器</td><td>li.spec</td><td>选择既是li标签，也属于spec 类的标签</td><td>特点就是没有空格逗号，全部写在一起</td></tr><tr><td>并集选择器</td><td>ul, ol</td><td>选择所有ul和ol标签</td><td>特点就是逗号</td></tr></tbody></table><p>想理解这三个其实有点困难，每个字都能看到理解，但是看到还是想一下，特别是后代和交集，区别就是一个空格。接下来用示例巩固这三个选择器</p><p>第一题：哪些 <code>&lt;p&gt;</code> 会变成红色？</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"box"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>p</span><span>&gt;第一段&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>section</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;第二段&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>&lt;/</span><span>section</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span>&lt;</span><span>p</span><span>&gt;第三段&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>.box p {</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>color: red;</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
查看答案与解析<p>答案：<strong>第一段和第二段</strong></p><ul>
<li>box p 表示选择 .box 内部所有层级的 p，所以第一段和第二段都会匹配。</li>
</ul><p>第二题：下面哪个 CSS 表示“选择 <code>.article</code> 里面的所有 <code>&lt;strong&gt;</code> 元素”？</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>A. .article, strong</span></div></div><div><div><div>2</div></div><div><span>B. .article strong</span></div></div><div><div><div>3</div></div><div><span>C. .articlestrong</span></div></div><div><div><div>4</div></div><div><span>D. .article.strong</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
查看答案与解析<p>答案：<strong>B</strong></p><ul>
<li>两个选择器之间的空格表示后代关系，因此会选择 .article 内部任意层级的 strong。</li>
</ul><p>第三题：结果是什么？</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>ul</span><span> </span><span>class</span><span>=</span><span>"menu"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>li</span><span>&gt;&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"#"</span><span>&gt;首页&lt;/</span><span>a</span><span>&gt;&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>li</span><span>&gt;&lt;</span><span>span</span><span>&gt;&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"#"</span><span>&gt;关于&lt;/</span><span>a</span><span>&gt;&lt;/</span><span>span</span><span>&gt;&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>&lt;/</span><span>ul</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>.menu a {</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>color: blue;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
查看答案与解析<p>答案：<strong>两个 a 都变蓝</strong></p><ul>
<li>两个 a 无论嵌套一层还是多层，都位于 .menu 内部，因此都会匹配 .menu a。</li>
</ul><p>第四题：哪个元素会变红？</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"active"</span><span>&gt;A&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"active"</span><span>&gt;B&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;</span><span>p</span><span>&gt;C&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>p.active {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>color: red;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
查看答案与解析<p>答案：<strong>只有 A</strong></p><ul>
<li>p.active 要求同一个元素既是 p，又具有 active 类，因此只有 A 符合。</li>
</ul><p>第五题：下面哪个选择器表示“选择同时拥有 <code>btn</code> 和 <code>primary</code> 两个 class 的元素”？</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>A. .btn .primary</span></div></div><div><div><div>2</div></div><div><span>B. .btn + .primary</span></div></div><div><div><div>3</div></div><div><span>C. .btn, .primary</span></div></div><div><div><div>4</div></div><div><span>D. .btn.primary</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
查看答案与解析<p>答案：<strong>D</strong></p><ul>
<li>两个类选择器连续书写且没有空格，表示同一个元素同时拥有 btn 和 primary 两个类。</li>
</ul><p>第六题：哪个元素会被选中？</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>h2</span><span> </span><span>class</span><span>=</span><span>"title big"</span><span>&gt;标题1&lt;/</span><span>h2</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>h2</span><span> </span><span>class</span><span>=</span><span>"title"</span><span>&gt;标题2&lt;/</span><span>h2</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;</span><span>p</span><span> </span><span>class</span><span>=</span><span>"title big"</span><span>&gt;标题3&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>h2.title.big {</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>color: red;</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
查看答案与解析<p>答案：<strong>只有标题1</strong></p><ul>
<li>标题1同时满足三个条件：标签是 h2，并且具有 title 和 big 两个类。</li>
</ul><p>第七题：这段代码表示什么？</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>h1</span><span><span>,</span><span> </span></span><span>h2</span><span><span>,</span><span> </span></span><span>p</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>color: </span><span>red</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
查看答案与解析<p>答案：<strong>同时选择所有 h1、所有 h2 和所有 p</strong></p><ul>
<li>逗号用于组合多个独立选择器，相当于给它们应用同一组 CSS 样式。</li>
</ul><p>第八题：如果希望“<code>.title</code> 和 <code>.content</code> 两类元素的文字都变成黑色”，应该怎么写？</p>
查看答案与解析<p>答案：<strong>.title, .content { color: black; }</strong></p><ul>
<li>逗号把两个独立选择器组合起来，因此 .title 和 .content 都会应用相同样式。</li>
</ul><p>第九题：下面三个选择器含义完全不同：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box</span><span> </span><span>p</span></div></div><div><div><div>2</div></div><div><span>.box.p</span></div></div><div><div><div>3</div></div><div><span>.box</span><span><span>,</span><span> </span></span><span>p</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>哪组选项对应正确？</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>A. 后代选择器、并集选择器、交集选择器</span></div></div><div><div><div>2</div></div><div><span>B. 交集选择器、后代选择器、并集选择器</span></div></div><div><div><div>3</div></div><div><span>C. 后代选择器、交集选择器、并集选择器</span></div></div><div><div><div>4</div></div><div><span>D. 并集选择器、交集选择器、后代选择器</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
查看答案与解析<p>答案：<strong>C</strong></p><ul>
<li>.box p 中的空格表示后代；.box.p 连续书写表示同一元素同时具有两个类；.box, p 中的逗号表示并集。</li>
</ul><p>最值得死记的其实就这一行：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.box p      /* 空格：后代 */</span></div></div><div><div><div>2</div></div><div><span>.box.active /* 紧挨：交集 */</span></div></div><div><div><div>3</div></div><div><span>.box, p     /* 逗号：并集 */</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这三个能一眼区分，后面大部分复合选择器就不会再搅成一锅 CSS 粥了。</p></section>
<section><h1>伪类<a href="#伪类"><span>#</span></a></h1><p>CSS的伪类目前有60多个，而且随着 CSS 标准继续发展，还会新增，所以不能死记硬背，但是也不能只记住hover、active、link 、visited 或者first-child等这些，应该拓宽思路；其中<strong>序号选择器也属于伪类</strong>的一种</p><p>伪类是选择器后加单个冒号，看到伪类，应该有这样的一个问题：<strong>它在描述元素的什么状态或条件</strong> ，伪类几乎所有标签能用，但不是所有，要想一下：<strong>这个元素有没有这个状态？</strong> 比如div这个标签，没有focus这个状态，设置了也没用，以下是常用的伪类</p>

<table><thead><tr><th>伪类</th><th>作用</th></tr></thead><tbody><tr><td><code>:hover</code></td><td>鼠标悬停</td></tr><tr><td><code>:active</code></td><td>鼠标按下</td></tr><tr><td><code>:focus</code></td><td>获得焦点</td></tr><tr><td><code>:first-child</code></td><td>第一个子元素</td></tr><tr><td><code>:last-child</code></td><td>最后一个子元素</td></tr><tr><td><code>:nth-child()</code></td><td>第 N 个子元素</td></tr><tr><td><code>:checked</code></td><td>被选中的表单元素</td></tr><tr><td><code>:disabled</code></td><td>被禁用</td></tr><tr><td><code>:not()</code></td><td>排除元素</td></tr><tr><td><code>:has()</code></td><td>根据内部元素匹配</td></tr></tbody></table><p>伪类：序号选择器：</p>

<table><thead><tr><th>举例</th><th>意义</th></tr></thead><tbody><tr><td><code>:first-child</code></td><td>第一个子元素</td></tr><tr><td><code>:last-child</code></td><td>最后一个子元素</td></tr><tr><td><code>:nth-child(3)</code></td><td>第3个子元素</td></tr><tr><td><code>:nth-last-child(3)</code></td><td>倒数第3个子元素</td></tr><tr><td><code>:nth-of-type(3)</code></td><td>第3个某类型子元素</td></tr><tr><td><code>:nth-last-of-type(3)</code></td><td>倒数第3个某类型子元素</td></tr></tbody></table></section>
<section><h1>元素关系选择器<a href="#元素关系选择器"><span>#</span></a></h1><p>字如其意，其实就是标签与标签之前的关系</p>

<table><thead><tr><th>名称</th><th>举例</th><th>意义</th></tr></thead><tbody><tr><td>子选择器</td><td>div&gt;p</td><td><strong>嵌套包含关系</strong>，只嵌套的第一层只要是div下的子标签p都选中，</td></tr><tr><td>相邻<strong>兄弟</strong>选择器</td><td>img+p</td><td><strong>平级关系</strong>，图片后面<strong>紧跟着</strong>的段落将被选中，但凡中间隔了几个标签都不会选中</td></tr><tr><td>通用兄弟选择器</td><td>p~span</td><td><strong>平级关系</strong>，p元素之后的<strong>所有同层级</strong>span元素 <strong>p不会被选中</strong></td></tr></tbody></table><p><strong>子选择器</strong></p><ul>
<li>当使用 &gt; 符号分隔两个元素时，它只会匹配那些作为第一 个元素的直接子元素，即两个标签为父子关系</li>
<li>子选择器从IE7开始兼容</li>
</ul><p><strong>相邻兄弟选择器</strong></p><ul>
<li>写法：<code>+</code> 写在两个选择器之间。</li>
<li>两个元素必须是兄弟元素，也就是拥有同一个父元素，平级的关系。</li>
<li><code>+</code>后面的元素被选中</li>
<li>相邻兄弟选择器从IE7开始兼容</li>
</ul><p><strong>通用兄弟选择器</strong></p><ul>
<li>通用兄弟选择器（），ab 选择a元素之后所有同层级b元素</li>
<li>通用兄弟选择器从IE7开始兼容</li>
</ul></section>
<section><h1>属性选择器<a href="#属性选择器"><span>#</span></a></h1><p>核心就 <strong>7 种常用写法</strong>，这里的<code>attr</code>是一个代词，不是什么属性，是代表某某属性</p>

<table><thead><tr><th>写法</th><th>含义</th><th>示例</th></tr></thead><tbody><tr><td><code>[attr]</code></td><td>有这个属性就选中</td><td><code>[disabled]</code></td></tr><tr><td><code>[attr="value"]</code></td><td>属性值完全等于某值</td><td><code>[type="text"]</code></td></tr><tr><td><code>[attr~="value"]</code></td><td>属性值是空格分隔的一组词，其中包含某个完整词</td><td><code>[class~="active"]</code></td></tr><tr><td>`[attr</td><td>=“value”]`</td><td>等于某值，或者以 <code>value-</code> 开头</td></tr><tr><td><code>[attr^="value"]</code></td><td>属性值以某内容开头</td><td><code>[href^="https"]</code></td></tr><tr><td><code>[attr$="value"]</code></td><td>属性值以某内容结尾</td><td><code>[href$=".pdf"]</code></td></tr><tr><td><code>[attr*="value"]</code></td><td>属性值中包含某段内容</td><td><code>[href*="google"]</code></td></tr></tbody></table></section>
<section><h1>伪元素<a href="#伪元素"><span>#</span></a></h1><p>它们并没有真的往 HTML 里面添加两个标签，而是 CSS 创建出来的“虚拟元素”；最常见的是这些：</p>

<table><thead><tr><th>伪元素</th><th>作用</th></tr></thead><tbody><tr><td><code>::before</code></td><td>在元素内容前插入“虚拟内容”</td></tr><tr><td><code>::after</code></td><td>在元素内容后插入“虚拟内容”</td></tr><tr><td><code>::first-letter</code></td><td>选中第一个字母/字符</td></tr><tr><td><code>::first-line</code></td><td>选中第一行文字</td></tr><tr><td><code>::selection</code></td><td>选中文字时的样式</td></tr><tr><td><code>::placeholder</code></td><td>输入框占位文字</td></tr><tr><td><code>::marker</code></td><td>列表前面的项目符号/编号</td></tr><tr><td><code>::file-selector-button</code></td><td>文件上传按钮</td></tr><tr><td><code>::backdrop</code></td><td>全屏、<code>dialog</code> 后面的遮罩层</td></tr></tbody></table></section>
<section><h1>层叠性和选择器权重计算<a href="#层叠性和选择器权重计算"><span>#</span></a></h1><p><strong>层叠性</strong></p><ul>
<li>CSS全名叫做“层叠式样式表” ，层叠性是它很重要的性质</li>
<li>层叠性：多个选择器可以同时作用于同一个标签，效果叠加</li>
</ul><p><strong>层叠性的冲突处理</strong></p><ul>
<li>如果多个选择器定义的属性有冲突呢？CSS有严密的处理冲 突的规则</li>
<li>id权重 &gt; class权重 &gt; 标签权重</li>
</ul><p><strong>复杂选择器权重计算</strong></p><ul>
<li>复杂选择器可以通过（id的个数, class的个数, 标签的个 数）的形式，计算权重</li>
</ul><p><strong>!important提升权重</strong></p><ul>
<li>如果我们需要将某个选择器的某条属性提升权重，可以在属 性后面写!important</li>
<li>很多公司不允许使用!important，因为这会带来不经意的 样式冲突</li>
</ul></section>
<section><h1>拓展选择器练习题<a href="#拓展选择器练习题"><span>#</span></a></h1><p>可以ChatGptt提问：给我5道关于CSS3选择器的综合练习题，这5道要有特点，能答对基本就对CSS3的选择器有很大的掌握</p></section>
<section><h1>拓展选择器速记<a href="#拓展选择器速记"><span>#</span></a></h1>

<table><thead><tr><th>选择器类型</th><th>写法</th><th>说明</th></tr></thead><tbody><tr><td>ID选择器</td><td>#id</td><td>使用#</td></tr><tr><td>类选择器</td><td>.class</td><td>使用.</td></tr><tr><td>后代</td><td>div .cla</td><td>空格，无论藏多深，只要是这个标签内部的</td></tr><tr><td>交集选择器</td><td>div.cla</td><td>没有空格，连着写，就是有一个标签同时全部满足的才选中</td></tr><tr><td>并集选择器</td><td>ul，li，ol</td><td>逗号隔开的，就是不管层级，只要是写到的，都是选中</td></tr><tr><td>子选择器</td><td>div&gt;p</td><td><strong>嵌套包含关系</strong>，选中多个，只嵌套的<strong>第一层</strong>只要是div下的子标签p<strong>都选中</strong>，就是只要是子元素的，<strong>不管中间隔了多少个元素</strong></td></tr><tr><td>相邻<strong>兄弟</strong>选择器</td><td>img+p</td><td><strong>平级关系</strong>，选中一个，图片后面<strong>紧跟着</strong>的段落将被选中，<strong>但凡中间隔了几个标签都不会选中</strong></td></tr><tr><td>通用兄弟选择器</td><td>p~span</td><td><strong>平级关系</strong>，选中多个，p元素之后的<strong>所有同层级</strong>span元素 <strong>p不会被选中</strong></td></tr></tbody></table></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/2026100501-qian-duan-ji-chu-html5/</id>
      <title type="text">前端基础知识HTML5</title>
      <published>2026-10-05T00:00:00.000Z</published>
      <updated>2026-10-05T00:00:00.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/2026100501-qian-duan-ji-chu-html5/"/>
      <summary type="text">学习前端基础语言HTML5</summary>
      <content type="html"><![CDATA[<section><h1>前言<a href="#前言"><span>#</span></a></h1><p>学习HTML5，大概可以分为以下几个阶段：基础概念、标签，标签属性</p></section>
<section><h1>学习目标<a href="#学习目标"><span>#</span></a></h1><p>本文最终学习HTML5的基础知识并且最终完成一个小慕医生的首页静态页面结构。</p></section>
<section><h1>基础概念<a href="#基础概念"><span>#</span></a></h1><p>HTML5是一种超文本标记语言，主要是网页的骨架，并没有样式和动效功能，HTML5是HTML的第5个版本，关于之前的版本，不再赘述，已经属于上古时期的知识；关于HTML5，其实这个版本的也是很久就已经发布的，但是现在用的HTML5和最开始定义的HTML5已经有非常多的更新，相当于这个5不再是版本，而是HTML的一部分，原因就是前端发展太快，等到标准定义出来，再去实现，已经慢了一大截了</p></section>
<section><h1>基础标签<a href="#基础标签"><span>#</span></a></h1><section><h2>骨架标签<a href="#骨架标签"><span>#</span></a></h2><div><figure><figcaption><span>index.html</span></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!</span><span>doctype</span><span> </span><span>html</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>html</span><span> </span><span>lang</span><span>=</span><span>"en"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>head</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>meta</span><span> </span><span>charset</span><span>=</span><span>"UTF-8"</span><span> /&gt;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>&lt;</span><span>meta</span><span> </span><span>name</span><span>=</span><span>"viewport"</span><span> </span><span>content</span><span>=</span><span>"width=device-width, initial-scale=1.0"</span><span> /&gt;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>&lt;</span><span>title</span><span>&gt;Document&lt;/</span><span>title</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>&lt;/</span><span>head</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>&lt;</span><span>body</span><span>&gt;&lt;/</span><span>body</span><span>&gt;</span></div></div><div><div><div>9</div></div><div><span>&lt;/</span><span>html</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这是一个非常常规的html5骨架，其中：</p><ul>
<li><code>&lt;!DOCTYPE html&gt;</code>是文档类型声明DTD，HTML文件第一行必须是DTD（Document Type Definition ，文档类型声明）</li>
<li><code>lang</code> 表示页面主要使用的语言。主要影响的是：搜索引擎理解页面语言，SEO、浏览器翻译等</li>
<li>meta是网页元信息，也就是来描述网页相关的内容，charset是描述网页字符集，一般写UTF-8就可以了，还有name为viewport的，viewport 可以简单理解成：浏览器用多大的虚拟区域来显示网页。width=device-width是网页宽度使用设备屏幕宽度。initial-scale=1.0是页面首次打开时，缩放比例为 100%。关于这点，只要理解跟响应式有关就可以，后续的web侧响应式再展开说</li>
<li>title标签用来设置网页的标题，文字会显示在浏览器的标签栏上</li>
<li><code>&lt;html&gt;&lt;/html&gt;</code>、<code>&lt;head&gt;&lt;/head&gt;</code> 、<code>&lt;body&gt;&lt;/body&gt;</code> 是标签对，head内的主要都是网页的配置项</li>
</ul></section><section><h2>标题和段落标签<a href="#标题和段落标签"><span>#</span></a></h2><p>标题标签有6个，从大到小：h1&gt;h2&gt;h3&gt;h4&gt;h5&gt;h6，标题标签对SEO有影响，特别是H1对SEO权重最大，<strong>通常会把logo放在H1标签中</strong></p><p>段落标签是p，字如其意，就是表达网页段落的意思，但是这个段落并不会前面空两格的段落，需要注意的是，<strong>标题和段落不能互相嵌套</strong>，非要这么写，是非常严重的语法错误，虽然在浏览器也能看到正常显示，但那是浏览器自动重新编排了，打开F12查看元素就能查看到</p></section><section><h2>拓展：H5的一些特性<a href="#拓展h5的一些特性"><span>#</span></a></h2><p>HTML5存在<strong>空白折叠现象</strong>：文字和文字之间的多个空格、<strong>换行会被折叠成一个空格</strong>，标签“内壁”和文字之间的空格会被忽略；<strong>转义字符：</strong> 如果想在网页显示标签对，直接写肯定是不行的，这时候需要用到转义字符</p><p>常见转义字符（字符实体）：</p>

<table><thead><tr><th>转义字符</th><th>意义</th></tr></thead><tbody><tr><td><code>&lt;</code></td><td>小于号</td></tr><tr><td><code>&gt;</code></td><td>大于号</td></tr><tr><td><code>&amp;nbsp;</code></td><td>空格（不会被折叠）</td></tr><tr><td><code>©</code></td><td>版权符号©</td></tr></tbody></table></section></section>
<section><h1>列表标签<a href="#列表标签"><span>#</span></a></h1><p>列表标签可以分三种：无序列表、有序列表和定义列表</p><p>无序列表：无序列表是“没有刻意顺序”的列表；使用 <code>ul</code>标签，每个列表项都是<code>li</code>标签；<strong>ul的子标签只能是li，li里面可以放任何东西</strong></p><p>有序列表：有序列表是“有刻意顺序”的列表；使用 <code>ol</code>标签，每个列表项都是<code>li</code>标签；<code>ol</code>标签有一个<strong>start</strong>属性：start属性值必须是一个整数，指定了列表编号的起始值：记住<strong>start是写在ol的，是ol的属性，start表示从哪个开始数字开始排序，type表示编号样式，value表示 某一个 li 强制指定编号</strong></p><div><figure><figcaption><span>index.html</span></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>ol</span><span> </span><span>start</span><span>=</span><span>"3"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>&lt;</span><span>li</span><span>&gt;我是有序列表1&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>&lt;</span><span>li</span><span>&gt;我是有序列表2&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>li</span><span> </span><span>value</span><span>=</span><span>"5"</span><span>&gt;我是有序列表3&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>&lt;</span><span>li</span><span>&gt;我是有序列表4&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span>&lt;/</span><span>ol</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span>&lt;!-- 只能值A --&gt;</span></div></div><div><div><div>8</div></div><div><span>&lt;</span><span>ol</span><span> </span><span>type</span><span>=</span><span>"A"</span><span>&gt;</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>&lt;</span><span>li</span><span>&gt;我是有序列表1&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>&lt;</span><span>li</span><span>&gt;我是有序列表2&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>&lt;</span><span>li</span><span>&gt;我是有序列表3&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>&lt;</span><span>li</span><span>&gt;我是有序列表4&lt;/</span><span>li</span><span>&gt;</span></div></div><div><div><div>13</div></div><div><span>&lt;/</span><span>ol</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>效果：</p><ol>
      <li>我是有序列表1</li>
      <li>我是有序列表2</li>
     <li>我是有序列表3</li>
      <li>我是有序列表4</li>
    </ol>   <ol>
      <li>我是有序列表1</li>
      <li>我是有序列表2</li>
      <li>我是有序列表3</li>
      <li>我是有序列表4</li>
    </ol><p>还有一个属性<strong>reversed</strong>，也<strong>是ol的属性</strong>，reversed属性指定列表中的条目是否是倒序排列的，reversed属性不需要值，只需要写reversed单词即可</p><p>定义列表：<code>dl</code>、<code>dt</code>、<code>dd</code>，都是定义列表的标签，字如其意，就是定义一个<strong>列</strong>表，定义的一列的数据，dl表示一列，dt表示列的头部，dd表示列的内容项，dt和dd是平级的，从效果可以看出来，定义列表是有默认样式的，dt是头部，相当于标题，加粗，dd是项，空格两行</p><div><figure><figcaption><span>index.html</span></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>dl</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>&lt;</span><span>dt</span><span>&gt;北京&lt;/</span><span>dt</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>&lt;</span><span>dd</span><span>&gt;我国首都、政治中心、文化中心&lt;/</span><span>dd</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;</span><span>dt</span><span>&gt;上海&lt;/</span><span>dt</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>&lt;</span><span>dd</span><span>&gt;国际经济、金融、科技创新中心&lt;/</span><span>dd</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>&lt;</span><span>dt</span><span>&gt;深圳&lt;/</span><span>dt</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>&lt;</span><span>dd</span><span>&gt;经济特区，国际化都市&lt;/</span><span>dd</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span>&lt;/</span><span>dl</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>效果：</p><dl>
    <dt>北京</dt>
    <dd>我国首都、政治中心、文化中心</dd>
    <dt>上海</dt>
    <dd>国际经济、金融、科技创新中心</dd>
    <dt>深圳</dt>
    <dd>经济特区，国际化都市</dd>
</dl><div><div><div></div><div>Tip</div></div><div><p>使用什么标签，不应该看样式，应该看语义，只要语义上有“解释说明”含义的文字，且为列表形态，应该使用定义列表</p></div></div></section>
<section><h1>多媒体标签<a href="#多媒体标签"><span>#</span></a></h1><p>多媒体标签主要有三个img、video和audio，一个是插入图片，一个是插入视频和插入音频</p><p>img标签：有一个<strong>src属性</strong>，表示图片的地址；<strong>alt属性</strong>，表示文件加载失败的时候显示的文字；还有<strong>width、height属性</strong>，表示宽高，如果只设置一个，就等比例缩放，以下是src<strong>支持的图片格式</strong>：</p>

<table><thead><tr><th>格式</th><th>说明</th></tr></thead><tbody><tr><td>.bmp</td><td>windows画图软件默认保存的格式，位图</td></tr><tr><td>.gif</td><td>支持动画（比如表情包）</td></tr><tr><td>.jpeg(.jpg)</td><td>有损压缩图片，用于照片</td></tr><tr><td>.png</td><td>便携式网络图像，用于logo、背景图形等，支持 透明和半透明</td></tr><tr><td>.svg</td><td>矢量图片</td></tr><tr><td>.webp</td><td>最新的压缩算法非常优秀的图片格式</td></tr></tbody></table><p>video和audio属性值基本相同，这里放在一起，区别是一个播放视频一个播放音频，audio 支持mp3和ogg格式，video支持mp4、ogv、webm等格式，通常有以下属性</p>

<table><thead><tr><th>属性</th><th>说明</th></tr></thead><tbody><tr><td>autoplay</td><td>自动播放</td></tr><tr><td>loop</td><td>循环播放</td></tr><tr><td>controls</td><td>显示播放控件</td></tr></tbody></table></section>
<section><h1>超链接标签<a href="#超链接标签"><span>#</span></a></h1><p>a标签是html的超链接的标签，可以跳转到其他网页或者其他地址，href属性可以指定跳转到哪里；</p><p>将标签的target属性设置为blank，即可在新标签页中打开网页；</p><p>除了文字可以加上超链接，图片也可以设置超链接，只需要用a标签包裹img标签即可；</p><p>除此之外还可以在页面内做锚点：较长的页面，可以适当的给h系列标签添加id属性，它将成为 页面的“锚点”，网址后面添加#时，页面将自动滚动到锚点所在位置，其他页面的超级链接，可以链接到指定锚点；</p><p>指向exe、zip、rar等文件格式的链接，将自动成为下载链接；</p><p>有mailto&lt;前缀的链接是邮件链接&gt;，系统将自动打开Email相 关软件；有tel&lt;前缀的链接是电话连接&gt;，系统将自动打开拨号盘</p><div><div><div></div><div>Tip</div></div><div><p>通常target会和rel出现，rel有两个属性值：noopener noreferrer，noopener是 防止新页面控制原页面，noreferrer是不告诉目标网站“我是从哪里跳过来的”</p></div></div></section>
<section><h1>语义化标签<a href="#语义化标签"><span>#</span></a></h1><p>语义化标签最大作用就是SEO，利于搜索引擎的抓取，大致分为大纲标签（大语义）和语义化标签（小语义）</p><p>以下这些都是块级标签，都会换行</p>

<table><thead><tr><th>区块标签</th><th>说明</th></tr></thead><tbody><tr><td><code>&lt;section&gt;</code></td><td>文档的区域，语义比div大</td></tr><tr><td><code>&lt;article&gt;</code></td><td>文档的核心文章内容，会被搜索引擎主要抓取</td></tr><tr><td><code>&lt;aside&gt;</code></td><td>文档的非必要相关内容，比如广告等</td></tr><tr><td><code>&lt;nav&gt;</code></td><td>导航条</td></tr><tr><td><code>&lt;header&gt;</code></td><td>页头</td></tr><tr><td><code>&lt;main&gt;</code></td><td>网页核心部分</td></tr><tr><td><code>&lt;footer&gt;</code></td><td>页脚</td></tr></tbody></table><p>以下的都是行内标签，不会换行</p>

<table><thead><tr><th>标签</th><th>说明</th></tr></thead><tbody><tr><td>span</td><td>是文本中的“区块”标签，本身没有任何特殊 的显示效果，可以结合CSS来丰富样式</td></tr><tr><td>b</td><td>被加粗的文字，CSS已经替代了它的功能</td></tr><tr><td>u</td><td>加下划线的文字，CSS已经替代了它的功能</td></tr><tr><td>i</td><td>倾斜的文字，CSS已经替代了它的功能</td></tr><tr><td>strong</td><td>代表特别重要文字</td></tr><tr><td>em</td><td>代表强调文字</td></tr><tr><td>mark</td><td>代表一段需要被高亮的文字</td></tr></tbody></table><div><figure><figcaption><span>index.html</span></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>span</span><span>&gt;span&lt;/</span><span>span</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>b</span><span>&gt;b&lt;/</span><span>b</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;</span><span>u</span><span>&gt;u&lt;/</span><span>u</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>&lt;</span><span>i</span><span>&gt;i&lt;/</span><span>i</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>&lt;</span><span>strong</span><span>&gt;非常重要&lt;/</span><span>strong</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span>&lt;</span><span>em</span><span>&gt;强调文字&lt;/</span><span>em</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span>&lt;</span><span>mark</span><span>&gt;需要被高亮的文字&lt;/</span><span>mark</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>效果：</p><p><span>span</span>
<b>b</b>
<u>u</u>
<i>i</i>
<strong>非常重要</strong>
<em>强调文字</em>
<mark>需要被高亮的文字</mark></p><p><code>figure</code>和<code>figcaption</code>  是比较特别的：<code>&lt;figure&gt;</code> 表示一块独立的媒体/内容，<code>&lt;figcaption&gt;</code> 表示这块内容的说明文字，figure可以单独存在，<code>figcaption</code>  必须在figure内部，因为<code>figcaption</code>  本身就是对figure的一个描述，通常应该是 <code>&lt;figure&gt;</code> 的<strong>第一个或最后一个子元素</strong></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>figure</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>&lt;</span><span>figcaption</span><span>&gt;我是对内容的描述，这是一张图片&lt;/</span><span>figcaption</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>&lt;</span><span>img</span><span> </span><span>src</span><span>=</span><span>"./小慕医生/images/logo.png"</span><span> </span><span>alt</span><span>=</span><span>"小慕"</span><span> </span><span>width</span><span>=</span><span>"200px"</span><span> /&gt;</span></div></div><div><div><div>4</div></div><div><span>&lt;/</span><span>figure</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>表单标签<a href="#表单标签"><span>#</span></a></h1><p>表单标签无非是from和input，内容比较多和复杂的input的type类型，表单的name一般强烈建议写上去，因为使用原生表单提交时，name时必须要写上的，因为这是提交数据时使用的字段名</p><p>from标签属性：</p>

<table><thead><tr><th>属性</th><th>说明</th></tr></thead><tbody><tr><td>action</td><td>表示表单要提 交到的后台程序的网址</td></tr><tr><td>method</td><td>属性表示表单提交 的方式，有get或post</td></tr></tbody></table><p>input标签属性</p>

<table><thead><tr><th>属性</th><th>说明</th></tr></thead><tbody><tr><td>type</td><td>表示input的类型，什么控件</td></tr><tr><td>value</td><td>表示已经input填写的值</td></tr><tr><td>placeholder</td><td>表示提示文本</td></tr><tr><td>disabled</td><td>用户不能与元素交互，即“锁死”</td></tr><tr><td>name</td><td>确定提交数据时使用的字段名</td></tr></tbody></table><p>input控件</p>

<table><thead><tr><th>属性值</th><th>说明</th></tr></thead><tbody><tr><td>text</td><td>单行 文本框</td></tr><tr><td>radio</td><td>单选按钮，name为相同值时候就可以实现互斥，要有value属性值，向服务器提交的就是value值</td></tr><tr><td>checkbox</td><td>复选框，同组复选框应该设置它们的name为相同值，要有value属性值，向服务器提交的就是name值+value值</td></tr><tr><td>password</td><td>密码框</td></tr><tr><td>select标签</td><td>表示下拉菜单，option是它内部的选项，select的属性name会被提交</td></tr><tr><td>textarea标签</td><td>多行文本框，有rows和cols属性，用于定义多行文本框的行数和列数</td></tr><tr><td>button</td><td>普通按钮</td></tr><tr><td>submit</td><td>重置按钮</td></tr><tr><td>reset</td><td>提交按钮</td></tr><tr><td>color</td><td>颜色选择控件</td></tr><tr><td>date、time</td><td>日期、时间选择控件</td></tr><tr><td>email</td><td>电子邮件输入控件</td></tr><tr><td>file</td><td>文件选择控件</td></tr><tr><td>number</td><td>数字输入控件</td></tr><tr><td>range</td><td>拖拽条</td></tr><tr><td>search</td><td>搜索框</td></tr><tr><td>url</td><td>网址输入控件</td></tr></tbody></table><p><strong>datalist控件</strong></p><p>datalist控件可以为输入框提供一些备选项，当用户输 入的内容与备选项文字相同时，将会显示智能感应</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"text"</span><span> </span><span>list</span><span>=</span><span>"province-list"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>datalist</span><span> </span><span>id</span><span>=</span><span>"province-list"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"山东"</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"山西"</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"广东"</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"广西"</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"河南"</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"河北"</span><span>&gt;</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"湖南"</span><span>&gt;</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"湖北"</span><span>&gt;</span></div></div><div><div><div>11</div></div><div><span>&lt;/</span><span>datalist</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>示例：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>form</span><span> </span><span>action</span><span>=</span><span>""</span><span> </span><span>method</span><span>=</span><span>"get"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>        </span></span><span>文本框required：&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"text"</span><span> </span><span>placeholder</span><span>=</span><span>"请输入文本"</span><span> </span><span>required</span><span> /&gt;</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>        </span></span><span>文本框disabled：</span></div></div><div><div><div>7</div></div><div><span><span>        </span></span><span>&lt;</span><span>input</span></div></div><div><div><div>8</div></div><div><span>               </span><span>type</span><span>=</span><span>"text"</span></div></div><div><div><div>9</div></div><div><span>               </span><span>placeholder</span><span>=</span><span>"请输入文本，disabled"</span></div></div><div><div><div>10</div></div><div><span>               </span><span>required</span></div></div><div><div><div>11</div></div><div><span>               </span><span>disabled</span></div></div><div><div><div>12</div></div><div><span><span>               </span></span><span>/&gt;</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;密码框：&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"password"</span><span> /&gt;&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;</span></div></div><div><div><div>16</div></div><div><span>        </span><span>&lt;!-- 单选name要一致,value是提交的值 --&gt;</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>&lt;</span><span>span</span><span>&gt;性别&lt;/</span><span>span</span><span>&gt;</span></div></div><div><div><div>18</div></div><div><span><span>        </span></span><span>&lt;</span><span>label</span><span> </span><span>for</span><span>=</span><span>"nan"</span></div></div><div><div><div>19</div></div><div><span><span>               </span></span><span>&gt;&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"radio"</span><span> </span><span>value</span><span>=</span><span>"man"</span><span> </span><span>name</span><span>=</span><span>"1"</span><span> </span><span>id</span><span>=</span><span>"nan"</span><span> /&gt;男&lt;/</span><span>label</span></div></div><div><div><div>20</div></div><div><span><span>            </span></span><span>&gt;</span></div></div><div><div><div>21</div></div><div><span><span>        </span></span><span>&lt;</span><span>label</span><span> </span><span>for</span><span>=</span><span>"nv"</span><span>&gt;</span></div></div><div><div><div>22</div></div><div><span><span>            </span></span><span>&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"radio"</span><span> </span><span>value</span><span>=</span><span>"grid"</span><span> </span><span>name</span><span>=</span><span>"1"</span><span> </span><span>id</span><span>=</span><span>"nv"</span><span> /&gt;女&lt;/</span><span>label</span></div></div><div><div><div>23</div></div><div><span><span>            </span></span><span>&gt;</span></div></div><div><div><div>24</div></div><div><span><span>    </span></span><span>&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;</span></div></div><div><div><div>26</div></div><div><span><span>        </span></span><span>&lt;</span><span>span</span><span>&gt;爱好组1&lt;/</span><span>span</span><span>&gt;</span></div></div><div><div><div>27</div></div><div><span><span>        </span></span><span>&lt;</span><span>label</span><span> </span><span>for</span><span>=</span><span>"1"</span></div></div><div><div><div>28</div></div><div><span><span>               </span></span><span>&gt;&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"checkbox"</span><span> </span><span>id</span><span>=</span><span>"1"</span><span> </span><span>name</span><span>=</span><span>"aihao"</span><span> </span><span>value</span><span>=</span><span>"chang"</span><span> /&gt;唱&lt;/</span><span>label</span></div></div><div><div><div>29</div></div><div><span><span>            </span></span><span>&gt;</span></div></div><div><div><div>30</div></div><div><span><span>        </span></span><span>&lt;</span><span>label</span><span> </span><span>for</span><span>=</span><span>"2"</span></div></div><div><div><div>31</div></div><div><span><span>               </span></span><span>&gt;&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"checkbox"</span><span> </span><span>id</span><span>=</span><span>"2"</span><span> </span><span>name</span><span>=</span><span>"aihao"</span><span> </span><span>value</span><span>=</span><span>"rab"</span><span> /&gt;rab&lt;/</span><span>label</span></div></div><div><div><div>32</div></div><div><span><span>            </span></span><span>&gt;</span></div></div><div><div><div>33</div></div><div><span><span>        </span></span><span>&lt;</span><span>label</span><span> </span><span>for</span><span>=</span><span>"3"</span></div></div><div><div><div>34</div></div><div><span><span>               </span></span><span>&gt;&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"checkbox"</span><span> </span><span>id</span><span>=</span><span>"3"</span><span> </span><span>name</span><span>=</span><span>"aihao"</span><span> </span><span>value</span><span>=</span><span>"tiao"</span><span> /&gt;跳</span></div></div><div><div><div>35</div></div><div><span><span>        </span></span><span>&lt;/</span><span>label</span><span>&gt;</span></div></div><div><div><div>36</div></div><div><span><span>        </span></span><span>&lt;</span><span>label</span><span> </span><span>for</span><span>=</span><span>"4"</span><span>&gt;</span></div></div><div><div><div>37</div></div><div><span><span>            </span></span><span>&lt;</span><span>input</span></div></div><div><div><div>38</div></div><div><span>                   </span><span>type</span><span>=</span><span>"checkbox"</span></div></div><div><div><div>39</div></div><div><span>                   </span><span>id</span><span>=</span><span>"4"</span></div></div><div><div><div>40</div></div><div><span>                   </span><span>name</span><span>=</span><span>"aihao"</span></div></div><div><div><div>41</div></div><div><span>                   </span><span>value</span><span>=</span><span>"lanqiu"</span></div></div><div><div><div>42</div></div><div><span><span>                   </span></span><span>/&gt;打篮球&lt;/</span><span>label</span></div></div><div><div><div>43</div></div><div><span><span>            </span></span><span>&gt;</span></div></div><div><div><div>44</div></div><div><span><span>    </span></span><span>&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>45</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;</span></div></div><div><div><div>46</div></div><div><span><span>        </span></span><span>&lt;</span><span>span</span><span>&gt;爱好组2&lt;/</span><span>span</span><span>&gt;</span></div></div><div><div><div>47</div></div><div><span><span>        </span></span><span>&lt;</span><span>label</span><span> </span><span>for</span><span>=</span><span>"5"</span></div></div><div><div><div>48</div></div><div><span><span>               </span></span><span>&gt;&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"checkbox"</span><span> </span><span>id</span><span>=</span><span>"5"</span><span> </span><span>name</span><span>=</span><span>"aihao2"</span><span> </span><span>value</span><span>=</span><span>"chang"</span><span> /&gt;唱&lt;/</span><span>label</span></div></div><div><div><div>49</div></div><div><span><span>            </span></span><span>&gt;</span></div></div><div><div><div>50</div></div><div><span><span>        </span></span><span>&lt;</span><span>label</span><span> </span><span>for</span><span>=</span><span>"6"</span></div></div><div><div><div>51</div></div><div><span><span>               </span></span><span>&gt;&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"checkbox"</span><span> </span><span>id</span><span>=</span><span>"6"</span><span> </span><span>name</span><span>=</span><span>"aihao2"</span><span> </span><span>value</span><span>=</span><span>"rab"</span><span> /&gt;rab&lt;/</span><span>label</span></div></div><div><div><div>52</div></div><div><span><span>            </span></span><span>&gt;</span></div></div><div><div><div>53</div></div><div><span><span>        </span></span><span>&lt;</span><span>label</span><span> </span><span>for</span><span>=</span><span>"7"</span></div></div><div><div><div>54</div></div><div><span><span>               </span></span><span>&gt;&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"checkbox"</span><span> </span><span>id</span><span>=</span><span>"7"</span><span> </span><span>name</span><span>=</span><span>"aihao2"</span><span> </span><span>value</span><span>=</span><span>"tiao"</span><span> /&gt;跳</span></div></div><div><div><div>55</div></div><div><span><span>        </span></span><span>&lt;/</span><span>label</span><span>&gt;</span></div></div><div><div><div>56</div></div><div><span><span>        </span></span><span>&lt;</span><span>label</span><span> </span><span>for</span><span>=</span><span>"8"</span><span>&gt;</span></div></div><div><div><div>57</div></div><div><span><span>            </span></span><span>&lt;</span><span>input</span></div></div><div><div><div>58</div></div><div><span>                   </span><span>type</span><span>=</span><span>"checkbox"</span></div></div><div><div><div>59</div></div><div><span>                   </span><span>id</span><span>=</span><span>"8"</span></div></div><div><div><div>60</div></div><div><span>                   </span><span>name</span><span>=</span><span>"aihao2"</span></div></div><div><div><div>61</div></div><div><span>                   </span><span>value</span><span>=</span><span>"lanqiu"</span></div></div><div><div><div>62</div></div><div><span><span>                   </span></span><span>/&gt;打篮球&lt;/</span><span>label</span></div></div><div><div><div>63</div></div><div><span><span>            </span></span><span>&gt;</span></div></div><div><div><div>64</div></div><div><span><span>    </span></span><span>&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>65</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;</span></div></div><div><div><div>66</div></div><div><span><span>        </span></span><span>下拉框：</span></div></div><div><div><div>67</div></div><div><span><span>        </span></span><span>&lt;</span><span>select</span><span> </span><span>name</span><span>=</span><span>"payment"</span><span>&gt;</span></div></div><div><div><div>68</div></div><div><span><span>            </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"alipay"</span><span>&gt;支付宝&lt;/</span><span>option</span><span>&gt;</span></div></div><div><div><div>69</div></div><div><span><span>            </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"wx"</span><span>&gt;微信&lt;/</span><span>option</span><span>&gt;</span></div></div><div><div><div>70</div></div><div><span><span>            </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"bank"</span><span>&gt;网银&lt;/</span><span>option</span><span>&gt;</span></div></div><div><div><div>71</div></div><div><span><span>        </span></span><span>&lt;/</span><span>select</span><span>&gt;</span></div></div><div><div><div>72</div></div><div><span><span>    </span></span><span>&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>73</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;多行文本框：&lt;</span><span>textarea</span><span> </span><span>cols</span><span>=</span><span>"50"</span><span> </span><span>rows</span><span>=</span><span>"20"</span><span>&gt;&lt;/</span><span>textarea</span><span>&gt;&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>74</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;date&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"date"</span><span> /&gt;&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>75</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;time&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"time"</span><span> /&gt;&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>76</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;email&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"email"</span><span> /&gt;&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>77</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;file&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"file"</span><span> /&gt;&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>78</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;number&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"number"</span><span> /&gt;&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>79</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;range&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"range"</span><span> /&gt;&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>80</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;搜索框&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"search"</span><span> /&gt;&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>81</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;只能输入网址&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"url"</span><span> /&gt;&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>82</div></div><div><span><span>    </span></span><span>&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"text"</span><span> </span><span>list</span><span>=</span><span>"province-list"</span><span> /&gt;</span></div></div><div><div><div>83</div></div><div><span><span>    </span></span><span>&lt;</span><span>datalist</span><span> </span><span>id</span><span>=</span><span>"province-list"</span><span>&gt;</span></div></div><div><div><div>84</div></div><div><span><span>        </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"山东"</span><span>&gt;&lt;/</span><span>option</span><span>&gt;</span></div></div><div><div><div>85</div></div><div><span><span>        </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"山西"</span><span>&gt;&lt;/</span><span>option</span><span>&gt;</span></div></div><div><div><div>86</div></div><div><span><span>        </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"广东"</span><span>&gt;&lt;/</span><span>option</span><span>&gt;</span></div></div><div><div><div>87</div></div><div><span><span>        </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"广西"</span><span>&gt;&lt;/</span><span>option</span><span>&gt;</span></div></div><div><div><div>88</div></div><div><span><span>        </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"河南"</span><span>&gt;&lt;/</span><span>option</span><span>&gt;</span></div></div><div><div><div>89</div></div><div><span><span>        </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"河北"</span><span>&gt;&lt;/</span><span>option</span><span>&gt;</span></div></div><div><div><div>90</div></div><div><span><span>        </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"湖南"</span><span>&gt;&lt;/</span><span>option</span><span>&gt;</span></div></div><div><div><div>91</div></div><div><span><span>        </span></span><span>&lt;</span><span>option</span><span> </span><span>value</span><span>=</span><span>"湖北"</span><span>&gt;&lt;/</span><span>option</span><span>&gt;</span></div></div><div><div><div>92</div></div><div><span><span>    </span></span><span>&lt;/</span><span>datalist</span><span>&gt;</span></div></div><div><div><div>93</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"button"</span><span> </span><span>value</span><span>=</span><span>"按钮"</span><span> /&gt;&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>94</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"submit"</span><span> </span><span>value</span><span>=</span><span>"登录"</span><span> /&gt;&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>95</div></div><div><span><span>    </span></span><span>&lt;</span><span>p</span><span>&gt;&lt;</span><span>input</span><span> </span><span>type</span><span>=</span><span>"reset"</span><span> </span><span>value</span><span>=</span><span>"重置"</span><span> /&gt;&lt;/</span><span>p</span><span>&gt;</span></div></div><div><div><div>96</div></div><div><span>&lt;/</span><span>form</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h1>表格标签<a href="#表格标签"><span>#</span></a></h1><p>表格控件可以参考列表标签中的定义列表，一个书写的顺序是列，表格是按照行</p><p>一个示例</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>table</span><span> </span><span>border</span><span>=</span><span>"1"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>&lt;</span><span>caption</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>        </span></span><span>表格标题</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>&lt;/</span><span>caption</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>&lt;</span><span>thead</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>        </span></span><span>&lt;</span><span>tr</span><span>&gt;</span></div></div><div><div><div>7</div></div><div><span><span>            </span></span><span>&lt;</span><span>th</span><span>&gt;表头1&lt;/</span><span>th</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span><span>            </span></span><span>&lt;</span><span>th</span><span>&gt;表头2&lt;/</span><span>th</span><span>&gt;</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>&lt;/</span><span>tr</span><span>&gt;</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>&lt;/</span><span>thead</span><span>&gt;</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>&lt;</span><span>tbody</span><span>&gt;</span></div></div><div><div><div>12</div></div><div><span><span>        </span></span><span>&lt;</span><span>tr</span><span>&gt;</span></div></div><div><div><div>13</div></div><div><span>            </span><span>&lt;!-- 向下合并列 --&gt;</span></div></div><div><div><div>14</div></div><div><span><span>            </span></span><span>&lt;</span><span>td</span><span> </span><span>colspan</span><span>=</span><span>"2"</span><span>&gt;第1行第1列&lt;/</span><span>td</span><span>&gt;</span></div></div><div><div><div>15</div></div><div><span>            </span><span>&lt;!-- &lt;td&gt;第1行第2列&lt;/td&gt; --&gt;</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>&lt;/</span><span>tr</span><span>&gt;</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>&lt;</span><span>tr</span><span>&gt;</span></div></div><div><div><div>18</div></div><div><span><span>            </span></span><span>&lt;</span><span>td</span><span>&gt;第2行第1列&lt;/</span><span>td</span><span>&gt;</span></div></div><div><div><div>19</div></div><div><span>            </span><span>&lt;!-- 向下合并行 --&gt;</span></div></div><div><div><div>20</div></div><div><span><span>            </span></span><span>&lt;</span><span>td</span><span> </span><span>rowspan</span><span>=</span><span>"2"</span><span>&gt;第2行第2列&lt;/</span><span>td</span><span>&gt;</span></div></div><div><div><div>21</div></div><div><span><span>        </span></span><span>&lt;/</span><span>tr</span><span>&gt;</span></div></div><div><div><div>22</div></div><div><span><span>        </span></span><span>&lt;</span><span>tr</span><span>&gt;</span></div></div><div><div><div>23</div></div><div><span><span>            </span></span><span>&lt;</span><span>td</span><span>&gt;第3行第1列&lt;/</span><span>td</span><span>&gt;</span></div></div><div><div><div>24</div></div><div><span>            </span><span>&lt;!-- &lt;td&gt;第3行第2列&lt;/td&gt; --&gt;</span></div></div><div><div><div>25</div></div><div><span><span>        </span></span><span>&lt;/</span><span>tr</span><span>&gt;</span></div></div><div><div><div>26</div></div><div><span><span>    </span></span><span>&lt;/</span><span>tbody</span><span>&gt;</span></div></div><div><div><div>27</div></div><div><span>&lt;/</span><span>table</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>效果：</p><table>
      <caption>
        表格标题
      </caption>
      <thead>
        <tr>
          <th>表头1</th>
          <th>表头2</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          
          <td>第1行第1列</td>
          
        </tr>
        <tr>
          <td>第2行第1列</td>
          
          <td>第2行第2列</td>
        </tr>
        <tr>
          <td>第3行第1列</td>
          
        </tr>
      </tbody>
    </table></section>]]></content>
    </entry>
    <entry>
      <id>https://f.youzi177.cn/posts/20261004-sui-bi-gan-wu/</id>
      <title type="text">随笔感悟</title>
      <published>2026-10-04T00:00:00.000Z</published>
      <updated>2026-10-04T00:00:00.000Z</updated>
      <author><name>小封鸭</name></author>
      <link rel="alternate" href="https://f.youzi177.cn/posts/20261004-sui-bi-gan-wu/"/>
      <summary type="text">记录一下这半年来的经历和感悟，也算是这对半年来对自己的一个总结。</summary>
      <content type="html"><![CDATA[本文已加密保护，请访问网站查看。]]></content>
    </entry>
</feed>
