孟令江 發表於 2025-3-27 13:20:00

JavaScript

<h1 id="javascript-基础">javascript 基础</h1>
<p>快速上手<br>
MDN</p>
<h2 id="js-定义">JS 定义</h2>
<p>HTML/CSS/JS 的关系,HTML 负责网页结构,CSS 负责网页样式,JS 负责网页行为</p>
<p>JavaScript 是运行在浏览器端的脚本语言(弱类型),由浏览器解释执行,不需要编译,功能在运行过程中逐行解释并执行的,现在的 JavaScript 也可以在 Node.js 技术进行服务端运行</p>
<p>现在 JS 使用于网页特效,服务端开发(Node.js),桌面程序(Flectron),App(Cordova),控制硬件-物联网(Ruff),游戏开发(cocos2d js)等等</p>
<ol>
<li>浏览器如何执行 JS</li>
</ol>
<p>浏览器分为渲染部分和 JS 引擎<br>
渲染引擎:用来解析 HTML 和 CSS,俗称内核,如 chrome 浏览器的 blink,老版本的 webkit<br>
JS 引擎:也成为 JS 解释器。用来读取网页中的 JS 代码,对其处理后运行,如 chrome 浏览器的 V8</p>
<ol start="2">
<li>JSAPI DOM—文档对象模型</li>
</ol>
<p>是处理可扩展性标记语言的标准编程接口,提供各种接口,可以对页面上的各种元素进行操作如大小,位置,颜色</p>
<ol start="3">
<li>JSAPI BOM—浏览器对象模型</li>
</ol>
<p>提供独立内容,可以于浏览器窗口进行互动的对象结构,通过 BOM 可以操作浏览器窗口,如弹出窗口,控制浏览器跳转,获取分辨率</p>
<h2 id="js-引入方式">JS 引入方式</h2>
<ol>
<li>行内式 - 用于事件</li>
</ol>
<pre><code class="language-html">&lt;input type="button" name="" onclick="alert('ok!')" /&gt;
</code></pre>
<ol start="2">
<li>内嵌式 - 学习使用</li>
</ol>
<pre><code class="language-html">&lt;script type="text/javascript"&gt;
alert("ok!");
&lt;/script&gt;
</code></pre>
<ol start="3">
<li>外链式 - 常用</li>
</ol>
<pre><code class="language-html">&lt;script type="text/javascript" src="js/inderx.js"&gt;&lt;/script&gt;
</code></pre>
<h2 id="js-代码结构">JS 代码结构</h2>
<ol>
<li>
<p>使用<code>;</code>分割消息,会有自动分号插入,但并不总是插入在预期位置。</p>
</li>
<li>
<p>使用<code>//</code>或者<code>/* */</code>进行注释</p>
</li>
<li>
<p>现代模式需要使用<code>use strict</code>开启,且必须在脚本的第一行,或使用包装器函数进行包裹。</p>
<ul>
<li>目前最好将其写入脚本当中,但当代码全部写在 class 和 module 中时,会自动开启。</li>
<li>开启后无法关闭。</li>
</ul>
</li>
</ol>
<h3 id="变量和数据类型">变量和数据类型</h3>
<ol>
<li>变量的声明 - 通常使用<code>let</code>进行声明</li>
</ol>
<pre><code class="language-js">let user; // 只声明
let username = "jojo"; // 声明并赋值
let age = 18,
message = "hello"; // 同时声明多个变量
</code></pre>
<ol start="2">
<li>变量命名规范 - 变量名称必须仅包含字母、数字、符号 <code>$</code> 和 <code>_</code>,且首字符必须非数字。</li>
</ol>
<pre><code class="language-js">// 区分大小写,通常使用小驼峰命名(除第一个单词以外都以大写字母开头)
// 对象类型+变量名如:对象 age 则命名为 nAge
// 变量名最好有实际含义
</code></pre>
<ol start="3">
<li>常量的声明 - 使用<code>const</code>进行声明,声明的常量不可修改。</li>
</ol>
<pre><code class="language-js">const COLOR_RED = "#f00"; // 常量名全部大写
const age = someCode(BIRTHDAY); // 常量值在声明时确定,这样的常量则使用变量命名法则。
</code></pre>
<ol start="4">
<li>旧的声明方式 - 使用<code>var</code>进行声明(不推荐使用)</li>
</ol>
<pre><code class="language-js">var username = "jojo"; // 一般情况下不再使用
</code></pre>
<ol start="5">
<li>数据类型 - js 当中有七大原始类型
<ul>
<li>number 数据类型,bigint 大整数类型</li>
<li>string 字符类型</li>
<li>boolean 布尔类型</li>
<li>undefined undefined 类型,变量声明未初始化</li>
<li>null null 类型,表示空对象,如果定义的变量将来准备保存对象,可将变量初始化为 null</li>
<li>object 复合类型,Symbol 创建对象的唯一标识符</li>
</ul>
</li>
</ol>
<pre><code class="language-js">let nFigure = 1; // typeof iNumber = number
nFigure = 2.123; // typeof iNumber = number
nFigure = Infinity; // typeof iNumber = number
nFigure = NaN; // typeof iNumber = number
bFigure = 123n; // typeof iNumber = bigint // 整数后加n设置为 bigint 大整数类型

let sName = "jojo"; // 可以使用单引号或双引号,没有特殊含义 typeof sName = string
let sName2 = `${sName} is a boy`; // 使用反引号包裹,可以插入变量;

let boolNameFieldChecked = true; // 名称字段是否被检测,true已经检查,typeof boolNameFieldChecked = boolean

let age = null; // typeof age = object // null 表示空,是一个空对象指针

let age2; // typeof age2 = undefined // 未定义

// 最后一种到对象时演示
</code></pre>
<ol start="6">
<li>数据类型转换</li>
</ol>
<pre><code class="language-js">let nFigure = 12;
nFigure1 = Infinity;
nFigure2 = NaN;
let sFigure = "abc12";
let sFigure1 = "12";
let boolFigure = true;
let empty = null;
let undefinedFigure;
let conversion;

// 转换为字符串
conversion = String(nFigure); // '12'
conversion = nFigure1.toString(); // 'Infinity'
conversion = nFigure2.toString(); // 'NaN'
conversion = String(boolFigure); // 'true'
conversion = String(empty); // ''
conversion = undefinedFigure.toString(); // 'undefined'

// 转换为数字
conversion = Number(sFigure); // NaN
conversion = Number(sFigure1); // 12
conversion = Number(boolFigure); // 1
conversion = Number(empty); // 0
conversion = Number(undefinedFigure); // NaN

// 转换为布尔值
let boolFigure = Boolean(nFigure); // true
boolFigure = Boolean(empty); // false 数字0,空字符串"",null,undefined,NaN 变换后为 false

// 转为object到对象时演示
</code></pre>
<h3 id="交互方式">交互方式</h3>
<ol>
<li>alert - 弹出消息窗口</li>
</ol>
<pre><code class="language-js">alert("hello world!");
</code></pre>
<ol start="2">
<li>prompt - 弹出消息窗口,可以接收输入</li>
</ol>
<pre><code class="language-js">let age = prompt("请输入年龄:", 18); // 第一个参数是提示信息,第二个参数是初始值(可以省略,但不建议)
alert(`${age}岁`); // 会弹两次窗口,第一次是输入窗口,第二次是弹出的提示窗口
</code></pre>
<ol start="3">
<li>confirm - 弹出消息窗口,并可以点击确定或取消</li>
</ol>
<pre><code class="language-js">let isConfirm = confirm("确定要删除吗?");
if (isConfirm) {
alert(isConfirm);
alert("删除成功");
} else {
alert("取消删除");
}
</code></pre>
<h3 id="运算符">运算符</h3>
<table>
<thead>
<tr>
<th style="text-align: center">优先级</th>
<th style="text-align: center">运算符类型</th>
<th style="text-align: center">结合性</th>
<th style="text-align: center">运算符</th>
<th style="text-align: center">使用场景</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center">19</td>
<td style="text-align: center">分组</td>
<td style="text-align: center">n/a</td>
<td style="text-align: center"><code>(…)</code></td>
<td style="text-align: center"><code>a*(b-c)</code></td>
</tr>
<tr>
<td style="text-align: center">18</td>
<td style="text-align: center">成员访问</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>….…</code></td>
<td style="text-align: center"><code>obj.a</code></td>
</tr>
<tr>
<td style="text-align: center">18</td>
<td style="text-align: center">需计算的成员访问</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…[…]</code></td>
<td style="text-align: center"><code>obj["name"]</code></td>
</tr>
<tr>
<td style="text-align: center">18</td>
<td style="text-align: center">new(带参数列表)</td>
<td style="text-align: center">n/a</td>
<td style="text-align: center"><code>new …(…)</code>构建实例</td>
<td style="text-align: center"><code>new add(1,2)</code></td>
</tr>
<tr>
<td style="text-align: center">18</td>
<td style="text-align: center">函数调用</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…(…)</code>执行函数</td>
<td style="text-align: center"><code>add(1,2)</code></td>
</tr>
<tr>
<td style="text-align: center">18</td>
<td style="text-align: center">可选链</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…?.…</code> 对<code>?</code>前校验</td>
<td style="text-align: center"><code>obj.a?.b</code></td>
</tr>
<tr>
<td style="text-align: center">17</td>
<td style="text-align: center">new(无参数列表)</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>new …</code></td>
<td style="text-align: center"><code>new add</code></td>
</tr>
<tr>
<td style="text-align: center">16</td>
<td style="text-align: center">后置递增</td>
<td style="text-align: center">n/a</td>
<td style="text-align: center"><code>…++</code></td>
<td style="text-align: center"><code>i++</code></td>
</tr>
<tr>
<td style="text-align: center">16</td>
<td style="text-align: center">后置递减</td>
<td style="text-align: center">n/a</td>
<td style="text-align: center"><code>…--</code></td>
<td style="text-align: center"><code>i--</code></td>
</tr>
<tr>
<td style="text-align: center">15</td>
<td style="text-align: center">逻辑非</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>!…</code></td>
<td style="text-align: center"><code>!true=false</code></td>
</tr>
<tr>
<td style="text-align: center">15</td>
<td style="text-align: center">按位非</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>~…</code></td>
<td style="text-align: center"><code>~1011=0100</code></td>
</tr>
<tr>
<td style="text-align: center">15</td>
<td style="text-align: center">一元加法</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>+…</code></td>
<td style="text-align: center"><code>+12</code></td>
</tr>
<tr>
<td style="text-align: center">15</td>
<td style="text-align: center">一元减法</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>-…</code></td>
<td style="text-align: center"><code>-13</code></td>
</tr>
<tr>
<td style="text-align: center">15</td>
<td style="text-align: center">前置递增</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>++…</code></td>
<td style="text-align: center"><code>++i</code></td>
</tr>
<tr>
<td style="text-align: center">15</td>
<td style="text-align: center">前置递减</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>--…</code></td>
<td style="text-align: center"><code>--i</code></td>
</tr>
<tr>
<td style="text-align: center">15</td>
<td style="text-align: center">typeof</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>typeof …</code></td>
<td style="text-align: center"><code>typeof a</code></td>
</tr>
<tr>
<td style="text-align: center">15</td>
<td style="text-align: center">void</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>void … </code></td>
<td style="text-align: center"><code>void(0)</code></td>
</tr>
<tr>
<td style="text-align: center">15</td>
<td style="text-align: center">delete</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>delete … </code></td>
<td style="text-align: center"><code>delete a.b </code></td>
</tr>
<tr>
<td style="text-align: center">15</td>
<td style="text-align: center">await</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>await … </code></td>
<td style="text-align: center"><code>await add() </code></td>
</tr>
<tr>
<td style="text-align: center">14</td>
<td style="text-align: center">幂</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>…**… </code></td>
<td style="text-align: center"><code>a**b </code></td>
</tr>
<tr>
<td style="text-align: center">13</td>
<td style="text-align: center">乘法</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…*… </code></td>
<td style="text-align: center"><code>a*b </code></td>
</tr>
<tr>
<td style="text-align: center">13</td>
<td style="text-align: center">除法</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…/… </code></td>
<td style="text-align: center"><code>a/b </code></td>
</tr>
<tr>
<td style="text-align: center">13</td>
<td style="text-align: center">取余</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…%… </code></td>
<td style="text-align: center"><code>a%b </code></td>
</tr>
<tr>
<td style="text-align: center">12</td>
<td style="text-align: center">加法</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…+… </code></td>
<td style="text-align: center"><code>a+b </code></td>
</tr>
<tr>
<td style="text-align: center">12</td>
<td style="text-align: center">减法</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…-… </code></td>
<td style="text-align: center"><code>a-b </code></td>
</tr>
<tr>
<td style="text-align: center">11</td>
<td style="text-align: center">按位左移</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…&lt;&lt;… </code></td>
<td style="text-align: center"><code>16&lt;&lt;2=64 </code></td>
</tr>
<tr>
<td style="text-align: center">11</td>
<td style="text-align: center">按位右移</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…&gt;&gt;… </code></td>
<td style="text-align: center"><code>16&gt;&gt;2=4 </code></td>
</tr>
<tr>
<td style="text-align: center">11</td>
<td style="text-align: center">无符号右移</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…&gt;&gt;&gt;… </code></td>
<td style="text-align: center"><code>-16&gt;&gt;&gt;31=1 </code></td>
</tr>
<tr>
<td style="text-align: center">10</td>
<td style="text-align: center">小于</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…&lt;… </code></td>
<td style="text-align: center"><code>5&lt;6=true </code></td>
</tr>
<tr>
<td style="text-align: center">10</td>
<td style="text-align: center">小于等于</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…&lt;=… </code></td>
<td style="text-align: center"><code>5&lt;=6=true </code></td>
</tr>
<tr>
<td style="text-align: center">10</td>
<td style="text-align: center">大于</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…&gt;… </code></td>
<td style="text-align: center"><code>5&gt;6=false </code></td>
</tr>
<tr>
<td style="text-align: center">10</td>
<td style="text-align: center">大于等于</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…&gt;=… </code></td>
<td style="text-align: center"><code>5&gt;=6=false </code></td>
</tr>
<tr>
<td style="text-align: center">10</td>
<td style="text-align: center">in</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…in… </code></td>
<td style="text-align: center"><code>a in b </code></td>
</tr>
<tr>
<td style="text-align: center">10</td>
<td style="text-align: center">instanceof</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…instanceof… </code></td>
<td style="text-align: center"><code>a instanceof b </code></td>
</tr>
<tr>
<td style="text-align: center">9</td>
<td style="text-align: center">相等</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…==… </code></td>
<td style="text-align: center"><code>a == b </code></td>
</tr>
<tr>
<td style="text-align: center">9</td>
<td style="text-align: center">不相等</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…!=… </code></td>
<td style="text-align: center"><code>a != b </code></td>
</tr>
<tr>
<td style="text-align: center">9</td>
<td style="text-align: center">严格相等</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…===… </code></td>
<td style="text-align: center"><code>a === b </code></td>
</tr>
<tr>
<td style="text-align: center">9</td>
<td style="text-align: center">严格不相等</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…!==… </code></td>
<td style="text-align: center"><code>a !== b </code></td>
</tr>
<tr>
<td style="text-align: center">8</td>
<td style="text-align: center">按位与</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…&amp;… </code></td>
<td style="text-align: center"><code>12 &amp; 4=4 </code></td>
</tr>
<tr>
<td style="text-align: center">7</td>
<td style="text-align: center">按位异或</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…^… </code></td>
<td style="text-align: center"><code>12 ^ 4=8 </code></td>
</tr>
<tr>
<td style="text-align: center">6</td>
<td style="text-align: center">按位或</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…|… </code></td>
<td style="text-align: center"><code>12 | 4=12 </code></td>
</tr>
<tr>
<td style="text-align: center">5</td>
<td style="text-align: center">逻辑与</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…&amp;&amp;… </code></td>
<td style="text-align: center"><code>12 &amp;&amp; 4=4 </code></td>
</tr>
<tr>
<td style="text-align: center">4</td>
<td style="text-align: center">逻辑或</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…||… </code></td>
<td style="text-align: center"><code>12 &amp; 4=12 </code></td>
</tr>
<tr>
<td style="text-align: center">4</td>
<td style="text-align: center">空值合并</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…??… </code></td>
<td style="text-align: center">替代逻辑或,做默认值</td>
</tr>
<tr>
<td style="text-align: center">3</td>
<td style="text-align: center">条件(三元)运算符</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>…?…:… </code></td>
<td style="text-align: center"><code>a?1:2 </code></td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">赋值</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>…=… </code></td>
<td style="text-align: center"><code>a=2 </code></td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">赋值</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>…+=… </code></td>
<td style="text-align: center"><code>a+=2 </code></td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">赋值</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>…-=… </code></td>
<td style="text-align: center"><code>a-=2 </code></td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">赋值</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>…**=… </code></td>
<td style="text-align: center"><code>a**=2 </code></td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">赋值</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>…*=… </code></td>
<td style="text-align: center"><code>a*=2 </code></td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">赋值</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>…/=… </code></td>
<td style="text-align: center"><code>a/=2 </code></td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">赋值</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>…%=… </code></td>
<td style="text-align: center"><code>a%=2 </code></td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">赋值</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>…&lt;&lt;=… </code></td>
<td style="text-align: center"><code>a&lt;&lt;=2 </code></td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">赋值</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>…&gt;&gt;=… </code></td>
<td style="text-align: center"><code>a&gt;&gt;=2 </code></td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">赋值</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>…&gt;&gt;&gt;=… </code></td>
<td style="text-align: center"><code>a&gt;&gt;&gt;=2 </code></td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">赋值</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>…&amp;=… </code></td>
<td style="text-align: center"><code>a&amp;=2 </code></td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">赋值</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>…^=… </code></td>
<td style="text-align: center"><code>a^=2 </code></td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">赋值</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>…|=… </code></td>
<td style="text-align: center"><code>a|=2 </code></td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">赋值</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>…&amp;&amp;=… </code></td>
<td style="text-align: center"><code>a&amp;&amp;=2 </code></td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">赋值</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>…||=… </code></td>
<td style="text-align: center"><code>a||=2 </code></td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">赋值</td>
<td style="text-align: center">从右到左</td>
<td style="text-align: center"><code>…??=… </code></td>
<td style="text-align: center"><code>a??=2 </code></td>
</tr>
<tr>
<td style="text-align: center">1</td>
<td style="text-align: center">逗号/序列</td>
<td style="text-align: center">从左到右</td>
<td style="text-align: center"><code>…,… </code></td>
<td style="text-align: center"><code>a=2,b=3 </code></td>
</tr>
</tbody>
</table>
<ol>
<li><code>()[]</code>,优先级运算符</li>
<li>一元操作符 <code>-</code>减,<code>+</code>加,<code>--</code>自减,<code>++</code>自增
<ul>
<li>自减自增运算符,前置和后置的区别,前置先运算再赋值,后置先赋值再运算</li>
<li>正/负运算符,会自动执行类型转换,将其他类型转换为数字类型</li>
</ul>
</li>
<li>算术运算符 <code>+</code>加,<code>-</code>减,<code>*</code>乘,<code>/</code>除,<code>%</code>取余,<code>**</code>幂;先乘除后加减
<ul>
<li>连接运算符 <code>+</code>,<code>'1'+2="12"</code>,<code>2+2+'1'="41"</code>,<code>1+'2'+'2'="122"</code></li>
</ul>
</li>
<li>关系操作符 <code>==</code>等于,<code>!=</code>不等于,<code>===</code>全等于,<code>!==</code>不全等于,<code>&gt;</code>大于,<code>&lt;</code>小于,<code>&gt;=</code>大于等于,<code>&lt;=</code>小于等于
<ul>
<li>比较结果均返回布尔类型</li>
<li>字符串比较会按照字典的方式一个个字符比较,比较的是字符的 Unicode 编码</li>
<li>等于<code>==</code>会转换类型并对比。全等于<code>===</code>不转换类型直接对比。</li>
</ul>
</li>
<li>逻辑运算符 <code>!</code>非,<code>&amp;&amp;</code>与,<code>||</code>或,<code>??</code>空值合并;先非再与最后或
<ul>
<li><code>!true = false</code>,<code>!false = true</code></li>
<li><code>true||true = true</code>,<code>true||false = true</code>,<code>false||true = true</code>,<code>false||false = false</code></li>
<li>或运算执行到<code>true</code>就停止,返回<code>true</code></li>
<li><code>true&amp;&amp;true = true</code>,<code>true&amp;&amp;false = false</code>,<code>false&amp;&amp;true = false</code>,<code>false&amp;&amp;false = false</code></li>
<li>与运算执行到<code>false</code>就停止,返回<code>false</code></li>
<li><code>??</code>空值合并运算符,当运算符左侧为<code>null</code>或<code>undefined</code>时,返回右侧的值,否则返回左侧的值</li>
</ul>
</li>
<li>三目运算符 <code>? :</code>,如果条件为真,则返回冒号前的值,否则返回冒号后的值</li>
<li>赋值运算符 <code>=</code>等号,<code>+=</code>加等,<code>-=</code>减等,<code>*=</code>乘等,<code>/=</code>除等,<code>%=</code>取余等</li>
<li>逗号运算符 <code>,</code>,从左到右依次执行,返回最后一个值</li>
</ol>
<h3 id="条件分支语句">条件分支语句</h3>
<ol>
<li>if 语句</li>
</ol>
<pre><code class="language-js">let nFigure = 70;
let sFigure = "12";
//第一种
if (nFigure == 70) {
console.log("相等!");
}
//第二种
if (sFigure === 12) {
console.log("相等!");
} else {
console.log("不相等!");
}
//第三种
if (nFigure &lt;= 100 &amp;&amp; nFigure &gt; 90) {
console.log("优秀");
} else if (nFigure &lt;= 90 &amp;&amp; nFigure &gt; 80) {
console.log("良好");
} else if (nFigure &lt;= 80 &amp;&amp; nFigure &gt;= 60) {
console.log("及格");
} else {
console.log("不及格");
}
</code></pre>
<ol start="2">
<li>? 语句</li>
</ol>
<pre><code class="language-js">let nFigure = 70;
let sFigure = "12";
console.log(nFigure == 70 ? "相等!" : "不相等!");

console.log(
nFigure &lt;= 100 &amp;&amp; nFigure &gt; 90
    ? "优秀"
    : nFigure &lt;= 90 &amp;&amp; nFigure &gt; 80
    ? "良好"
    : nFigure &lt;= 80 &amp;&amp; nFigure &gt;= 60
    ? "及格"
    : "不及格"
);

nFigure &lt;= 100 &amp;&amp; nFigure &gt; 90
? console.log("优秀")
: nFigure &lt;= 90 &amp;&amp; nFigure &gt; 80
? console.log("良好")
: nFigure &lt;= 80 &amp;&amp; nFigure &gt;= 60
? console.log("及格")
: console.log("不及格");
</code></pre>
<h3 id="循环语句">循环语句</h3>
<ol>
<li>while 循环</li>
</ol>
<pre><code class="language-js">let nFigure = 0;
while (nFigure &lt; 100) {
nFigure++;
console.log(nFigure);
}
</code></pre>
<ol start="2">
<li>do-while 循环,至少循环一次</li>
</ol>
<pre><code class="language-js">let nFigure = 0;
do {
nFigure++;
console.log(nFigure);
} while (nFigure &lt; 100);
</code></pre>
<ol start="3">
<li>for 循环</li>
</ol>
<pre><code class="language-js">// let nFigure = 0;
for (let nFigure = 0; nFigure &lt;= 100; nFigure++) {
// 内联变量声明
console.log(nFigure);
}
/* 执行流程:
-&gt;let nFigure = 0;
-&gt;如果nFigure &lt;= 100 成立 -&gt; 运行console.log(nFigure); -&gt;运行nFigure++
-&gt;如果nFigure &lt;= 100 成立 -&gt; 运行console.log(nFigure); -&gt;运行nFigure++
-&gt;...
-&gt;如果nFigure &lt;= 100 不成立 -&gt; 结束循环
*/
</code></pre>
<h3 id="跳出循环">跳出循环</h3>
<ol>
<li>break 语句</li>
</ol>
<pre><code class="language-js">for (let nFigure = 0; nFigure &lt;= 100; nFigure++) {
if (nFigure == 50) {
    break;
}
console.log(nFigure);
}
</code></pre>
<ol start="2">
<li>continue 语句</li>
</ol>
<pre><code class="language-js">for (let nFigure = 0; nFigure &lt;= 100; nFigure++) {
if (nFigure == 50) {
    continue;
}
console.log(nFigure);
}
</code></pre>
<ol start="3">
<li>标签跳出</li>
</ol>
<pre><code class="language-js">outer: for (let nFigure = 0; nFigure &lt;= 100; nFigure++) {
for (let jNum = 0; jNum &lt;= 100; jNum++) {
    if (nFigure == 50) {
      break outer; // 跳出outer循环,直接执行到console.log("跳出循环");
    }
    console.log(nFigure);
}
}
console.log("跳出循环");
</code></pre>
<h3 id="多分枝语句">多分枝语句</h3>
<p>这里主要的是接收数据的数据类型,需要同时匹配才可以。</p>
<pre><code class="language-js">switch (x) {
case 1:
    //do something
    break;
case 2:
    //do something
    break;
default:
    //do something
    break;
}
</code></pre>
<h2 id="函数">函数</h2>
<h3 id="函数声明和调用">函数声明和调用</h3>
<p>函数通常是一个动作/行为,给函数起名时应该是动词,简短且明确的描述函数作用。<br>
通常是动词开头例如:<code>show..</code>展示什么内容,<code>get...</code>得到什么值,<code>calc...</code>计算某些内容,<code>create...</code>创建一些东西,<code>check...</code>检查内容并返回布尔值。</p>
<pre><code class="language-js">// 1. 函数声明,声明后的函数可以在任意地方调用,因为这是全局性的
function fnName(parameter1, parameter2, ... parameterN) {
...body...
}// 声明一个叫fnName的函数,接收参数parameter1,parameter2,...parameterN,函数体为body
// 2. 函数复制
let func = fnName; // 将函数赋值给变量func,func也可以调用函数
// 3. 函数调用
fnName(value1, value2, ... valueN);// 调用函数,传入参数value1,value2,...valueN
func(value1, value2, ... valueN);// 同等调用
// 4. 函数表达式,创建一个匿名函数并复制给sayHi
// 执行到这一句时才会创建函数,这只能在此之后调用函数
let sayHi = function(value1, value2, ... valueN) {
alert(value1);
};
// 5. 传入的参数可以是任意类型,包括函数
// 如果传入函数,则称其为回调函数,回调函数会在函数体内被调用
</code></pre>
<p>示例:</p>
<pre><code class="language-js">function calcAdd(nFigure1, nFigure2) {
let nRs = nFigure1 + nFigure2;
alert(nRs);
return nRs;
}
let nCount = calcAdd(3, 4);
alert(nCount);
</code></pre>
<h3 id="变量作用域">变量作用域</h3>
<p>js 变量分为全局变量和局部变量,局部变量优先全局变量<br>
如果全局变量和局部变量重名,在函数内使用的是局部变量(形成遮蔽),在函数外使用的是全局变量</p>
<pre><code class="language-js">//局部变量
function fnMyalert() {
let b = 20;
alert(b);
}
fnMyalert();
alert(b);
//全局变量
let c = 22;
function fnYouralert() {
c++;
}
fnYouralert();
alert(c);
</code></pre>
<h3 id="传入参数和返回值">传入参数和返回值</h3>
<pre><code class="language-js">function calcAdd(nFigure1, nFigure2 = "abc") {
// 设置形参,接收传入的参数
// 设置默认参数,这里可以是另外的函数(当第二个参数没传入时,才会执行,如果传入参数则不会执行)

return nFigure1 + nFigure2; // 返回值,将计算结果返回,函数立即停止并返回内容,若果没有return则返回undefined
}
</code></pre>
<h3 id="es6-箭头函数">ES6 箭头函数</h3>
<pre><code class="language-js">let func = () =&gt; ...body...;
let func1 = n =&gt; ...body...;
let func2 = (n, m) =&gt; {
...body...;
return n*m
};
()=&gt;...body...;
// 等同于
let func = function () {
...body...;
}
let func1 = function (n) {
...body...;
}
let func2 = function (n,m) {
...body...;
return n*m
}
function(){
...body...;
}
</code></pre>
<h3 id="浏览器调试方法">浏览器调试方法</h3>
<p>F12 开启开发者工具<br>
在“控制台”输入代码,可以实时查看代码运行结果。<br>
在“代码来源”处添加 js 文件,可进行断点调试。<br>
在代码文件当中添加<code>debugger;</code>,可进行断点调试。执行到此时会自动暂停。<br>
<img src="https://img2024.cnblogs.com/blog/3286006/202508/3286006-20250818190302099-771886945.png" alt="image" loading="lazy"></p>
<p>在“控制台”使用<code>console.log()</code>代码可以输出内容</p>
<h3 id="函数测试">函数测试</h3>
<p>使用 Mocha 进行函数测试</p>
<pre><code class="language-js">function pow(x, n) {
return x ** n;
}
describe("pow", function () {
it("pow(2,3) should return 8", function () {
    // 一个it最好只使用一个断言
    assert.equal(pow(2, 3), 8); // 这里代码就叫做断言,如果pow(2,3)不等于8,则测试失败
});
it("pow(3,4) should return 81", function () {
    // 通常使用循环创建多个it进行测试通用性
    assert.equal(pow(3, 4), 81);
});
});
</code></pre>
<p>示例写法</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;!-- add mocha css, to show results --&gt;
    &lt;link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/mocha/3.2.0/mocha.css"
    /&gt;
    &lt;!-- add mocha framework code --&gt;
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/3.2.0/mocha.js"&gt;&lt;/script&gt;
    &lt;script&gt;
      mocha.setup("bdd"); // minimal setup
    &lt;/script&gt;
    &lt;!-- add chai --&gt;
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.5.0/chai.js"&gt;&lt;/script&gt;
    &lt;script&gt;
      // chai has a lot of stuff, let's make assert global
      let assert = chai.assert;
    &lt;/script&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;script&gt;
      function pow(x, n) {
      return x ** n; // using exponentiation operator
      /* function code is to be written, empty now */
      }
    &lt;/script&gt;

    &lt;!-- the script with tests (describe, it...) --&gt;
    &lt;!-- &lt;script src="../js/test.js"&gt;&lt;/script&gt; --&gt;
    &lt;!-- 文件当中的内容如下所示 --&gt;
    &lt;script&gt;
      describe("pow", function () {
      it("raises to n-th power", function () {
          assert.equal(pow(2, 3), 8);
      });
      });
    &lt;/script&gt;

    &lt;!-- the element with id="mocha" will contain test results --&gt;
    &lt;div id="mocha"&gt;&lt;/div&gt;

    &lt;!-- run tests! --&gt;
    &lt;script&gt;
      mocha.run();
    &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<h2 id="对象">对象</h2>
<p>使用对象可以存储数据,对象中的数据叫做属性,属性名和属性值用冒号分隔,多个属性之间用逗号分隔。</p>
<h3 id="对象的写法">对象的写法</h3>
<ol>
<li>通用写法</li>
</ol>
<pre><code class="language-js">// 字面量写法
let user = {};
// 构造函数写法
let user = new Object();

let user = {
// 一个对象,对象如果是纯数字会自动正向排序,否则按照添加时间排序。纯数字前加`+`将取消自动排序
name: "jojo", // 属性名(所有的属性名都会被转换成str类型):属性值
age: 18,
};
user.city = "shanghai"; // 添加属性
alert(user.name); // 读取属性
delete user.name; // 删除属性
</code></pre>
<ol start="2">
<li>使用方括号来加强属性名</li>
</ol>
<pre><code class="language-js">let user = {};
user["likes birds"] = true;
alert(user["likes birds"]); // true

let key = prompt("你想了解点什么", "Online");
user["user " + key] = true; // user["user Online"] = true;
alert(user["user " + key]);
</code></pre>
<ol start="3">
<li>若在函数中使用同名形参传递,则在对象处可简写</li>
</ol>
<pre><code class="language-js">function makeUser(name, age) {
return {
    name, // 相等于name:name
    age, // 相等于age:age
};
}
</code></pre>
<ol start="4">
<li>特殊 key<code>__proto__</code>这个 key 只能设置是对象的值</li>
</ol>
<pre><code class="language-js">let obj = {};
obj.__proto__ = 5; // __proto__ 是一个特殊属性
alert(obj.__proto__); //
</code></pre>
<ol start="5">
<li>文档注释对象标签</li>
</ol>
<pre><code class="language-js">/** 用户对象
* @typedef {object} User
* @property {number} id - 用户ID
* @property {string} name - 用户名
*/

/**获取用户信息
* @param {number} userId - 用户ID
* @returns {User} - 返回用户对象
*/
function getUserInfo(userId) {
return {
    id: userId,
    name: "jojo",
};
}
getUserInfo(123);
</code></pre>
<ol start="6">
<li>在对象当中创建函数</li>
</ol>
<pre><code class="language-js">// 第一种在对象当中创建函数的方法
let user = {
name : "jojo",
age : 18,
}
function sayHi(){
console.log("Hello, world!");
}
user.sayHi = sayHi; // 将sayHi函数添加到user对象当中
user.sayHi(); // 调用执行user对象当中添加的sayHi函数

// 第二种在对象当中创建函数的方法
let user = {
name = "jojo",
age = 18,
sayHi: function(){ // 在对象当中创建函数,并使用一个名称来指向这个函数
    alert("Hello, world!");
},
sayHi1(){ // 直接创建一个指向sayHi函数的名称,不能重名
    alert("Hello, world!");
}
}
</code></pre>
<h3 id="对象的in方法">对象的<code>in</code>方法</h3>
<p><code>in</code>查询属性是否存在,<code>for... in...</code>循环遍历属性</p>
<pre><code class="language-js">let obj = { test: NaN, test2: 1 };
alert("test" in obj); // true
for (let key in obj) {
alert(key); // 得到key值 test test2
alert(obj); // 得到value值 NaN 1
}
</code></pre>
<h3 id="浅拷贝和深拷贝">浅拷贝和深拷贝</h3>
<pre><code class="language-js">let user1 = {
name: "jojo1",
sizes: {
    height: 182,
    width: 50,
},
};
let user2 = { name: "jojo2" };

// 引用,使用另一个名称引用同一个对象。
let admin = user1; // admin和user指向同一个对象,修改admin会修改user
admin.name = "peter";
alert(user1.name); // 'peter'

// 合并,将两个对象合并成一个,覆盖相同的属性。
Object.assign(user1, user2); // admin和user指向不同的对象,修改admin不会修改user
alert(user1); // user2不改变,user1变为{ name: 'jojo2', sizes: { height: 182, width: 50 } }

// 浅拷贝
// 方案1
let clone = {};
for (let key in user1) {
clone = user1;
}
clone.name = "jojo3"; // 不影响user1;
clone.sizes.wight = 60; // 影响 user1;
// 方案2
let clone1 = Object.assign({}, user1); // 完全拷贝只对一层有效,其他层级还是引用
clone1.name = "jojo4"; // 不影响user1和clone
clone1.sizes.wight = 60; // 影响 user1和clone

// 多层深拷贝
// 方案1
let deepclone = JSON.parse(JSON.stringify(user1)); // 使用JSON.stringify将对象转换成字符串,再使用JSON.parse将字符串转换成对象
// 方案2
import _ from "lodash";
let deepclone2 = _.cloneDeep(user1); // 使用lodash库
</code></pre>
<h3 id="对象的回收">对象的回收</h3>
<p>当对象没有任何引用时,会被垃圾回收机制回收.<br>
对象变为不可达状态后被回收,主要是从根开始的不可达。</p>
<h3 id="对象的this方法">对象的<code>this</code>方法</h3>
<p>当需要在对象内的函数中引用对象中的一些属性时,可以使用 <code>this</code> 关键字来引用对象</p>
<pre><code class="language-js">let user = {
name: "jojo",
age: 18,
sayHi: function sayHi() {
    alert(this.name); // 使用this来引用对象中的属性,这里的this指向User对象
},
};
user.sayHi(); // jojo

// 简写
let user = {
name: "jojo",
age: 18,
sayHi() {
    alert(this.name); // 使用this来引用对象中的属性,这里的this指向User对象
},
};
</code></pre>
<p>函数内部都可以使用<code>this</code>关键字来引用一些属性,这个值是计算出来的,不同的对象当中得到的结果不同</p>
<pre><code class="language-js">function SayHi() {
// 先定义函数
console.log(this.name); // 使用this来引用对象中的属性,这个值是计算出来的,不同的对象当中得到的结果不同
}
let User = { name: "jojo" }; // 创建对象
let Admin = { name: "peter" }; // 创建对象
User.func = sayHi; // 将函数添加到对象当中,函数当中的this指向User对象
Admin.func = sayHi; // 将函数添加到对象当中,函数当中的this指向Admin对象
User.func(); // jojo
Admin.func(); // peter
// 在全局当中使用this,则指向window对象,如果使用严格模式则this指向undefined
console.log(this.name); // 这里的this指向window对象(window对象是全局对象)。如果使用严格模式,则this指向undefined
</code></pre>
<h3 id="对象的new方法">对象的<code>new</code>方法</h3>
<p>使用<code>new</code>方法需要先声明构造函数,然后再使用<code>new</code>方法进行实例化。<br>
构造函数起名通常使用大驼峰命名法(UserInfo),构造函数中的<code>this</code>指向实例化的对象。</p>
<ol>
<li>第一种构造函数,使用<code>new</code>方法,不推荐使用</li>
</ol>
<pre><code class="language-js">function User(name, age) {
// 声明一个构造函数,
this.name = name;
this.age = age;
this.sayHi = function () {
    console.log("Hi" + this.age + this.name);
};
}

let user = new User("jj", 18); // 使用new方法进行实例化
let user1 = new User("jj1", 18); // 使用new方法进行实例化
user.sayHi(); // Hi18jj
user1.sayHi(); // Hi18jj1
</code></pre>
<ol start="2">
<li>第二种构造函数,使用<code>new</code>方法,更好的做法</li>
</ol>
<pre><code class="language-js">function User(name, age) {
this.name = name;
this.age = age;
}
User.prototype.sayHi = function () {
console.log("Hi" + this.age + this.name);
};

let user = new User("jj", 18); // 使用new方法进行实例化
user.sayHi(); // Hi18jj
</code></pre>
<ol start="3">
<li>通过顶级 Object 类型来实例化一个对象,通过对象字面量创建对象。</li>
</ol>
<pre><code class="language-js">// Object类来实例对象,相当于创建一次性的构造函数,并直接实例化
let oCar = new Object();
oCar.brand = "Benz";
oCar.number = "00001";
oCar.speed = 200;
oCar.driver = function () {
console.log(this.brand, this.number, this.speed);
};
console.log(oCar.number);
oCar.driver();
//字面量
let oTom = {
name: "tom",
age: "20",
sing: function () {
    console.log(this.name + this.age);
},
};
console.log("name" + oTom.name);
oTom.sing();
</code></pre>
<ol start="4">
<li>第三种构造函数,使用<code>new</code>方法,新语法是第二种的语法糖。</li>
</ol>
<pre><code class="language-js">class User {
constructor(name, age) {
    this.name = name;
    this.age = age;
}
sayHi() {
    console.log("Hi" + this.age + this.name);
}
}

let user = new User("jj", 18); // 使用new方法进行实例化
user.sayHi(); // Hi18jj
</code></pre>
<h3 id="对象的选择">对象的<code>?.</code>选择</h3>
<p><code>?.</code>这样的语法,可以选择对象当中可能不存在的属性,但选择的对象是必须要声明的。<br>
<code>?.()</code>这是选择调用一个可能不存在的函数。<br>
<code>?.[]</code>读取一个可能不存在的属性。更为安全的读取。<br>
这些符号也可以用以<code>delete</code>关键字之后,删除一个可能不存在的属性。存在则删除,不存在则不改变。<br>
但是这些符号不能用于写入。</p>
<pre><code class="language-js">obj?.prop; // 如果obj存在,则返回obj.prop,否则返回undefined
obj?.; // 如果obj存在,则返回obj,否则返回undefined
obj?.method(); // 如果obj存在,则调用obj.method(),否则返回undefined
delete obj?.prop; // 如果obj存在,则删除obj.prop,否则不改变obj
</code></pre>
<h3 id="symbol类型"><code>Symbol</code>类型</h3>
<ol>
<li><code>Symbol</code>类型和<code>string</code>类型可作为对象属性键。</li>
</ol>
<pre><code class="language-js">let user = {
name: "jojo", // 对象字面量方法,使用string类型作为属性键
: 1, // 对象字面量方法,使用Symbol类型作为属性键
};
let user1 = {
name: "jojo",
id: 1, // 这里是string类型的key,和后续创建的Symbol类型的key重复,但不冲突
};
let id = Symbol("id"); // 将id定义为symbol类型,并给予一个描述叫id
user1 = 2; // 使用symbol类型作为属性键
console.log(user1); // 2,使用symbol类型作为属性键
console.log(user1.id); // 1,使用string类型作为属性键
</code></pre>
<ol start="2">
<li><code>Symbol</code>类型是唯一值,即使两个<code>Symbol</code>类型描述相同,也是不同的值。</li>
</ol>
<pre><code class="language-js">let id1 = Symbol("id");
let id2 = Symbol("id");
console.log(id1 == id2); // false,即使描述相同,也是不同的值
</code></pre>
<ol start="3">
<li><code>Symbol</code>类型不能自动转换成<code>string</code>类型,需要使用<code>toString()</code>进行。</li>
<li><code>Symbol</code>类型使用<code>Symbol.description</code>显示描述。</li>
</ol>
<pre><code class="language-js">let id = Symbol("id");
console.log(id); // error
console.log(id.toString()); // Symbol(id),将symbol类型转换成string类型
console.log(id.description); // id,显示symbol类型的描述
</code></pre>
<ol start="5">
<li><code>Symbol</code>类型可以创建隐藏属性,防止被意外读取。</li>
<li><code>Symbol</code>类型不能使用<code>for...in</code>循环遍历。</li>
</ol>
<pre><code class="language-js">let user = {
name: "jojo",
}; // 这是在其他代码当中引用的

let id = Symbol("id");
user = 1;

console.log(user); // 1
console.log(user.id); // undefined,因为id是symbol类型,不能自动转换成string类型,所以不能使用点语法来访问

for (let key in user) {
console.log(key); // name,因为id是symbol类型,不能使用for...in循环遍历
}
</code></pre>
<ol start="7">
<li>全局<code>Symbol</code>类型,使用<code>Symbol.for()</code>创建,使用<code>Symbol.keyFor()</code>获取。</li>
</ol>
<pre><code class="language-js">// 从全局注册表中读取,按给定的描述返回Symbol。
let id = Symbol.for("idaa"); // 如果该Symbol不存在则创建
let idAgain = Symbol.for("idaa"); // 获取这个全局Symbol
console.log(id == idAgain); // true

consoloe.log(Symbol.keyFor(id)); //idaa,按找给定的Symbol,返回描述
</code></pre>
<h3 id="对象的转换">对象的转换</h3>
<ol>
<li>对象不会自动转换为布尔类型,若主动转换成布尔类型,都是 true</li>
<li>转为数字类型发生在对象相减或者应用数学函数时,例如,Date 对象相减会得到两个日期之间的差值</li>
<li>转为字符串通常发生在诸如 alert(obj)或者对象属性键这种输出函数中</li>
</ol>
<h4 id="使用-hint-进行自定义转换">使用 hint 进行自定义转换</h4>
<p><code>hint</code>有三种取值<code>String</code>、<code>Numbre</code>、<code>Default</code></p>
<pre><code class="language-js">//String取值通常发生在(输出,将对象作为属性键)
alert(obj);
console.log(obj);
Obj = 123;
//Number取值通常发生在(显示转换,数学运算(除了二元加法),大于/小于比较)
let num = Number(obj);
let x = +obj;
let delta = data1 - data2;
let greater = num1 &gt; num2; // 这里是因为历史原因使用的是Number
//Default取值通常发生在(二元加法,与字符串、数字或Symbol进行==比较)
let total = obj1 + obj2;
if (user == 1){...};
</code></pre>
<p>然后根据<code>hint</code>得到的值,就可以自定义转换,调用的函数是<code>(hint)</code>.通常调用的顺序是</p>
<blockquote>
<ol>
<li>尝试调用<code>obj(hint)</code>,如果定义了则改变,否则下延。</li>
<li>若<code>hint</code>是<code>String</code>,尝试调用<code>obj.toString()</code>或<code>obj.valueOf()</code>,那个存在调用那个</li>
<li>若<code>hint</code>是<code>Number</code>或<code>Default</code>,尝试调用<code>obj.valueOf()</code>或<code>obj.toString()</code>,那个存在调用那个</li>
</ol>
</blockquote>
<pre><code class="language-js">// obj(hint)使用方法
obj(hint) = function(hint){
// hint取值有三种,String,Number,Default
// 必须返回一个原始值(string,number,bigin,boolean,symbol,null,undefined)
}
let user = {
name: "John",
money: 1000,

(hint) {
    console.log(`hint: ${hint}`);
    return hint == "string" ? `{name: "${this.name}"}` : this.money; // 根据hint的值,返回不同的值,string返回this.name,number和default返回this.money
},
}
console.log(user); // hint: string -&gt; {name: "John"}
console.log(+user); // hint: number - &gt; 1000
console.log(user + 500); // hint: default - &gt; 1500
</code></pre>
<pre><code class="language-js">// obj.toString()和obj.valueOf()使用方法
// 如果hint是String,则优先调用toString(),然后再用valueOf()
// 如果hint是Number或Default,则优先调用valueOf(),然后再用toString()
let user = {
name: "John",
money: 1000,

// 对于hint="string"
toString() { // 相对来说比较全能
    return `{name: "${this.name}"}`;
}
// 对于hint="number"或"default"
valueOf() {
    return this.money;
}
};
console.log(user); // hint: string -&gt; toString -&gt; {name: "John"}
console.log(+user); // hint: number -&gt; valueOf -&gt; 1000
console.log(user + 500); // hint: default -&gt; valueOf -&gt; 1500
</code></pre>
<h2 id="数据类型的使用">数据类型的使用</h2>
<p>在 JS 中原始类型有七种:<code>string</code>、<code>number</code>、<code>bigint</code>、<code>boolean</code>、<code>undefined</code>、<code>symbol</code>、<code>null</code>。<br>
这些原始类型可以被当作对象来做一些方法,但这并不是真正的对象,我们不能给这些原始类型添加属性。</p>
<h3 id="数字类型的使用">数字类型的使用</h3>
<ol>
<li>分割数字,使用<code>_</code>进行分割,例如<code>let num = 1_000_000_000;</code>。</li>
<li>科学计数法,使用<code>e</code>进行科学计数法,例如<code>let num = 1e3;// 1e3 = 1000</code>。</li>
<li>二进制、八进制和十六进制,使用<code>0b</code>、<code>0o</code>、<code>0x</code>进行表示,例如<code>let num = 0b1111;0o377;0xff</code>。</li>
<li>数字进制转换,使用<code>toString(base)</code>进行转换<code>base=2~36</code>,例如<code>let num = 255;num.toString(2) // 1111_1111</code>和<code>123456..toString(36); // 2n9c</code>使用两个<code>.</code>调用。</li>
<li>舍入,使用<code>Math.round()</code>进行四舍五入,使用<code>Math.ceil()</code>向上舍入,使用<code>Math.floor()</code>向下舍入,使用<code>Math.trunc()</code>去掉小数部分,使用<code>Math.toFixed(n)</code>将数字舍入到指定的小数位数,返回字符串。</li>
<li>是否为正确的数字,使用<code>Number.isFinite()</code>判断是否为有限数字,使用<code>Number.isNaN()</code>判断是否为<code>NaN</code>,使用<code>Number.isInteger()</code>判断是否为整数。</li>
<li>数字转换,使用<code>parseInt(str,radix)</code>从左向右读取字符串转换为整数直到非数字出现(可设置进制),使用<code>parseFloat(str)</code>从左向右读取字符串转换为浮点数直到除第一个<code>.</code>后的非数字出现,使用<code>Number()</code>将其他类型转换为数字。</li>
<li>更多内置 Math 对象文档</li>
</ol>
<h3 id="字符串类型的使用">字符串类型的使用</h3>
<ol>
<li>字符串的引号,使用单引号、双引号、反引号(模板字符串)。</li>
</ol>
<pre><code class="language-js">function myTag(strings, personExp, ageExp) {
let str0 = strings;
let str1 = strings;
let str2 = strings;

let ageStr = ageExp &gt; 17 ? "adult" : "child";
return `${str0}${personExp}${str1}${ageStr}${str2}`;
}
const output = myTag`Hello,${person}! You are ${age}.`;
let age = +prompt("age", 18);
let person = prompt("person", "jojo");

console.log(output); // Hello,jojo! You are adult.
</code></pre>
<ol start="2">
<li>特殊符号,使用<code>\</code>进行转义,例如<code>\n</code>换行,<code>\t</code>制表符,<code>\b</code>退格符,<code>\r</code>回车符,<code>\f</code>换页符,<code>\v</code>垂直制表符,<code>\\</code>反斜杠,<code>\'</code>单引号,<code>\"</code>双引号,<code>\x</code>十六进制,<code>\u</code> Unicode。</li>
<li>字符串的长度,使用<code>str.length</code>获取字符串长度。</li>
<li>访问字符,使用<code>str</code>获取字符串第<code>i</code>个字符,使用<code>str.charAt(i)</code>获取字符串第<code>i</code>个字符,使用<code>str.charCodeAt(i)</code>获取字符串第<code>i</code>个字符的 Unicode 编码。这里不能单独赋值(字符串不可变)</li>
<li>字符串大小写转换,使用<code>str.toUpperCase()</code>将字符串转换为大写,使用<code>str.toLowerCase()</code>将字符串转换为小写。</li>
<li>字符串查找</li>
</ol>
<pre><code class="language-js">// str.indexOf(substr,pos)从左向右和str.lastIndexOf(substr,pos)从右向左,找到一次就返回。
let str = "Hello, world!";
str.indexOf("Hello"); // 0
if (~str.indexOf("world")) {
// ~-1 = 0
// ~0 = -1
// ~1 = -2
}
// str.includes(substr,pos)从左向右、str.startsWith(substr,pos)从右向左、str.endsWith(substr,pos)找到一次就返回true。
</code></pre>
<ol start="7">
<li>字符串截取
<ul>
<li><code>str.slice(start,end)</code>,<code>start</code>为开始位置,<code>end</code>为结束位置,<code>start</code>和<code>end</code>可以为负数,<code>start</code>为负数表示从后往前数,<code>end</code>为负数(或空)表示截取到字符串末尾,<code>start</code>大于<code>end</code>则返回空字符串。</li>
<li><code>str.substring(start,end)</code>,<code>start</code>为开始位置,<code>end</code>为结束位置,<code>start</code>和<code>end</code>不为负数,<code>start</code>大于<code>end</code>则调换<code>start</code>和<code>end</code>位置。</li>
<li><code>str.substr(start,length)</code>,<code>start</code>为开始位置,<code>length</code>为截取长度,<code>start</code>可为负数表示从后往前数。</li>
</ul>
</li>
<li>字符串的 UTF-16 编码,使用<code>str.codePointAt(pos)</code>获取字符串第<code>pos</code>个字符的 UTF-16 编码,使用<code>String.fromCodePoint(code)</code>将 UTF-16 编码转换为字符串。</li>
</ol>
<h3 id="数组操作方法">数组操作方法</h3>
<ol>
<li>声明数组</li>
</ol>
<pre><code class="language-js">let lA = new Array(1, 2, 3);

let lA2 = ;

let lA3 = [ // 数组可以嵌套,可存储任意类型
,
["a", "b", "c"],
{name:"jojo"}, // console.log(lA3.name); // jojo
function (){console.log("asd")}, // lA3(); // asd
];

let lA2 = 4; // 修改数组元素
let lA = 4; // 数组添加元素
console.log(lA.length); // 数组长度 4,自动更细,可写(arr.length=0清空数组)
console.log(lA2); // 显示整个数组
console.log(lA.at(-1)); // 获取数组最后一个元素 4
</code></pre>
<ol start="2">
<li>队列/栈操作(unshift,shift,push,pop)</li>
</ol>
<pre><code class="language-js">let lA = ;

// 队列操作
lA.unshift(0); //从最前面进行插入
console.log(lA); //
console.log(lA.shift()); //删除第一个
console.log(lA); //

// 栈操作
lA.push(5); //从最后进行插入
console.log(lA); //
console.log(lA.pop()); //删除最后一个
console.log(lA); //
</code></pre>
<ol start="3">
<li>数组的遍历(for,for in,for of,forEach,reduce,reduceRight)</li>
</ol>
<pre><code class="language-js">let lA = ;

//for循环遍历
for (let i = 0; i &lt; lA.length; i++) {
console.log(lA);
}

//for循环变形
for (let n in lA) {
console.log(n);
}

//for循环变形
for (let n of lA) {
console.log(n);
}

// arr.forEach(function (element, index, array) {...}); // arr指代数组,function指对数组元素进行操作的函数,element指数组元素,index指数组元素下标,array指数组
let lA = ;
lA.forEach(function (element, index, array) {
// 只是创建一个可遍历数组的函数,不对数组内容修改
console.log(`${element} is at index ${index} in ${array}`);
});
// 0 is at index 0 in 0,1,2,3,4,5,6,7,8,9
// 1 is at index 1 in 0,1,2,3,4,5,6,7,8,9
// 2 is at index 2 in 0,1,2,3,4,5,6,7,8,9

// arr.reduce(function (accumulator, currentValue, currentIndex, array) {...}, initialValue); // arr指代数组,function指对数组元素进行操作的函数,accumulator指累加器,currentValue指数组元素,currentIndex指数组元素下标,array指数组,initialValue指累加器初始值
let lA = ;
let lA2 = lA.reduce(function (accumulator, currentValue, currentIndex, array) {
// 1. accumulator=0, currentValue=0, currentIndex=0, array=0,1,2,3,4,5,6,7,8,9
// 2. accumulator=0, currentValue=1, currentIndex=1, array=0,1,2,3,4,5,6,7,8,9
// 3. accumulator=1, currentValue=2, currentIndex=2, array=0,1,2,3,4,5,6,7,8,9
return accumulator + currentValue;
}, 0);
</code></pre>
<ol start="4">
<li>数组的<code>toString</code>方法</li>
</ol>
<pre><code class="language-js">let lA = ;

console.log(lA.toString()); // 1,2,3,4,5,6,7,8,9
console.log(lA + 1); // 1,2,3,4,5,6,7,8,91
</code></pre>
<ol start="5">
<li>根据下标添加和删除元素(splice,slice,concat)</li>
</ol>
<pre><code class="language-js">// arr.splice(start,num,element1,...,elementN);
// arr指代数组,star指代要对数组开始操作的元素下标,num指要对多少元素进行操作,elementN指修改后或被添加的元素
let lA = ;
// 删除操作
lA.splice(3, 3); // 删除,从下标3开始删除三个元素
console.log(lA); //
// 插入操作
lA.splice(3, 0, 33); // 插入,从下标3插入一个33,元素数据向后移动
console.log(lA); //
// 插入多个数据
lA.splice(3, 0, 44, 55, 66); // 插入多个,原本元素向后移动
console.log(lA); //
// 替换操作
lA.splice(3, 1, 333); // 替换,从下标3替换一个元素,其他元素不变
console.log(lA); //
// 替换多个数据
lA.splice(3, 2, 333, 444, 555); // 替换多个,可一部分替换一部分插入
console.log(lA); //

// arr.slice(start,end); // arr指代数组,star指代要对数组开始操作的元素下标,end指要对数组结束操作的元素下标,返回一个新数组
let lA = ;
let lA2 = lA.slice(3, 6); // 截取,从下标3开始截取到下标6,不包含下标6,返回一个新数组
console.log(lA2); //

// arr.concat(element1,...,elementN); // arr指代数组,elementN指要添加的元素,返回一个新数组
let lA = ;
let lA2 = lA.concat(10, 11, 12); // 拼接,将10,11,12添加到lA数组后面,返回一个新数组
console.log(lA2); //
</code></pre>
<ol start="6">
<li>数组的搜索(indexOf,lastIndexOf,includes,find,findIndex,findLastIndex,filter)</li>
</ol>
<pre><code class="language-js">// arr.indexOf(item, from); // arr指代数组,item指要搜索的元素,from指从哪个下标开始搜索,返回元素下标,没有找到返回-1
let lA = ;
console.log(lA.indexOf(3)); // 3

// arr.includes(item, from); // arr指代数组,item指要搜索的元素,from指从哪个下标开始搜索,返回布尔值,可以正确处理NaN数据。
let lA = ;
console.log(lA.includes(3)); // true

// arr.find(function(element, index, array){}); // arr指代数组,function指对数组元素进行操作的函数,element指数组元素,index指数组元素下标,array指数组,返回找到的元素,没有找到返回undefined
let lA = ;
let lA2 = lA.find(function (element, index, array) {
return element &gt; 5;
});
console.log(lA2); // 6
let lA3 = lA.find((item) =&gt; item &gt; 5);
console.log(lA3); // 6

// arr.filter(function(element, index, array){}); // arr指代数组,function指对数组元素进行操作的函数,element指数组元素,index指数组元素下标,array指数组,返回一个新数组,新数组为原数组中满足条件的元素
let lA = ;
let lA2 = lA.filter(function (element, index, array) {
return element &gt; 5;
});
console.log(lA2); //
let lA3 = lA.filter((item) =&gt; item &gt; 5);
console.log(lA3); //
</code></pre>
<ol start="7">
<li>转换数组(map,sort,reverse,split,join)</li>
</ol>
<pre><code class="language-js">//arr.map(function(element, index, array){}); // arr指代数组,function指对数组元素进行操作的函数,element指数组元素,index指数组元素下标,array指数组,返回一个新数组,新数组为原数组中满足条件的元素
let lA = ;
let lA2 = lA.map(function (element, index, array) {
return element * 2;
});
console.log(lA2); //
let lA3 = lA.map((item) =&gt; item * 2);
console.log(lA3); //

// arr.sort(function(a, b){}); // arr指代数组,function指对数组元素进行操作的函数,a,b指数组元素,计算得到的值用于排序,正值则不变,负值则交换。返回一个新数组但通常省略,原数组会改变。
let lA = ;
let lA2 = lA.sort(function (a, b) {
return a - b;
});
console.log(lA2); //
let lA3 = lA.sort((a, b) =&gt; a - b);
console.log(lA3); //

// arr.reverse(); // arr指代数组,返回一个新数组,原数组会改变。
let lA = ;
let lA2 = lA.reverse();
console.log(lA2); //

// str.split(separator, limit); // str指代字符串,separator指分隔符,limit指返回的数组最大长度,返回一个数组
let str = "a,b,c,d,e,f,g,h,i,j";
let arr = str.split(",", 5);
console.log(arr); // ["a", "b", "c", "d", "e"]

// arr.join(separator); // arr指代数组,separator指分隔符,返回一个字符串
let arr = ["a", "b", "c", "d", "e"];
let str = arr.join(",");
console.log(str); // "a,b,c,d,e"
</code></pre>
<ol start="8">
<li>数组的判断(isArray,instanceof)</li>
</ol>
<pre><code class="language-js">let lA = ;
console.log(Array.isArray(lA)); // true
console.log(lA instanceof Array); // true
</code></pre>
<h4 id="特别注意">特别注意</h4>
<p>上述操作大多数都可以在末尾添加<code>thisArg</code>,可以将定义的函数的<code>this</code>值改变为<code>thisArg</code>的值,例如:</p>
<pre><code class="language-js">let army = {
minAge: 18,
maxAge: 27,
canJoin: function (user) {
    return user.age &gt;= this.minAge &amp;&amp; user.age &lt;= this.maxAge;
},
};
let users = [{ age: 16 }, { age: 20 }, { age: 23 }, { age: 30 }];
let armyCanJoin = users.filter(army.canJoin, army);
console.log(armyCanJoin.length); // 2
console.log(armyCanJoin); // [{ age: 20 }, { age: 23 }]
console.log(armyCanJoin.age); // 20
</code></pre>
<h3 id="可迭代对象">可迭代对象</h3>
<p>可迭代对象,都具有<code>Symbol.iterator</code>属性,因此在对象当中添加<code>Symbol.iterator</code>属性,就可以让对象成为可迭代对象。<br>
对于<code>for of</code>循环启动时都需要调用<code>Symbol.iterator</code>方法。这个方法必须返回一个<code>next</code>方法的对象。</p>
<p>对于字符串、数组、Map、Set、arguments 对象、NodeList 对象这些都是内置可迭代对象,不需要自己添加<code>Symbol.iterator</code>。</p>
<pre><code class="language-js">let range = { // 创建一个对象
from: 1,
to: 5,
};
// 在对象当中添加Symbol.iteration属性,让对象成为可迭代对象。
// for of 方法会调用这个对象的 Symbol.iterator 方法
range = function () { // 返回迭代器对象(iterator object)
// for of 仅与下面的迭代器对象一起工作,需要提供一下个值
return { // 这里重新创建了一个对象,一个可以迭代的对象
    current: this.from,
    last: this.to,
    // for of 的每轮循环迭代中都会调用 next 方法
    next() { // next 方法是在Symbol.iterator方法中的,range对象自身没有。
      if (this.current &lt;= this.last) {
      // 返回{done:..., value:...}格式的对象
      return { done: false, value: this.current++ };
      } else {
      return { done: true };
      }
    },
};
};
// 迭代器对象和与其进行迭代的对象是分开的。
for (let num of range) {
console.log(num); // 1 2 3 4 5
}

/////////第二种实现方法
// 将range自身作为迭代器,将next方法定义在range对象当中。
let range = {
from: 1,
to: 5,
() {
    this.current = this.from;
    return this; // 这里直接返回自身即可,因为自身是一个可迭代的对象
}
next() {
    if (this.current &lt;= this.to) {
      return { done: false, value: this.current++ };
    }else{
      return { done: true };
    }
}
};
for (let num of range) {
console.log(num); // 1 2 3 4 5
}
</code></pre>
<p>对于可迭代对象,可以直接显示调用<code>Symbole.iterator</code>方法</p>
<pre><code class="language-js">let str = "hello";
// 等同于for (let char of str) console.log(char);
let iterator = str();
while (true) {
let result = iterator.next();
if (result.done) break;
console.log(result.value);
} // h e l l o
</code></pre>
<p>可迭代(iterable)对象和类数组(array-like)对象<br>
可迭代对象:上述自定义或内置的具有<code>Symbole.iterator</code>方法的对象。(上述都是)<br>
类数组对象:具有<code>length</code>属性和索引属性的对象。(下述举例)</p>
<pre><code class="language-js">let arraylike = {
0: "Hello",
1: "World",
length: 2,
};
let arr = Array.from(arraylike);
console.log(arr); // ["Hello", "World"]
console.log(arr.pop()); // World
</code></pre>
<p>当然对于可迭代对象也是可以使用<code>Array.from</code>方法将其转换为数组。</p>
<pre><code class="language-js">let range = {
from: 1,
to: 5,

() {
    this.current = this.from;
    return this;
},

next() {
    if (this.current &lt;= this.to) {
      return { done: false, value: this.current++ };
    } else {
      return { done: true };
    }
},
};
let arr = Array.from(range);
console.log(arr); //
</code></pre>
<p>并且在使用<code>Array.from()</code>时,可以传入第二个参数(一个函数或表达式),用于对每个元素进行处理,返回一个新数组。</p>
<pre><code class="language-js">let str = "𝒳😂";
let arr = Array.from(str, (num) =&gt; num + num);
console.log(arr); // ['𝒳𝒳', '😂😂']
console.log(arr); // 𝒳𝒳
console.log(arr.length); // 2
</code></pre>
<h4 id="注意">注意</h4>
<ol>
<li>可迭代对象需要包含 Symbol.iterator 属性,并且该属性需要是一个函数,该函数返回一个可迭代对象,该对象需要包含 next 方法。</li>
<li>第二种创建方法在出现多个 for of 循环且异步时,会出现共享迭代状态的情况</li>
</ol>
<pre><code class="language-js">// 1. 定义“自己当迭代器”的 range 对象(状态 current 存在自身)
let range = {
from: 1,
to: 5,
current: 1, // 共享状态:所有遍历共用这个 current

// Symbol.iterator 返回 this(自己当迭代器)
() {
    console.log(`[迭代器启动] 重置 current 为 ${this.from}`);
    this.current = this.from; // 每次启动遍历,都会重置 current!
    return this;
},

// next() 操作共享的 current 属性
next() {
    if (this.current &lt;= this.to) {
      const value = this.current;
      console.log(
      ` current = ${
          this.current
      } → 返回 ${value},current 自增为 ${this.current + 1}`
      );
      this.current++;
      return { done: false, value };
    }
    console.log(
      ` current = ${this.current}(超过 to=${this.to})→ 遍历结束`
    );
    return { done: true };
},
};

// 2. 非阻塞暂停函数(用 Promise 包裹 setTimeout,不阻塞主线程)
function sleep(ms) {
return new Promise((resolve) =&gt; setTimeout(resolve, ms));
}

// 3. 第一个遍历:遍历到 2 时暂停,释放主线程
async function firstTraversal() {
console.log("\n=== 第一个遍历开始 ===");
// for...of 会自动调用 range() 和 next()
for await (let num of range) {
    // 用 for await...of 支持异步暂停
    console.log("第一个遍历拿到值:", num);

    // 当第一个遍历拿到 2 时,暂停 100ms(非阻塞,释放主线程)
    if (num === 2) {
      console.log("第一个遍历:拿到 2,暂停 100ms,释放主线程...");
      await sleep(100); // 关键:非阻塞暂停,主线程可执行其他任务
      console.log("第一个遍历:暂停结束,继续执行");
    }
}
console.log("=== 第一个遍历结束 ===");
}

// 4. 第二个遍历:在第一个遍历暂停时启动
function secondTraversal() {
console.log("\n=== 第二个遍历开始 ===");
for (let num of range) {
    // 普通 for...of(同步遍历)
    console.log("第二个遍历拿到值:", num);
}
console.log("=== 第二个遍历结束 ===");
}

// 5. 启动测试:先跑第一个遍历,在它暂停时跑第二个遍历
firstTraversal();
// 第一个遍历启动后,主线程会在“拿到 2 并 await sleep(100)”时释放
// 此时设置一个 50ms 的定时器,确保第二个遍历在第一个遍历暂停期间启动
setTimeout(secondTraversal, 50);
</code></pre>
<h3 id="映射map与集合set">映射(Map)与集合(Set)</h3>
<p>Map 是一个带键的数据项集合,<br>
Set 是一个唯一值的集合。</p>
<pre><code class="language-js">let map = new Map(); // 创建一个 Map 对象
map.set("name", "张三"); // 添加一个键值对,字符串键
map.set(1, "李四"); //数字键
map.set(true, "王五"); // 布尔值键
map.set({ name: "John" }, 123); // 对象键,对象键会被转换为字符串 ""
map.set(null, "null").set(undefined, "undefined"); // null 键 和 undefined 键,可以链式调用
console.log(map.get("name")); // 获取键为"name"的值
console.log(map.has("name")); // 判断是否存在键为"name"的键值对
map.delete("name"); // 删除键为"name"的键值对
console.log(map.size); // 获取键值对的数量
map.clear(); // 清空所有键值对

// Map 的遍历
map.keys(); // 获取所有键的迭代器
map.values(); // 获取所有值的迭代器
map.entries(); // 获取所有键值对的迭代器,在for of循环中默认调用
map.forEach((value, key) =&gt; {
console.log(key, value); // 遍历所有键值对
});

// Map 和对象相互转换
let obj = {
name: "张三",
age: 18,
};
let map = new Map(Object.entries(obj)); // 对象 =&gt; Map
console.log(map); // Map { 'name' =&gt; '张三', 'age' =&gt; 18 }
let map = new Map([
["1", "value1"],
,
,
]);
let prices = Object.fromEntries(map); // Map =&gt; 对象
console.log(prices); // { 1: 'value2', true: 'value3' }
</code></pre>
<pre><code class="language-js">let set = new Set(); // 创建一个 Set 对象
let john = { name: "John" };
let pete = { name: "Pete" };
let mary = { name: "John" };
set.add(john); // 添加一个对象
set.add(pete);
set.add(mary);
set.add(pete); // 再次添加同一个对象
set.add(john);
console.log(set.size); // 3 获取集合的大小,重复不计入
set.delete(mary); // 删除一个对象
set.has(pete); // 判断集合中是否存在某个对象
set.clear(); // 清空集合

// Set 的遍历
set.keys(); // 获取所有键的迭代器
set.values(); // 与 set.keys() 作用相同,这是为了兼容 Map
set.entries(); // 遍历并返回一个包含所有的实体 的可迭代对象,它的存在也是为了兼容 Map
set.forEach((value, key) =&gt; {
console.log(key, value); // 遍历所有键值对
});
</code></pre>
<h4 id="弱映射weakmap和弱集合weakset">弱映射(WeakMap)和弱集合(WeakSet)</h4>
<p>在上述 Map 和 Set 的基础上,取消了对键值对引用的计数,即不会阻止垃圾回收器回收键值对,因此键值对只能是对象,不能是原始类型。<br>
当对象被操作为 null 或对象被删除时,WeakMap 和 WeakSet 中的键值对也会被删除。<br>
这样的设计使得 WeakMap 和 WeakSet 更适合用于存储那些不需要手动删除的键值对。<br>
WeakMap 仅支持<code>get set has delete</code>方法,WeakSet 仅支持<code>add delete has</code>方法。WeakMap 的键必须为对象,WeakSet 的值必须为对象。</p>
<pre><code class="language-js">let weakMap = new WeakMap();
let weakSet = new WeakSet();

let john = { name: "John" };
weakMap.set(john, "..."); // john添加到WeakMap
john = null; // 覆盖引用,john 被从内存中删除了!

john = { name: "John" }; // 重新创建一个对象
weakSet.add(john); // john添加到WeakSet
john = null; // 覆盖引用,john 被从内存中删除了!
</code></pre>
<h4 id="对-object-使用keysvaluesentries方法">对 Object 使用<code>keys,values,entries</code>方法</h4>
<pre><code class="language-js">let user = {
name: "John",
age: 30,
};
console.log(Object.keys(user)); // ["name", "age"]
console.log(Object.values(user)); // ["John", 30]
console.log(Object.entries(user)); // [["name", "John"], ["age", 30]]
</code></pre>
<h3 id="解构赋值">解构赋值</h3>
<pre><code class="language-js">let = ["John", 30]; // 数组解构
console.log(name, age); // John 30

let = ["Julius", "Caesar", "Consul", "Republic"]; // 跳过第二个元素
console.log(title); // Consul

let = "abc"; // 字符串解构
console.log(a, b, c); // a b c

let = ["Jane", "Pete"]; // 交换变量值
= ;
console.log(guest, admin); // Pete Jane

let = ["Julius", "Caesar", "Consul", "Republic"]; // rest 是包含从第三项开始的其余数组项的数组
console.log(rest, rest.length); // ["Consul", "Republic"] 2

let = ["Julius"]; // 默认值
console.log(name); // Julius(来自数组的值)
console.log(surname); // Anonymous(默认值被使用了)

let { height, width, title } = { title: "Menu", height: 200, width: 100 }; // 对象解构, 顺序不重要
console.log(name, age); // John 30

let { name: firstName, age: years } = { name: "John", age: 30 }; // 重命名
console.log(firstName, years); // John 30

let { name: firstName, age: years = 18 } = { name: "John" }; // 默认值
console.log(firstName, years); // John 18

let { name, ...restProps } = { name: "John", age: 30, job: "teacher" }; // restProps 是一个对象,包含除 name 属性之外的所有属性
console.log(restProps); // { age: 30, job: 'teacher' }

// 注意,在js当中{}代表的是代码块,而不是对象,所以解构赋值时,如果{}不在[]内,则会被解析为代码块,而不是对象。
// 所以在解构赋值时,需要将{}放在[]内,表示对象解构。
({ name, age } = { name: "John", age: 30 }); // 使用括号来消除歧义

let options = {
size: {
    width: 100,
    height: 200,
},
items: ["Cake", "Donut"],
extra: true,
};

// 为了清晰起见,解构赋值语句被写成多行的形式
let {
size: {
    // 把 size 赋值到这里
    width,
    height,
},
items: , // 把 items 赋值到这里
title = "Menu", // 在对象中不存在(使用默认值)
} = options; // 这里得到的数据是 width、height、item1、item2 和具有默认值的 title 变量。
console.log(width); // 100
</code></pre>
<p>通常用于函数的参数部分,将形参变为一个对象,传入参数时只需要传入一个对象即可,函数内部则可得到解构完成的实参。</p>
<pre><code class="language-js">function showMenu({
title = "Menu",
width = 200,
height = 100,
items = [],
} = {}) {
// 这里使用多层默认值,防止传入空对象时,解构赋值失败
console.log(`Title: ${title}, W${wight}px, H${height}px`);
console.log(items);
}
let options = { title: "My menu", items: ["Item1", "Item2"] };
showMenu(options); // Title: My menu, W200px, H100px ['Item1', 'Item2']
showMenu(); // Title: Menu, W200px, H100px []
</code></pre>
<h3 id="日期和时间">日期和时间</h3>
<pre><code class="language-js">let now = new Date();
console.log(now); // 星期 月份 日期 年份 时:分:秒 时区 时区描述
// new Date(milliseconds) 时间戳 1234567890123
// new Date(datestring) 格式字符串 2022-01-01
// new Date(year, month, date, hours, minutes, seconds, ms) 多参数
// 在创建时会自动矫正输入错误
let wrongTime = new Date(2013, 0, 32);
console.log(wrongTime); // 2013-02-01

// 可以单独方位年月日时分秒
console.log(now.getFullYear()); // 年
console.log(now.getMonth()); // 月 0-11
console.log(now.getDate()); // 日
console.log(now.getDay()); // 星期 0-6 日-六
console.log(now.getHours()); // 时
console.log(now.getMinutes()); // 分
console.log(now.getSeconds()); // 秒
console.log(now.getMilliseconds()); // 毫秒
console.log(now.getTime()); // 时间戳 console.log(+now);console.log(Date.now());相同
console.log(now.getTimezoneOffset()); // 时区偏移

// 设置年月日时分秒
now.setFullYear(2022);
now.setMonth(0);
now.setDate(1);
now.setHours(0);
now.setMinutes(0);
now.setSeconds(0);
now.setMilliseconds(0);

// 时间加减,不需要考虑闰年的情况,直接加减即可
now.setDate(now.getDate() + 1); // 加一天
now.setMonth(now.getMonth() - 1); // 减一月

// 字符串转换时间戳和日期格式
let ms = Date.parse("2012-01-26T13:51:50.417-07:00");
// YYYY-MM-DDTHH:mm:ss.sss+08:00(东八区)
console.log(ms); // 时间戳
console.log(new Date(ms)); // 日期格式
</code></pre>
<h3 id="json-方法tojson">JSON 方法,toJSON</h3>
<p>为了弥补 toString()方法的麻烦性,JSON 提供了 JSON.stringify(对象转换为 json) 和 JSON.parse(json 转换为对象) 方法。</p>
<p>JSON。stringify 支持<code>Object{...}``Arrays[...]``strings``numbers``boolean values``null</code><br>
不支持<code>functions</code>、存储<code>undefined</code>的属性、<code>Symbol</code>类型的键和值,遇到后直接忽略。<br>
不能有循环引用。可以通过指定格式属性来解决。</p>
<pre><code class="language-js">// JSON.stringify(value, reolacer, spaces);
let student = {
name: "John",
age: 30,
isAdmin: false,
courses: ["html", "css", "js"],
spouse: null,
};

let json = JSON.stringify(student);
console.log(typeof json); // string
console.log(json);
/* JSON 编码的对象:
{
"name": "John",
"age": 30,
"isAdmin": false,
"courses": ["html", "css", "js"],
"spouse": null
}
*/

// toJSON 方法,可以自定义 JSON.stringify() 的行为
let room = {
number: 23,
toJSON() {
    return this.number;
},
};
let meetup = {
title: "Conference",
room,
};
console.log(JSON.stringify(room)); // 23
console.log(JSON.stringify(meetup)); // {"title":"Conference","room":23}

// JSON.parse(value, reviver)
let numbers = "";
numbers = JSON.parse(numbers);
console.log(numbers, typeof numbers); // object
let userData =
'{ "name": "John", "age": 35, "isAdmin": false, "friends": }';

let user = JSON.parse(userData);
console.log(user.friends); // 1

let str = '{"title":"Conference","date":"2017-11-30T12:00:00.000Z"}';

let meetup = JSON.parse(str, function (key, value) {
if (key == "date") return new Date(value);
return value;
});

console.log(meetup.date.getDate()); // 30
</code></pre>
<h1 id="认识-jquery">认识 jQuery</h1>
<p>jQuery 是对 JS 的封装,简化 JS 的编程,作用效果和 JS 一样<br>
当前 jQuery 兼容现在主流浏览器,加快开发效率</p>
<h2 id="jquery-的使用">jQuery 的使用</h2>
<p>jQuery 官网,一般使用旧版本,兼容性更高</p>
<h3 id="jquery-的引用">jQuery 的引用</h3>
<blockquote>
<ul>
<li>将jQuery 下载到本地并引用,使用&lt;script src=''&gt;&lt;\script&gt;标签进行引用</li>
<li>联网引用 jQuery,许多用户在访问其他站点时,已经从其他地方加载过 jQuery。当访问网站时使用别人的文件,会从缓存中加载 jQuery,这样可以减少加载时间。</li>
</ul>
</blockquote>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Document&lt;/title&gt;
    // 引用百度的jQuery
    &lt;script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"&gt;&lt;/script&gt;
    &lt;script&gt;
      // jQuery的ready函数做为入口
      $(document).ready(function () {
      // 在jQuery中如果获取标签对象时,前缀要用一个$
      let $d = $("#d1");
      alert("jquery" + $d);
      });
      //简写法
      $(function () {
      let $d = $("#d1");
      alert("简写" + $d);
      });
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div class="" id="d1"&gt;asd&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<h2 id="jquery-的选择器">jQuery 的选择器</h2>
<p>快速选择标签元素,获取标签元素,选择规则和 css 一样。</p>
<blockquote>
<p>选择器类型</p>
<ul>
<li>标签选择器 $('li')</li>
<li>类选择器 $('.myClass')</li>
<li>id 选择器 $('#myId')</li>
<li>层级选择器 $('#ul1 li span')选择 id 为 ul1 下的所有 li 标签下的 span 标签</li>
<li>属性选择器 $('input')选择 name 属性等于 first 的 input 标签</li>
</ul>
</blockquote>
<p>判断是否选择成功用到.length,如果 lenght 大于 0 表示选择成功。</p>
<pre><code class="language-js">$(function () {
result = $("div").length;
alert(result);
});
</code></pre>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Document&lt;/title&gt;
    &lt;script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"&gt;&lt;/script&gt;
    &lt;script&gt;
      $(function () {
      //标签选择器
      let $mk1 = $("h1");
      $mk1.css({ background: "red" });
      //类选择器
      let $mk2 = $(".mp");
      $mk2.css({ color: "blue" });
      // id选择器
      let $mk3 = $("#d1");
      $mk3.css({ "font-size": "30px" });
      // 层级选择器
      let $mk4 = $("div a");
      $mk4.css({ background: "red" });
      // 属性选择器
      let $mk5 = $("input");
      $mk5.css({ background: "blue" });
      let $mk5 = $("input");
      $mk5.css({ background: "red" });
      });
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;qwe&lt;/h1&gt;
    &lt;p class="mp"&gt;asd&lt;/p&gt;
    &lt;div class="" id="d1"&gt;zxc&lt;/div&gt;
    &lt;div&gt;&lt;a href="www.baiadu.com"&gt;rty&lt;/a&gt;&lt;/div&gt;
    &lt;input type="text" name="" id="" value="fgh" /&gt;
    &lt;input type="password" name="" id="" value="vbn" /&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<h2 id="选择器过滤">选择器过滤</h2>
<p>选择器过滤就是在选择的标签集合中过滤出自己需要的标签</p>
<blockquote>
<ul>
<li>has(选择器名称)方法,选取包含指定选择器的标签</li>
<li>eq(索引)方法,表示选取指定索引的标签</li>
</ul>
</blockquote>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Document&lt;/title&gt;
    &lt;script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"&gt;&lt;/script&gt;
    &lt;script&gt;
      $(function () {
      let $divs = $("div");
      // alert($divs.length);
      console.log($divs);
      // has 过滤
      let $mk1 = $divs.has("p");
      $mk1.css({ background: "red" });
      // last 过滤
      let $mk2 = $divs.last();
      $mk2.css({ background: "blue" });
      // first 过滤
      let $mk3 = $divs.first();
      $mk3.css({ color: "blue" });
      // eq 过滤
      let $mk4 = $divs.eq(1);
      $mk4.css({ color: "pink" });
      });
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div&gt;&lt;p&gt;qwe&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt;asd&lt;/div&gt;
    &lt;div&gt;zxc&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<h2 id="选择器转移">选择器转移</h2>
<p>以某一个选择的标签为参照,获取转移后的标签</p>
<blockquote>
<ul>
<li>$('#box').prev();表示选择 id 是 box 元素的上一个的同级元素</li>
<li>$('#box').prevAll();表示选择 id 是 box 元素的上面所有同级元素</li>
<li>$('#box').next();表示选择 id 是 box 元素的下一个的同级元素</li>
<li>$('#box').nextAll();表示选择 id 是 box 元素的下面所有同级元素</li>
<li>$('#box').parent();表示选择 id 是 box 元素的父元素</li>
<li>$('#box').children();表示选择 id 是 box 元素的所有子元素</li>
<li>$('#box').siblings();表示选择 id 是 box 元素的其他同级元素</li>
<li>$('#box').find(".myClass");表示选择 id 是 box 元素的 class 为 myClass 的元素</li>
</ul>
</blockquote>
<h2 id="设置标签内容">设置标签内容</h2>
<p>jQuery 中 html 方法可以获取和设置标签的 html 内容</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Document&lt;/title&gt;
    &lt;script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"&gt;&lt;/script&gt;
    &lt;script&gt;
      $(function () {
      let $div1 = $("#div1");
      // alert($div1)
      // 获取div当中的内容
      let $mkp = $div1.html();
      alert($mkp);
      // 修改div当中的内容
      $div1.html('&lt;a href="www.baidu.com"&gt;baidu&lt;/a&gt;');
      // 添加div当中的内容
      $div1.append("&lt;hr&gt;");
      $div1.append('&lt;a href="www.baidu.com"&gt;百度&lt;/a&gt;');
      });
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div id="div1"&gt;&lt;p&gt;hello&lt;/p&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<h2 id="设置标签元素属性">设置标签元素属性</h2>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Document&lt;/title&gt;
    &lt;script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"&gt;&lt;/script&gt;
    &lt;script&gt;
      $(function () {
      // 获取对象
      let $inp = $('');
      let $a = $("a");
      // 通过prop()方法获取属性
      $inp.prop({ value: "kkkk", class: "incla" });
      $a.prop({ href: "www.biadu.com" });
      // val方法可以快速获取value值
      alert($inp.val());
      $inp.val("ssss");
      });
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;input type="text" name="username" value="xxx" class="cin" id="inid" /&gt;
    &lt;a&gt;百度&lt;/a&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<h2 id="jquery-事件绑定">jQuery 事件绑定</h2>
<blockquote>
<ul>
<li>click()鼠标单击</li>
<li>blur()元素失去焦点</li>
<li>focus()元素获得焦点</li>
<li>mouseover()鼠标进入(进入子元素也触发)</li>
<li>mouseout()鼠标离开(离开子元素也触发)</li>
<li>ready()DOM 加载完成</li>
</ul>
</blockquote>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Document&lt;/title&gt;
    &lt;script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"&gt;&lt;/script&gt;
    &lt;script&gt;
      $(function () {
      let $div = $("div");
      let $btn = $("#inb");
      let $text = $("#in1");
      let $lis = $("ol li");
      // 给按钮绑定对象
      $btn.click(function () {
          alert("点到按钮了");
      });
      // 给列表绑定对象
      $lis.click(function () {
          // 点击后更改颜色,this指代当前的内容
          $(this).css({ color: "red" });
          // 弹出点击内容
          alert($(this).html());
      });
      // 获取焦点
      $text.focus(function () {
          $(this).css({ background: "blue" });
          $div.css({ background: "yellow" });
      });
      // 失去焦点
      $text.blur(function () {
          $(this).css({ background: "white" });
          $div.css({ background: "white" });
      });
      // 鼠标移入
      $div.mouseover(function () {
          $(this).css({ width: "20px", height: "20px", background: "red" });
      });
      // 鼠标移出
      $div.mouseout(function () {
          $(this).css({
            width: "100px",
            height: "100px",
            background: "yellow",
          });
      });
      });
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div&gt;aa&lt;/div&gt;
    &lt;hr /&gt;
    &lt;input type="text" id="in1" /&gt;
    &lt;hr /&gt;
    &lt;input type="button" id="inb" value="ok" /&gt;
    &lt;hr /&gt;
    &lt;ol&gt;
      &lt;li&gt;第一&lt;/li&gt;
      &lt;li&gt;第二&lt;/li&gt;
      &lt;li&gt;第三&lt;/li&gt;
    &lt;/ol&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<h2 id="jquery-事件代理">jQuery 事件代理</h2>
<p>事件代理就是利用事件冒泡原理(事件会向父级一级一级传递),把事件加到父级身上,通过判断事件来源执行相对应的子元素操作,<strong>事件代理可以极大的减少事件绑定次数,提高性能;还可以让新加入的子元素也用有相同操作</strong></p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Document&lt;/title&gt;
    &lt;style&gt;
      #fd {
      width: 300px;
      height: 300px;
      background: red;
      }
      #cd {
      width: 100px;
      height: 100px;
      background: blue;
      }
    &lt;/style&gt;

    &lt;script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"&gt;&lt;/script&gt;
    &lt;!-- 冒泡原理 --&gt;
    &lt;!-- &lt;script&gt;
      $(function(){
            let $fd = $('#fd');
            let $cd = $('div').eq(1);
            
            $cd.click(function(){
                alert("子标签被点击");
            });
            $fd.click(function(){
                alert('父标签被点击了')
            })
      });
    &lt;/script&gt; --&gt;
    &lt;!-- 代理父元素代理子元素 --&gt;
    &lt;script&gt;
      $(function () {
      let $ol = $("ol");
      $ol.delegate("li", "click", function () {
          $(this).css({ background: "red" });
          alert($(this).html());
      });
      });
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div id="fd"&gt;
      qwe
      &lt;div id="cd"&gt;asd&lt;/div&gt;
    &lt;/div&gt;
    &lt;hr /&gt;
    &lt;ol&gt;
      &lt;li&gt;第一个&lt;/li&gt;
      &lt;li&gt;第二个&lt;/li&gt;
      &lt;li&gt;第三个&lt;/li&gt;
    &lt;/ol&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<h1 id="json">json</h1>
<p>最外面一定要有容器进行包裹,内部只能用双引号<br>
json 是一种数据格式,使用 js 的字符串进行描述</p>
<h2 id="对象格式">对象格式</h2>
<pre><code class="language-json">{
"name": "tom",
"age": 18
}
</code></pre>
<h2 id="数组格式">数组格式</h2>
<pre><code class="language-json">["tom", 18, "programmer"]
</code></pre>
<h2 id="常出现的样式">常出现的样式</h2>
<pre><code class="language-json">{
    "name":"jack",
    "age":29,
    "hobby":["reading","travel","photography"]
    "school":{
      "name":"Merrimack College",
      "location":"North Andover, MA"
    }
}
</code></pre>
<h2 id="使用-js-进行解析-json">使用 js 进行解析 json</h2>
<pre><code class="language-js">// 创建一个js的str类型以json数组为样式
let sjson1 = '';
console.log(typeof sjson1);
// 数据解析成js数组
let jArray = JSON.parse(sjson1);
console.log(jArray);

// 第二种形式
let sjson2 = '{"name":"tom","age":21}';
let tom = JSON.parse(sjson2);
console.log(tom);
console.log(tom.name, tom.age);
</code></pre>
<h1 id="ajax">ajax</h1>
<p>ajax 是一个前后端配合的技术,可以<strong>让 JS 发送异步的 http 请求,与后台进行数据的获取</strong>,ajax 最大的优点就是<strong>实现局部的刷新</strong>,ajax 可以发送 http 请求,当获取到后台的数据后就可以更新页面显示数据,实现局部刷新,<strong>前端页面想同后端服务器进行数据交互就要使用 ajax</strong></p>
<h2 id="ajax-的使用">ajax 的使用</h2>
<p>jQuery 将 ajax 封装成一个$.ajax()方法,使用方法就可以直接执行 ajax 请求。<br>
基本样式</p>
<pre><code class="language-js">$.ajax({
// 1.url请求地址,可以写绝对地址,也可以写相对地址(可以自动补齐地址)
url: "",
// 2.type:请求方式,默认是"GET"请求方式,常用的还有"POST"
type: "",
// 3.dataType:设置返回的数据格式,常用的是"json"格式,还有"xml","html","text"
dataType: "",
// 4.data:设置发送给服务器的数据,没有参数可以不设置
data: {},
// 5.success:设置请求成功后的回调函数
success: function (response) {
    console.log(response);
},
// 6.error:设置请求失败后的回调参数
error: function () {
    alert("请求失败,请稍后再试");
},
// 7.async:设置是否异步进行,默认值为"true",表示异步,一般不用设置
async: true,
});
</code></pre>
<h3 id="具体使用方法">具体使用方法</h3>
<pre><code>|--ajax
|--data.json
|--page.html
</code></pre>
<pre><code class="language-json">{ "name": "苹果笔记本15", "price": 55000 }
</code></pre>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8" /&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge" /&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&gt;
    &lt;title&gt;Document&lt;/title&gt;
    &lt;script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"&gt;&lt;/script&gt;
    &lt;script&gt;
      // 这个方法传入的是一个js对象
      $.ajax({
      url: "data.json",
      type: "GET",
      dataType: "JSON",
      // data:{page:1,count:20},
      success: function (data) {
          console.log(data);
          let $ln = $("#ln").next();
          $ln.html(data.name);
          let $lp = $("#lp").next();
          $lp.html(data.price);
      },
      error: function () {
          alert("请求失败");
      },
      async: true,
      });
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;label id="ln"&gt;商品名:&lt;/label&gt;&lt;label&gt;a&lt;/label&gt;
    &lt;hr /&gt;
    &lt;label id="lp"&gt;价格:&lt;/label&gt;&lt;label&gt;0&lt;/label&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<h3 id="ajax-简写">ajax 简写</h3>
<h4 id="get">get</h4>
<blockquote>
<p>$.get(url,success(data,status,xhr),dataType).error(func)</p>
</blockquote>
<pre><code class="language-js">$.get(
"data.json",
{ page: 1, count: 20 },
function (data) {
    console.log(data);
    let $ln = $("#ln").next();
    $ln.html(data.name);
    let $lp = $("#lp").next();
    $lp.html(data.price);
},
"json"
).error(function () {
alert("请求失败");
});
</code></pre>
<h4 id="post">post</h4>
<blockquote>
<p>$.post(url,success(data,status,xhr),dataType).error(func)</p>
</blockquote>
<pre><code class="language-js">$.post("data.json", { page: 1, count: 20 }, function (data) {
console.log(data);
let $ln = $("#ln").next();
$ln.html(data.name);
let $lp = $("#lp").next();
$lp.html(data.price);
}).error(function () {
alert("请求失败");
});
</code></pre>
<h1 id="vue">Vue</h1>
<p>Vue.js 使用的是 MVVM 框架,有容易上手的 API<br>
Vue.js 是一个数据驱动的 Web 界面的库<br>
Vue.js 是一套构建用户界面的渐进式框架<br>
核心是一个响应的数据绑定系统<br>
Vue.js 的官方文档</p>
<h2 id="使用-vuejs">使用 Vue.js</h2>
<h3 id="vue-的导入">vue 的导入</h3>
<pre><code class="language-html">&lt;!--导入Vue.js库进去--&gt;
&lt;!-- 开发环境版本,包含了有帮助的命令行警告 --&gt;
&lt;script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"&gt;&lt;/script&gt;
&lt;!-- 生产环境版本,优化了尺寸和速度 --&gt;
&lt;script src="https://cdn.jsdelivr.net/npm/vue"&gt;&lt;/script&gt;
</code></pre>
<h3 id="一般模板">一般模板</h3>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8" /&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge" /&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&gt;
    &lt;!-- 开发环境版本,包含了有帮助的命令行警告 --&gt;
    &lt;!-- 导入vue --&gt;
    &lt;script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"&gt;&lt;/script&gt;
    &lt;title&gt;Document&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;!-- 定义一个标签,并给标签一个id值 --&gt;
    &lt;div id="app"&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;!-- 创建vue实例 --&gt;
&lt;script type="text/javascript"&gt;
    let app = new Vue({
      el: "#app",
      data: {
      message: "hello",
      },
    });
&lt;/script&gt;
&lt;/html&gt;
</code></pre>
<h3 id="基础使用">基础使用</h3>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8" /&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge" /&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&gt;
    &lt;!-- 开发环境版本,包含了有帮助的命令行警告 --&gt;
    &lt;script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"&gt;&lt;/script&gt;
    &lt;title&gt;Document&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div id="app"&gt;
      &lt;!-- vue使用声明式渲染 --&gt;
      &lt;a href="#"&gt;{{ message }}&lt;/a&gt;
      &lt;hr /&gt;
      &lt;span&gt;{{ hello }}&lt;/span&gt;
      &lt;hr /&gt;

      &lt;!-- 使用v-bind给属性绑定数据 --&gt;
      &lt;a v-bind:href="url"&gt;点击&lt;/a&gt;
      &lt;hr /&gt;

      &lt;!-- 将v-bind进行简写 --&gt;
      &lt;span :title="showmessage"&gt;鼠标放在这里&lt;/span&gt;
      &lt;hr /&gt;

      &lt;!-- 使用v-if进行判断 --&gt;
      &lt;a href="#" v-if="isLogin"&gt;欢迎&lt;/a&gt;
      &lt;hr /&gt;
      &lt;!-- v-if与v-else及v-else-if必须挨着否则无效 --&gt;
      &lt;a href="#" v-if="level === 1"&gt;青铜&lt;/a&gt;
      &lt;a href="#" v-else-if="level === 2"&gt;白银&lt;/a&gt;
      &lt;a href="#" v-else&gt;王者&lt;/a&gt;
      &lt;hr /&gt;

      &lt;!-- v-if和v-show的区别,使用f12打开控制台查看区别 --&gt;
      &lt;span v-if="seen"&gt; v-if &lt;/span&gt;
      &lt;span v-show="seen"&gt; v-shiw &lt;/span&gt;
      &lt;hr /&gt;

      &lt;!-- v-for使用语法 --&gt;
      &lt;ul&gt;
      &lt;!-- 解包这个顺序不能改变 --&gt;
      &lt;li v-for="(item,index) in items"&gt;{{index+1}} {{item}}&lt;/li&gt;
      &lt;/ul&gt;
      &lt;hr /&gt;
      &lt;!-- 对对象进行遍历 --&gt;
      &lt;ul&gt;
      &lt;!-- 解包这个顺序不能改变 --&gt;
      &lt;li v-for="(value,key) in object"&gt;{{key}} : {{value}}&lt;/li&gt;
      &lt;/ul&gt;
      &lt;hr /&gt;

      &lt;!-- 使用v-on进行绑定动作 --&gt;
      &lt;button v-on:click="login"&gt;登录&lt;/button&gt;
      &lt;!-- 将v-on进行简写 --&gt;
      &lt;a href="" @click="register"&gt;注册&lt;/a&gt;
      &lt;button @click="add(counter)"&gt;+1&lt;/button&gt;
      &lt;hr /&gt;

      &lt;!-- 绑定输入(双向绑定) --&gt;
      &lt;table&gt;
      &lt;tr&gt;
          &lt;td&gt;用户名&lt;/td&gt;
          &lt;td&gt;&lt;input type="text" name="username" v-model="username" /&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;密码&lt;/td&gt;
          &lt;td&gt;
            &lt;input type="password" name="password1" v-model="password1" /&gt;
          &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;确认密码&lt;/td&gt;
          &lt;td&gt;
            &lt;input type="password" name="password2" v-model="password2" /&gt;
          &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;性别&lt;/td&gt;
          &lt;td&gt;
            男&lt;input type="radio" name="sex" value="boy" v-model="sex" /&gt;
            女&lt;input type="radio" name="sex" value="girl" v-model="sex" /&gt;
          &lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;爱好&lt;/td&gt;
          &lt;td&gt;
            足球&lt;input
            type="checkbox"
            name="like"
            value="足球"
            v-model="like"
            /&gt;
            篮球&lt;input
            type="checkbox"
            name="like"
            value="篮球"
            v-model="like"
            /&gt;
            乒乓球&lt;input
            type="checkbox"
            name="like"
            value="乒乓球"
            v-model="like"
            /&gt;
          &lt;/td&gt;
      &lt;/tr&gt;
      &lt;/table&gt;
      &lt;button v-on:click="register2"&gt;注册&lt;/button&gt;
    &lt;/div&gt;
&lt;/body&gt;
&lt;script type="text/javascript"&gt;
    //创建一个app下的vue实例
    let app = new Vue({
      //挂载到id=app的标签上,el内写接管标签
      el: "#app",
      // 使用模板语言进行填充,数据进行双向绑定
      // data内写绑定数据
      data: {
      // 内容message赋值一个hello vue
      message: "hello vue",
      hello: "你好",
      // 将url发给绑定的位置
      url: "https://www.baidu.com",
      // 创建一个显示时间的函数赋值给showmessage
      showmessage: "当前时间是" + new Date().toLocaleString(),
      isLogin: true,
      level: 1,
      seen: false,
      items: ,
      object: {
          title: "How to do lists in Vue",
          author: "Jane Doe",
          publishedAt: "2016-04-10",
      },
      counter: 1,
      username: "",
      password1: "",
      password2: "",
      sex: "",
      like: [],
      },
      // methods内写方法
      methods: {
      login: function () {
          alert("成功");
      },
      register: function () {
          alert("注册");
      },
      add: function (counter) {
          // this表示当前vue,通过this.level访问data中的变量
          this.level += counter;
      },
      register2: function () {
          alert(
            this.username +
            this.password1 +
            this.password2 +
            this.sex +
            this.like
          );
      },
      },
    });
&lt;/script&gt;
&lt;/html&gt;
</code></pre>
<h3 id="todolist-示例">todolist 示例</h3>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8" /&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge" /&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&gt;
    &lt;!-- 开发环境版本,包含了有帮助的命令行警告 --&gt;
    &lt;!-- 导入vue --&gt;
    &lt;script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"&gt;&lt;/script&gt;
    &lt;title&gt;Document&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;!-- 定义标签 --&gt;
    &lt;div id="app"&gt;
      &lt;input type="text" name="todoitem" v-model="newitem" /&gt;&lt;button
      @click="add"
      &gt;
      添加
      &lt;/button&gt;
      &lt;hr /&gt;
      &lt;ul&gt;
      &lt;li v-for="(item,index) in items"&gt;
          &lt;a href="javascript:;" @click="up(index)"&gt;↑&lt;/a&gt;
          {{ item }}
          &lt;a href="#" @click="deleteitem(index)"&gt;删除&lt;/a&gt;
          &lt;a href="javascript:;" @click="down(index)"&gt;↓&lt;/a&gt;
      &lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
&lt;/body&gt;
&lt;!-- 创建vue实例 --&gt;
&lt;script type="text/javascript"&gt;
    let app = new Vue({
      el: "#app",
      data: {
      items: ["asdasd", "asdasdqwe"],
      newitem: "",
      },
      methods: {
      add: function () {
          this.items.push(this.newitem);
          this.newitem = " ";
      },
      deleteitem: function (index) {
          this.items.splice(index, 1);
      },
      up: function (index) {
          // 获取当前元素
          current = this.items;
          // 把当前元素删除
          this.items.splice(index, 1);
          // 再添加,添加索引加1
          this.items.splice(index - 1, 0, current);
      },
      down: function (index) {
          // 获取当前元素
          current = this.items;
          // 把当前元素删除
          this.items.splice(index, 1);
          // 再添加,添加索引加1
          this.items.splice(index + 1, 0, current);
      },
      },
    });
&lt;/script&gt;
&lt;/html&gt;
</code></pre>
<h3 id="vue-实例生命周期">vue 实例生命周期</h3>
<p><img src="https://img2023.cnblogs.com/blog/3286006/202503/3286006-20250327131953643-934713712.png" alt="image" loading="lazy"></p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;meta charset="UTF-8" /&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge" /&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&gt;
    &lt;!-- 开发环境版本,包含了有帮助的命令行警告 --&gt;
    &lt;!-- 导入vue --&gt;
    &lt;script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"&gt;&lt;/script&gt;
    &lt;title&gt;Document&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;!-- 定义标签 --&gt;
    &lt;div id="app"&gt;
      &lt;span&gt; {{message}} &lt;/span&gt;
    &lt;/div&gt;
&lt;/body&gt;
&lt;!-- 创建vue实例 --&gt;
&lt;script type="text/javascript"&gt;
    let app = new Vue({
      el: "#app",
      data: {
      message: "hello",
      },
      // 生命周器的钩子(函数),没有在methods内
      // app对象实例化之前
      beforeCreate: function () {
      console.log("beforeCreate");
      },
      // app对象实例化后
      created: function () {
      console.log("created");
      },
      // app将作用标签之前
      beforeMount: function () {
      console.log("beforeMounted");
      },
      // app将作用标签之后
      mounted: function () {
      console.log("mounted");
      },
      // 数据或者属性更新之前
      berforeDestroy() {
      console.log("berforeDestroy");
      },
      // 数据或属性更新之后
      destroyed: function () {
      console.log("destroyed");
      },
    });
&lt;/script&gt;
&lt;/html&gt;
</code></pre>
<h3 id="发送-ajax-请求">发送 ajax 请求</h3>
<p>vue 本身不能发送 ajax 请求,可以使用 axios 发送,是 vue2.0 官方推荐的<br>
cdn</p>
<pre><code class="language-html">&lt;script src="https://unpkg.com/axios/dist/axios.min.js"&gt;&lt;/script&gt;
</code></pre>
<h4 id="前端代码">前端代码</h4>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
    &lt;!-- 开发环境版本,包含了有帮助的命令行警告 --&gt;
    &lt;!-- 导入vue --&gt;
    &lt;script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"&gt;&lt;/script&gt;
    &lt;!-- 导入axios --&gt;
    &lt;script src="https://unpkg.com/axios/dist/axios.min.js"&gt;&lt;/script&gt;
    &lt;title&gt;Document&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;!-- 定义一个标签,并给标签一个id值 --&gt;
    &lt;div id="app"&gt;
      &lt;!-- vue的大胡子模板语法和django/flask的模板语法冲突 --&gt;
      &lt;span&gt;[[ message ]]&lt;/span&gt;
      &lt;button @click="login"&gt;登录&lt;/button&gt;
      &lt;hr /&gt;
      [[ username ]]

      &lt;hr /&gt;
      &lt;button @click="login2"&gt;post&lt;/button&gt;
    &lt;/div&gt;
&lt;/body&gt;
&lt;!-- 创建vue实例 --&gt;
&lt;script type="text/javascript"&gt;
    let app = new Vue({
      el: "#app",
      // 修改vue语法的分隔符
      delimiters: ["[[", "]]"],
      data: {
      message: "hello",
      username: "",
      },
      methods: {
      // 这里发送ajax请求
      login: function () {
          alert("登录成功");
          // 定义一个url地址
          let url = "http://127.0.0.1:8000/rece?username=itcast&amp;password=1234";
          // then catch 用 =&gt; 箭头函数 this指向问题
          axios
            .get(url)
            .then((response) =&gt; {
            // 返回的数据responser(响应)--&gt;response.data(数据)--&gt;response.data.info(ajax返回的字典)--&gt;username
            console.log(response.data.info.username);
            this.username = response.data.info.username;
            })
            .catch((error) =&gt; {
            console.log(error);
            });
      },
      login2: function () {
          // axios.post().then().catch() then成功的回调,catach失败的回调
          let url = "http://127.0.0.1:8000/rece/";
          axios
            .post(url, {
            username: "李四",
            password: "123456",
            })
            .then((response) =&gt; {
            console.log(response.data.info.username);
            this.username = response.data.info.username;
            })
            .catch((error) =&gt; {
            console.log(response.data.info.username);
            });
      },
      },
    });
&lt;/script&gt;
&lt;/html&gt;
</code></pre>
<h4 id="后端参考-python-的-django-部分文档-view-内主要代码">后端参考 python 的 django 部分文档 view 内主要代码</h4>
<pre><code>import json
from django.shortcuts import render
from django.views import View
from django.http import JsonResponse
# Create your views here.
class LoginView(View):

def get(self,request):
return render(request,'login.html')

def post(self,request):
pass

class ReceiveView(View):

def get(self,request):
# 1。接收参数
data = request.GET
username = data.get('username')
password = data.get('password')
return JsonResponse({'info':{'username':username}})

def post(self,request):
data = json.loads(request.body.decode())
username = data.get('username')
password = data.get('password')
return JsonResponse({'info':{'username':username}})
</code></pre>
<h4 id="urls-内主要代码">urls 内主要代码</h4>
<pre><code>主路由
from django.contrib import admin
from django.urls import path, include, re_path

urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'^',include('book.urls')),
]

分路由
from django.urls import path, re_path
from book.views import LoginView,ReceiveView

urlpatterns = [
re_path(r'^login/$',LoginView.as_view()),
re_path(r'^rece/$',ReceiveView.as_view()),
]
</code></pre>
<h1 id="canvas">canvas</h1>
<h2 id="认识-canvas">认识 canvas</h2>
<p>可以使用 canvas 进行网页背景设计和图表设计<br>
官方文档 mdn</p>
<h3 id="一个简单的-canvas">一个简单的 canvas</h3>
<pre><code class="language-html">&lt;bod&gt;
&lt;!--
    id:标识元素的唯一性
    width:画布的宽度
    height:画布的高度
--&gt;
    &lt;canvas id="c1" width="600" heigth="400"&gt;
    当前浏览器不支持canvas请下载最新版的浏览器
    &lt;a herf="https://www.google.cn/intl/zh-CN/chrome"&gt;下载新版浏览器&lt;/a&gt;
    &lt;/canvas&gt;

    &lt;script&gt;
      // 1.找到画布
      let c1 = document.getElementById('c1');
      // 判断浏览器是否支持canvas
      if(!c1.getContext){
            console.log("当前浏览器不支持canvas请下载最新版的浏览器")
      }
      // 2.获取画笔,上下文对象
      let ctx = c1.getContext('2d');
      // 绘制图形
      // 填充矩形:fillRect(位置x,位置y,宽度,高度)
      ctx.fillRect(100,200,300,300);
    &lt;/script&gt;

&lt;/body&gt;
</code></pre>
<h2 id="canvas-绘制基本图形">canvas 绘制基本图形</h2>
<h3 id="栅格">栅格</h3>
<p><img src="https://img2023.cnblogs.com/blog/3286006/202503/3286006-20250327131954298-1299979334.png" alt="image" loading="lazy"></p>
<h3 id="canvas-的宽高和-css-设置的宽高">canvas 的宽高和 css 设置的宽高</h3>
<p>css 相当于对图片的放大缩小<br>
canvas 是指定图片的大小<br>
修改 css 对 canvas 的图片进行拉伸或压缩,导致图片变形</p>
<h3 id="矩形绘制填充模式">矩形绘制填充模式</h3>
<pre><code class="language-html">&lt;bod&gt;
&lt;!--
    id:标识元素的唯一性
    width:画布的宽度
    height:画布的高度
--&gt;
    &lt;canvas id="c1" width="600" heigth="400"&gt;
    当前浏览器不支持canvas请下载最新版的浏览器
    &lt;a herf="https://www.google.cn/intl/zh-CN/chrome"&gt;下载新版浏览器&lt;/a&gt;
    &lt;/canvas&gt;

    &lt;script&gt;
      // 1.找到画布
      let c1 = document.getElementById('c1');
      // 判断浏览器是否支持canvas
      if(!c1.getContext){
            console.log("当前浏览器不支持canvas请下载最新版的浏览器")
      }
      // 2.获取画笔,上下文对象
      let ctx = c1.getContext('2d');
      // 绘制图形
      // 填充矩形:fillRect(位置x,位置y,宽度,高度)
      ctx.fillRect(100,200,300,300);
      // 填充矩形拆开写法:ctx.rect(100,200,300,300);ctx.fill();
      // 单写ctx.rect()不会显示,
      ctx.rect(100,200,300,300);
      // 填充后才显示
      ctx.fill();
    &lt;/script&gt;

&lt;/body&gt;
</code></pre>
<h3 id="矩形绘制路径模式">矩形绘制路径模式</h3>
<pre><code class="language-html">&lt;bod&gt;
&lt;!--
    id:标识元素的唯一性
    width:画布的宽度
    height:画布的高度
--&gt;
    &lt;canvas id="c1" width="600" heigth="400"&gt;
    当前浏览器不支持canvas请下载最新版的浏览器
    &lt;a herf="https://www.google.cn/intl/zh-CN/chrome"&gt;下载新版浏览器&lt;/a&gt;
    &lt;/canvas&gt;

    &lt;script&gt;
      // 1.找到画布
      let c1 = document.getElementById('c1');
      // 判断浏览器是否支持canvas
      if(!c1.getContext){
            console.log("当前浏览器不支持canvas请下载最新版的浏览器")
      }
      // 2.获取画笔,上下文对象
      let ctx = c1.getContext('2d');
      // 绘制图形
      // 路径绘制矩形:strockeRect(位置x,位置y,宽度,高度)
      ctx.strokeRect(100,100,200,100);
      // 路径绘制矩形拆开写法:ctx.rect(100,200,300,300);ctx.stroke();
      // 单写ctx.rect()不会显示,
      ctx.rect(100,200,300,300);
      // 填充后才显示
      ctx.stroke();
    &lt;/script&gt;

&lt;/body&gt;
</code></pre>
<h3 id="矩形绘制清除模式">矩形绘制清除模式</h3>
<pre><code class="language-html">&lt;bod&gt;
&lt;!--
    id:标识元素的唯一性
    width:画布的宽度
    height:画布的高度
--&gt;
    &lt;canvas id="c1" width="600" heigth="400"&gt;
    当前浏览器不支持canvas请下载最新版的浏览器
    &lt;a herf="https://www.google.cn/intl/zh-CN/chrome"&gt;下载新版浏览器&lt;/a&gt;
    &lt;/canvas&gt;

    &lt;script&gt;
      // 1.找到画布
      let c1 = document.getElementById('c1');
      // 判断浏览器是否支持canvas
      if(!c1.getContext){
            console.log("当前浏览器不支持canvas请下载最新版的浏览器")
      }
      // 2.获取画笔,上下文对象
      let ctx = c1.getContext('2d');
      // 绘制图形
      // 填充矩形:fillRect(位置x,位置y,宽度,高度)
      ctx.fillRect(100,200,300,300);
      // 清除填充内容
      ctx.clearRect(0,0,c1.clientWidth,c1.clientHeight);
      let height = 0;
      // 逐渐清除(每10ms清除一个height)
      let t1 = setInterval(()=&gt;{
            height++;
            ctx.clearRect(0,0,c1.clientWidth,height);
            // 判断清除函数
            if(height &gt; c1.clientHeight){
                // 清除t1这个函数
                clearInterval(t1);
            }
      },10)
    &lt;/script&gt;

&lt;/body&gt;
</code></pre>
<h3 id="画笔抬起">画笔抬起</h3>
<pre><code class="language-html">&lt;bod&gt;
&lt;!--
    id:标识元素的唯一性
    width:画布的宽度
    height:画布的高度
--&gt;
    &lt;canvas id="c1" width="600" heigth="400"&gt;
    当前浏览器不支持canvas请下载最新版的浏览器
    &lt;a herf="https://www.google.cn/intl/zh-CN/chrome"&gt;下载新版浏览器&lt;/a&gt;
    &lt;/canvas&gt;

    &lt;script&gt;
      // 1.找到画布
      let c1 = document.getElementById('c1');
      // 判断浏览器是否支持canvas
      if(!c1.getContext){
            console.log("当前浏览器不支持canvas请下载最新版的浏览器")
      }
      // 2.获取画笔,上下文对象
      let ctx = c1.getContext('2d');
      // 绘制图形
      // 填充矩形:fillRect(位置x,位置y,宽度,高度)
      // 下笔
      ctx.bgeinPath();
      ctx.rect(100,100,200,100);
      ctx.stroke();
      // 抬笔
      ctx.closePath();

      // 下笔
      ctx.bgeinPath();
      ctx.rect(200,150,200,100);
      ctx.fill();
      // 抬笔
      ctx.closePath();
    &lt;/script&gt;

&lt;/body&gt;
</code></pre>
<h3 id="绘制圆圆弧">绘制圆,圆弧</h3>
<pre><code class="language-html">&lt;bod&gt;
&lt;!--
    id:标识元素的唯一性
    width:画布的宽度
    height:画布的高度
--&gt;
    &lt;canvas id="c1" width="600" heigth="400"&gt;
    当前浏览器不支持canvas请下载最新版的浏览器
    &lt;a herf="https://www.google.cn/intl/zh-CN/chrome"&gt;下载新版浏览器&lt;/a&gt;
    &lt;/canvas&gt;

    &lt;script&gt;
      // 1.找到画布
      let c1 = document.getElementById('c1');
      // 判断浏览器是否支持canvas
      if(!c1.getContext){
            console.log("当前浏览器不支持canvas请下载最新版的浏览器")
      }
      // 2.获取画笔,上下文对象
      let ctx = c1.getContext('2d');
      // 绘制图形
      // 绘制圆弧:ctx.arc(圆心x,圆心y,半径r,开始的角度,结束的角度,顺时针false /逆时针true)
      ctx.arc(300,200,50,0,Math.PI*2);
      ctx.fill();

      // 起始点
      ctx.moveTo(300,200);
      // 绘制圆弧:ctx.arcTo(点1x,点1y,点2x,点2y,半径r)
      ctx.arcTo(300,250,250,250,25);
      ctx.strock();

    &lt;/script&gt;

&lt;/body&gt;
</code></pre>
<h3 id="使用-moveto-移动点">使用 moveTo 移动点</h3>
<pre><code class="language-html">&lt;bod&gt;
&lt;!--
    id:标识元素的唯一性
    width:画布的宽度
    height:画布的高度
--&gt;
    &lt;canvas id="c1" width="600" heigth="400"&gt;
    当前浏览器不支持canvas请下载最新版的浏览器
    &lt;a herf="https://www.google.cn/intl/zh-CN/chrome"&gt;下载新版浏览器&lt;/a&gt;
    &lt;/canvas&gt;

    &lt;script&gt;
      // 1.找到画布
      let c1 = document.getElementById('c1');
      // 判断浏览器是否支持canvas
      if(!c1.getContext){
            console.log("当前浏览器不支持canvas请下载最新版的浏览器")
      }
      // 2.获取画笔,上下文对象
      let ctx = c1.getContext('2d');
      // 绘制图形
      ctx.beginPath();
      // 绘制圆脸:
      ctx.arc(75,75,50,0,Math.PI *2);
      // 移动画笔
      ctx.moveTo(110,75)
      // 绘制嘴巴
      ctx.arc(75,75,35,0,Math.PI);
      // 移动画笔
      ctx.moveTo(65,65)
      // 绘制左眼
      ctx.arc(60,65,5,0,Math.PI *2);
      // 移动画笔
      ctx.moveTo(95,65)
      //绘制右眼
      ctx.arc(90,65,5,0,Math.PI *2);
      // 填充线段
      ctx.stroke();
      ctx.closePath();
    &lt;/script&gt;

&lt;/body&gt;
</code></pre>
<h3 id="绘制折线">绘制折线</h3>
<pre><code class="language-html">&lt;bod&gt;
&lt;!--
    id:标识元素的唯一性
    width:画布的宽度
    height:画布的高度
--&gt;
    &lt;canvas id="c1" width="600" heigth="400"&gt;
    当前浏览器不支持canvas请下载最新版的浏览器
    &lt;a herf="https://www.google.cn/intl/zh-CN/chrome"&gt;下载新版浏览器&lt;/a&gt;
    &lt;/canvas&gt;

    &lt;script&gt;
      // 1.找到画布
      let c1 = document.getElementById('c1');
      // 判断浏览器是否支持canvas
      if(!c1.getContext){
            console.log("当前浏览器不支持canvas请下载最新版的浏览器")
      }
      // 2.获取画笔,上下文对象
      let ctx = c1.getContext('2d');
      // 绘制图形
      ctx.beginPath();
      // 绘制折线
      // 开始位置在300,200
      ctx.moveTo(300,200);
      // 结束路径在350,250
      ctx.lineTo(350,250);


      ctx.strock();
      ctx.closePath();
    &lt;/script&gt;

&lt;/body&gt;
</code></pre>
<h3 id="贝塞尔曲线">贝塞尔曲线</h3>
<p>贝塞尔曲线由三个点控制的曲线,这三个点中一个起点,一个终点,还有一个控制点,控制点可以再增加其他点进行控制</p>
<pre><code class="language-html">&lt;bod&gt;
&lt;!--
    id:标识元素的唯一性
    width:画布的宽度
    height:画布的高度
--&gt;
    &lt;canvas id="c1" width="600" heigth="400"&gt;
    当前浏览器不支持canvas请下载最新版的浏览器
    &lt;a herf="https://www.google.cn/intl/zh-CN/chrome"&gt;下载新版浏览器&lt;/a&gt;
    &lt;/canvas&gt;

    &lt;script&gt;
      // 1.找到画布
      let c1 = document.getElementById('c1');
      // 判断浏览器是否支持canvas
      if(!c1.getContext){
            console.log("当前浏览器不支持canvas请下载最新版的浏览器")
      }
      // 2.获取画笔,上下文对象
      let ctx = c1.getContext('2d');
      // 绘制图形
      // 贝塞尔曲线:quadraticCurveTo(控制点x,控制点y,终点x,终点y);
      // 冒泡聊天框
      // 起始点
      ctx.moveTo(200,300);
      // 控制点,终止点
      ctx.quadraticCurveTo(150,300,150,200);
      ctx.quadraticCurveTo(100,100,300,100);
      ctx.quadraticCurveTo(450,100,450,200);
      ctx.quadraticCurveTo(450,300,250,300);
      ctx.quadraticCurveTo(250,350,150,300);
      ctx.quadraticCurveTo(200,350,200,300);
      ctx.strock();

         // 贝塞尔曲线:ctx.bezierCurveTo(控制点1x,控制点1y,控制点2x,控制点2y,终点x,终点y);
      // 爱心
      // 起始点
      ctx.moveTo(200,300);
      // 控制点1,控制点2,终止点
      ctx.bezierCurveTo(350,150,400,200,300,300);
      ctx.bezierCurveTo(350,150,400,200,300,300);
      ctx.strock();


    &lt;/script&gt;

&lt;/body&gt;
</code></pre>
<h3 id="path2d-封装路径">path2D-封装路径</h3>
<pre><code class="language-html">&lt;bod&gt;
&lt;!--
    id:标识元素的唯一性
    width:画布的宽度
    height:画布的高度
--&gt;
    &lt;canvas id="c1" width="600" heigth="400"&gt;
    当前浏览器不支持canvas请下载最新版的浏览器
    &lt;a herf="https://www.google.cn/intl/zh-CN/chrome"&gt;下载新版浏览器&lt;/a&gt;
    &lt;/canvas&gt;

    &lt;script&gt;
      // 1.找到画布
      let c1 = document.getElementById('c1');
      // 判断浏览器是否支持canvas
      if(!c1.getContext){
            console.log("当前浏览器不支持canvas请下载最新版的浏览器")
      }
      // 2.获取画笔,上下文对象
      let ctx = c1.getContext('2d');

      // 创建路径实例
      let heartPath = new.Path2D();
      // 路径起始点
      heartPath.moveTo(200,300);
      // 路径使用贝塞尔曲线绘制
      heartPath.bezierCurveTo(350,150,400,200,300,300);
      heartPath.bezierCurveTo(350,150,400,200,300,300);
      // 绘制制定的路径
      cxt.strock(heartPath);

      // 创建一条折线
      // 使用svg的写法
      let polyline = new Path2D("M10 10 h 80 v 80 h -80 z");
      ctx.strocke(polyline);
    &lt;/script&gt;

&lt;/body&gt;
</code></pre>
<h3 id="颜色修改">颜色修改</h3>
<pre><code class="language-html">&lt;bod&gt;
&lt;!--
    id:标识元素的唯一性
    width:画布的宽度
    height:画布的高度
--&gt;
    &lt;canvas id="c1" width="600" heigth="400"&gt;
    当前浏览器不支持canvas请下载最新版的浏览器
    &lt;a herf="https://www.google.cn/intl/zh-CN/chrome"&gt;下载新版浏览器&lt;/a&gt;
    &lt;/canvas&gt;

    &lt;script&gt;
      // 1.找到画布
      let c1 = document.getElementById('c1');
      // 判断浏览器是否支持canvas
      if(!c1.getContext){
            console.log("当前浏览器不支持canvas请下载最新版的浏览器")
      }
      // 2.获取画笔,上下文对象
      let ctx = c1.getContext('2d');
      ctx.strokeStyle = "red";

      ctx.strokeRect(100,100,200,100);
      ctx.strokeStyle = "#ff00ff";
      ctx.rect(100,200,300,300);
      ctx.stroke();



    &lt;/script&gt;

&lt;/body&gt;
</code></pre>
<h3 id="封装绘制的物体">封装绘制的物体</h3>
<pre><code class="language-html">&lt;bod&gt;
&lt;!--
    id:标识元素的唯一性
    width:画布的宽度
    height:画布的高度
--&gt;
    &lt;canvas id="c1" width="600" heigth="400"&gt;
    当前浏览器不支持canvas请下载最新版的浏览器
    &lt;a herf="https://www.google.cn/intl/zh-CN/chrome"&gt;下载新版浏览器&lt;/a&gt;
    &lt;/canvas&gt;

    &lt;script&gt;
      // 1.找到画布
      let c1 = document.getElementById('c1');
      // 判断浏览器是否支持canvas
      if(!c1.getContext){
            console.log("当前浏览器不支持canvas请下载最新版的浏览器")
      }
      // 2.获取画笔,上下文对象
      let ctx = c1.getContext('2d');

      // 封装
      class Heart{
            constructor(x,y){
                this.x = x;
                this.y = y;
                this.color = "red";
                this.isIn = false;
                this.eventMapList = {
                  hover:[],
                  leave:[],
                };
                // 监听鼠标
                c1.onmousemove = (e)=&gt;{
                  // 获取鼠标位置
                  let x = e.offsetX;
                  let x = e.offsetX;
                  this.isIn = ctx.isPointInPath(
                  this.hearPath,x,y);
                  is(this.isIn){
                        this.eventMapList.hover.forEach((item)=&gt;{item();});
                  }else{
                        this.eventMapList.hover.forEach((item)=&gt;{item();});
                  }
                };
            }
            onHover(fn){
                this.eventMapList.hover.push(fn);
            }
            onLeace(fn){
                this.eventMapList.leave.push(fn);
            }
            // 修改设置x,y
            setPostition(x,y){
                this.x = x;
                this.y = y;
            }
            draw(){
                this.heartPath = new path2D();
                this.heartPath.moveTo(this.x,this.y);
                heartPath.bezierCurveTo(
                  this.x+50,
                  this.y-50,
                  this.x+100,
                  this.y,
                  this.x,
                  this.y+50
                );
                heartPath.bezierCurveTo(
                  this.x-100,
                  this.y,
                  this.x-50,
                  this.y-50,
                  this.x,
                  this,y
                );
                ctx.save();
                ctx.fillStyle = this.color;
                ctx.fill(this.heartpath);
                ctx.restore();
            }
      }
      // 创建画图实例
      let heart = new Heart(100,100);
      heart.onHover(()=&gt;{
            heart.color = "blue";
      })
      heart.onLeave(()=&gt;{
            heart.color = "red";
      })
      // 改动更新
      function render(){
            ctx.clearRect(0,0,c1.width,c1.heigth);
            heart.draw();
            // 不定时异步刷新
            requestAnimationFrame(render);
      }
      // 调用主函数
      render();

    &lt;/script&gt;

&lt;/body&gt;
</code></pre><br><br>
来源:https://www.cnblogs.com/elmhome/p/18795808
頁: [1]
查看完整版本: JavaScript