init
This commit is contained in:
412
JavaScript.md
Normal file
412
JavaScript.md
Normal file
@@ -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
|
||||||
|
```
|
||||||
|
|
||||||
|
## 函数表达式
|
||||||
Reference in New Issue
Block a user