From 00163f484ee5f699f16711ba9002f735db69b068 Mon Sep 17 00:00:00 2001 From: void Date: Mon, 6 Jul 2026 20:14:37 +0800 Subject: [PATCH] init --- JavaScript.md | 412 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 412 insertions(+) create mode 100644 JavaScript.md diff --git a/JavaScript.md b/JavaScript.md new file mode 100644 index 0000000..1dfc8f5 --- /dev/null +++ b/JavaScript.md @@ -0,0 +1,412 @@ +## 交互:alert、prompt 和 confirm + +```js +alert("Hello"); +result = prompt(title, [default]); +result = confirm(question); // true | false +``` + +## 类型转换 + +### 字符串转换 + +我们也可以显式地调用 `String(value)` 来将 value 转换为字符串类型: + +```js +let value = true; +alert(typeof value); // boolean + +value = String(value); // 现在,值是一个字符串形式的 "true" +alert(typeof value); // string +``` + +### 数字型转换 + +在算术函数和表达式中,会自动进行 number 类型转换。 + +```js +alert( "6" / "2" ); // 3, string 类型的值被自动转换成 number 类型后进行计算 +``` + +显式转换。 + +```js +let str = "123"; +alert(typeof str); // string + +let num = Number(str); // 变成 number 类型 123 + +alert(typeof num); // number +``` + +`Number` 类型的转换规则: + +| 值 | 变成…… | +| :-------------- | :----------------------------------------------------------- | +| `undefined` | `NaN` | +| `null` | `0` | +| `true 和 false` | `1` and `0` | +| `string` | 去掉首尾空白字符(空格、换行符 `\n`、制表符 `\t` 等)后的纯数字字符串中含有的数字。如果剩余字符串为空,则转换结果为 `0`。否则,将会从剩余字符串中“读取”数字。当类型转换出现 error 时返回 `NaN`。 | + +### 布尔型转换 + +它发生在逻辑运算中,也可以通过调用 Boolean(value) 显式地进行转换。 + +转换规则如下: + +- 直观上为“空”的值(如 `0`、空字符串、`null`、`undefined` 和 `NaN`)将变为 `false`。 +- 其他值变成 `true`。 + +## 基础运算符,数学运算 + +### 术语:“一元运算符”,“二元运算符”,“运算元” + +运算元:比如说乘法运算 `5 * 2`,有两个运算元:左运算元 `5` 和右运算元 `2`。有时候人们也称其为“参数”而不是“运算元”。 + +如果一个运算符对应的只有一个运算元,那么它是 **一元运算符**。比如说一元负号运算符(unary negation)`-`,它的作用是对数字进行正负转换: + +```js +let x = 1; + +x = -x; +alert( x ); // -1,一元负号运算符生效 +``` + +如果一个运算符拥有两个运算元,那么它是 **二元运算符**。减号还存在二元运算符形式: + +```js +let x = 1, y = 3; +alert( y - x ); // 2,二元运算符减号做减运算 +``` + +### 数学运算 +支持以下数学运算: + +- 加法 `+`, +- 减法 `-`, +- 乘法 `*`, +- 除法 `/`, +- 取余 `%`, +- 求幂 `**`. + +### 数字转化,一元运算符 `+` + +加号 `+` 有两种形式。一种是上面我们刚刚讨论的二元运算符,还有一种是一元运算符。 + +一元运算符加号,或者说,加号 `+` 应用于单个值,对数字没有任何作用。但是如果运算元不是数字,加号 `+` 则会将其转化为数字。 + +```JS +let apples = "2"; +let oranges = "3"; + +alert( apples + oranges ); // "23",二元运算符加号合并字符串 +``` + +```JS +let apples = "2"; +let oranges = "3"; + +// 在二元运算符加号起作用之前,所有的值都被转化为了数字 +alert( +apples + +oranges ); // 5 + +// 更长的写法 +// alert( Number(apples) + Number(oranges) ); // 5 +``` + +### 逗号运算符 + +逗号运算符能让我们处理多个表达式,使用 , 将它们分开。每个表达式都运行了,但是只有最后一个的结果会被返回。 + +```js +let a = (1 + 2, 3 + 4); + +alert( a ); // 7(3 + 4 的结果) + +// 一行上有三个运算符 +for (a = 1, b = 3, c = a * b; a < 10; a++) { + ... +} +``` + +## 值的比较 + +### 字符串比较 + +在比较字符串的大小时,JavaScript 会使用 **Unicode 编码顺序** 顺序进行判定。 + +换言之,字符串是按字符(母)逐个进行比较的。 + +例如: + +```javascript +alert( 'Z' > 'A' ); // true +alert( 'Glow' > 'Glee' ); // true +alert( 'Bee' > 'Be' ); // true +``` + +字符串的比较算法非常简单: + +1. 首先比较两个字符串的首位字符大小。 +2. 如果一方字符较大(或较小),则该字符串大于(或小于)另一个字符串。算法结束。 +3. 否则,如果两个字符串的首位字符相等,则继续取出两个字符串各自的后一位字符进行比较。 +4. 重复上述步骤进行比较,直到比较完成某字符串的所有字符为止。 +5. 如果两个字符串的字符同时用完,那么则判定它们相等,否则未结束(还有未比较的字符)的字符串更大。 + +### 不同类型间的比较 + +当对不同类型的值进行比较时,除了 `null` 和 `undefined`,JavaScript 会首先将其转化为数字(number)再判定大小。 + +```js +alert( '2' > 1 ); // true,字符串 '2' 会被转化为数字 2 +alert( '01' == 1 ); // true,字符串 '01' 会被转化为数字 1 +alert( true == 1 ); // true +alert( false == 0 ); // true +``` + +### 严格相等 + +普通的相等性检查 `==` 存在一个问题,它不能区分出 `0` 和 `false`: + +```js +alert( 0 == false ); // true +``` + +也同样无法区分空字符串和 `false`: + +```javascript +alert( '' == false ); // true +``` + +**严格相等运算符 `===` 在进行比较时不会做任何的类型转换。** + +```js +alert( 0 === false ); // false,因为被比较值的数据类型不同 +``` + +### null 与 undefined 比较 + +它们不相等,因为它们属于不同的类型。 + +```js +alert( null === undefined ); // false +``` + +JavaScript 存在一个特殊的规则,会判定它们相等。 + +```js +alert( null == undefined ); // true +``` + +`undefined` 和 `null` 在相等性检查 `==` 中不会进行任何的类型转换,它们有自己独立的比较规则,所以除了它们之间互等外,不会等于任何其他的值。 + +```js +alert( null > 0 ); // (1) false, null => 0 +alert( null == 0 ); // (2) false, null => null +alert( null >= 0 ); // (3) true, null => 0 +``` + +### undefined 与其他值比较 + +`undefined` 不应该被与其他值进行比较: + +```javascript +alert( undefined > 0 ); // false +alert( undefined < 0 ); // false +alert( undefined == 0 ); // false +``` + +## 条件分支:if 和 '?' + +### 布尔转换 + +- 数字 `0`、空字符串 `""`、`null`、`undefined` 和 `NaN` 都会被转换成 `false`。因为它们被称为“假值(falsy)”。 +- 其他值被转换为 `true`,所以它们被称为“真值(truthy)”。 + +## 逻辑运算符 + +JavaScript 中有四个逻辑运算符:`||`(或),`&&`(与),`!`(非),`??`(空值合并运算符)。 + +### 或运算寻找第一个真值 + +一个或运算 `||` 的链,将返回第一个真值,如果不存在真值,就返回该链的最后一个值。 + +```js +alert( 1 || 0 ); // 1(1 是真值) + +alert( null || 1 ); // 1(1 是第一个真值) +alert( null || 0 || 1 ); // 1(第一个真值) + +alert( undefined || null || 0 ); // 0(都是假值,返回最后一个值) +``` + +有趣的用法: + +```js +let firstName = ""; +let lastName = ""; +let nickName = "SuperCoder"; + +alert( firstName || lastName || nickName || "Anonymous"); // SuperCoder + +true || alert("not printed"); +false || alert("printed"); +``` + +### 与运算寻找第一个假值 + +```js +// 如果第一个操作数是真值, +// 与运算返回第二个操作数: +alert( 1 && 0 ); // 0 +alert( 1 && 5 ); // 5 + +// 如果第一个操作数是假值, +// 与运算将直接返回它。第二个操作数会被忽略 +alert( null && 5 ); // null +alert( 0 && "no matter what" ); // 0 + +alert( 1 && 2 && null && 3 ); // null +alert( 1 && 2 && 3 ); // 3,最后一个值 +``` + +### 与运算 `&&` 在或运算 `||` 之前进行 + +与运算 `&&` 的优先级比或运算 `||` 要高。 + +所以代码 `a && b || c && d` 跟 `&&` 表达式加了括号完全一样:`(a && b) || (c && d)`。 + +### !(非) + +两个非运算 `!!` 有时候用来将某个值转化为布尔类型: + +```javascript +alert( !!"non-empty string" ); // true +alert( !!null ); // false +alert( Boolean("non-empty string") ); // true +alert( Boolean(null) ); // false +``` + +也就是,第一个非运算将该值**转化为布尔类型并取反**,第二个非运算**再次取反**。最后我们就得到了一个任意值到布尔值的转化。 + +非运算符 `!` 的优先级在所有逻辑运算符里面最高,所以它总是在 `&&` 和 `||` 之前执行。 + +## 空值合并运算符 '??' + +由于它对待 `null` 和 `undefined` 的方式类似,所以在本文中我们将使用一个特殊的术语对其进行表示。为简洁起见,当一个值既不是 `null` 也不是 `undefined` 时,我们将其称为“已定义的(defined)”。 + +`a ?? b` 的结果是: + +- 如果 `a` 是已定义的,则结果为 `a`, +- 如果 `a` 不是已定义的,则结果为 `b`。 + +我们可以使用我们已知的运算符重写 `result = a ?? b`,像这样: + +```javascript +result = (a !== null && a !== undefined) ? a : b; +``` + +### 与 `||` 比较 + +它们之间重要的区别是: + +- `||` 返回第一个 **真** 值。 +- `??` 返回第一个 **已定义的** 值。 + +```js +let height = 0; + +alert(height || 100); // 100 +alert(height ?? 100); // 0 +``` + +## "switch" 语句 + +### 类型很关键 + +强调一下,这里的相等是严格相等。被比较的值必须是相同的类型才能进行匹配。 + +比如,我们来看下面的代码: +```js +let arg = prompt("Enter a value?") +switch (arg) { + case '0': + case '1': + alert( 'One or zero' ); + break; + + case '2': + alert( 'Two' ); + break; + + case 3: + alert( 'Never executes!' ); + break; + default: + alert( 'An unknown value' ) +} +``` + +1. 在 `prompt` 对话框输入 `0`、`1`,第一个 `alert` 弹出。 +2. 输入 `2`,第二个 `alert` 弹出。 +3. 但是输入 `3`,因为 `prompt` 的结果是字符串类型的 `"3"`,不严格相等 `===` 于数字类型的 `3`,所以 `case 3` 不会执行!因此 `case 3` 部分是一段无效代码。所以会执行 `default` 分支。 + +## 函数 + +```js +function name(parameter1, parameter2, ... parameterN) { + ...body... +} + +name(); +``` + +### 参数默认值 + +```js +function showMessage(from, text = "no text given") { + alert( from + ": " + text ); +} + +showMessage("Ann"); // Ann: no text given +``` + +```js +function showMessage(from, text = anotherFunction()) { + // anotherFunction() 仅在没有给定 text 时执行 + // 其运行结果将成为 text 的值 +} +``` + +### 后备的默认参数 + +有些时候,将参数默认值的设置放在函数执行(相较更后期)而不是函数声明时,也行得通。 + +我们可以通过将参数与 `undefined` 进行比较,来检查该参数是否在函数执行期间被传递进来: + +```js +function showCount(count) { + // 如果 count 为 undefined 或 null,则提示 "unknown" + alert(count ?? "unknown"); +} + +showCount(0); // 0 +showCount(null); // unknown +showCount(); // unknown +``` + +### 返回值 + +**空值的** `return` **或没有** `return` **的函数返回值为** `undefined`。 + +```js +function doNothing() { /* 没有代码 */ } + +function doNothing() { + return; + // return undefined; +} + +alert( doNothing() === undefined ); // true +``` + +## 函数表达式