運算符:也叫操作符,是一種符號。通過運算符可以對一個或多個值進行運算,並獲取運算結果。
表達式:由數字、運算符、變量的組合(組成的式子)。
表達式最終都會有一個運算結果,我們將這個結果稱為表達式的返回值。
比如:`+`、`*`、`/`、`(` 都是運算符,而`(3+5)/2`則是表達式。
比如:typeof 就是運算符,可以來獲得一個值的類型。它會將該值的類型以字符串的形式返回,返回值可以是 number string boolean undefined object。
一、運算符
分類
- 算數運算符
- 自增/自減運算符
- 一元運算符
- 邏輯運算符
- 賦值運算符
- 比較運算符
- 三元運算符(條件運算符)
1、算數運算符
**算術運算符**:用於執行兩個變量或值的算術運算。
常見的算數運算符有以下幾種:
| 運算符 | 描述 |
| :---------------- | :-------: |
| + | 加、字符串連接 |
| - | 減 |
| * | 乘 |
| / | 除 |
| % | 獲取余數(取余、取模) |
**求余的舉例**:
假設用戶輸入345,怎么分別得到3、4、5這三個數呢?
得到3的方法:345 除以100,得到3.45然后取整,得到3。即:parseInt(345/100)
得到4的方法:345 除以100,余數是45,除以10,得到4.5,取整。即:parseInt(345 % 100 / 10)
得到5的方法:345 除以10,余數就是5。即:345 % 10
算數運算符的運算規則
(1)先算乘除、后算加減。
(2)小括號`( )`:能夠影響計算順序,且可以嵌套。沒有中括號、沒有大括號,只有小括號。
(3)百分號:取余。只關心余數。
舉例1:(取余)
console.log(3 % 5);
輸出結果為3。
舉例2:(注意運算符的優先級)
var a = 1 + 2 * 3 % 4 / 3;
結果分析:
原式 = 1 + 6 % 4 / 3 = 1 + 2 / 3 = 1.66666666666666
浮點數運算的精度問題
浮點數值的最高精度是 17 位小數,但在進行算術計算時,會丟失精度,導致計算不夠准確。比如:
console.log(0.1 + 0.2); // 運算結果不是 0.3,而是 0.30000000000000004
console.log(0.07 * 100); // 運算結果不是 7,而是 7.000000000000001
因此,不要直接判斷兩個浮點數是否相等。
2、自增和自減
自增 `++`
自增分成兩種:`a++`和`++a`。
(1)一個變量自增以后,原變量的值會**立即**自增1。也就是說,無論是 `a++` 還是`++a`,都會立即使原變量的值自增1。
(2)**我們要注意的是**:`a`是變量,而`a++`和`++a`是**表達式**。
那這兩種自增,有啥區別呢?區別是:`a++` 和 `++a`的值不同:(也就是說,表達式的值不同)
- `a++`這個表達式的值等於原變量的值(a自增前的值)。你可以這樣理解:先把 a 的值賦值給表達式,然后 a 再自增。
- `++a`這個表達式的值等於新值 (a自增后的值)。 你可以這樣理解:a 先自增,然后再把自增后的值賦值給表達式。
自減 `-- `
原理同上。
開發時,大多使用后置的自增/自減,並且代碼獨占一行,例如:`num++`,或者 `num--`。
### 代碼舉例
```javascript
var n1 = 10;
var n2 = 20;
var result1 = n1++;
console.log(n1); // 11
console.log(result1); // 10
result = ++n1;
console.log(n1); //12
console.log(result); //12
var result2 = n2--;
console.log(n2); // 19
console.log(result2); // 20
result2 = --n2;
console.log(n2); // 18
console.log(result2); // 18
```
3、一元運算符
一元運算符,只需要一個操作數。
常見的一元運算符如下。
typeof
typeof就是典型的一元運算符,因為后面只跟一個操作數。
舉例如下:
```javascript
var a = '123';
console.log(typeof a); // 打印結果:string
```
正號 `+`
(1)正號不會對數字產生任何影響。比如說,`2`和`+2`是一樣的。
(2)我們可以對一個其他的數據類型使用`+`,來將其轉換為number【重要的小技巧】。比如:
```javascript
var a = true;
a = +a; // 注意這行代碼的一元運算符操作
console.log('a:' + a);
console.log(typeof a);
console.log('-----------------');
var b = '18';
b = +b; // 注意這行代碼的一元運算符操作
console.log('b:' + b);
console.log(typeof b);
```
打印結果:
```
a:1
number
-----------------
b:18
number
```
負號 `-`
負號可以對數字進行取反。
4、邏輯運算符
邏輯運算符有三個:
- `&&` 與(且):兩個都為真,結果才為真。
- `||` 或:只要有一個是真,結果就是真。
- `!` 非:對一個布爾值進行取反。
連比的寫法:
來看看邏輯運算符連比的寫法。
舉例1:
```javascript
console.log(3 < 2 && 2 < 4);
```
輸出結果為false。
舉例2:(判斷一個人的年齡是否在18~60歲之間)
```javascript
var a = prompt("請輸入您的年齡");
alert(a>=18 && a<= 65);
```
PS:上面的這個`a>=18 && a<= 65`千萬別想當然的寫成` 18<= a <= 65`,沒有這種語法。
注意事項
(1)能參與邏輯運算的,都是布爾值。
(2)JS中的`&&`屬於**短路**的與,如果第一個值為false,則不會看第二個值。舉例:
```javascript
//第一個值為true,會檢查第二個值
true && alert("看我出不出來!!"); // 可以彈出 alert 框
//第一個值為false,不會檢查第二個值
false && alert("看我出不出來!!"); // 不會彈出 alert 框
```
(3)JS中的`||`屬於**短路**的或,如果第一個值為true,則不會看第二個值。舉例:
(4)如果對**非布爾值**進行邏輯運算,則會**先將其轉換為布爾值**,然后再操作。舉例:
```javascript
var a = 10;
a = !a;
console.log(a); // false
console.log(typeof a); // boolean
```
上面的例子,我們可以看到,對非布爾值進行`!`操作之后,返回結果為布爾值。
非布爾值的與或運算【重要】
> 之所以重要,是因為在實際開發中,我們經常用這種代碼做容錯處理或者兜底處理。
非布爾值進行**與或運算**時,會先將其轉換為布爾值,然后再運算,但返回結果是**原值**。比如說:
```javascript
var result = 5 && 6; // 運算過程:true && true;
console.log('result:' + result); // 打印結果:6(也就是說最后面的那個值。)
```
上方代碼可以看到,雖然運算過程為布爾值的運算,但返回結果是原值。
那么,返回結果是哪個原值呢?我們來看一下。
**與運算**的返回結果:(以兩個非布爾值的運算為例)
- 如果第一個值為false,則直接返回第一個值;不會再往后執行。
- 如果第一個值為true,則返回第二個值(如果所有的值都為true,則返回的是最后一個值)。
**或運算**的返回結果:(以兩個非布爾值的運算為例)
- 如果第一個值為true,則直接返回第一個值;不會再往后執行。
- 如果第一個值為false,則返回第二個值((如果所有的值都為false,則返回的是最后一個值)。
實際開發中,我們經常是這樣來做「容錯處理」的:
當成功調用一個接口后,返回的數據為 result 對象。這個時候,我們用變量 a 來接收 result 里的圖片資源。通常的寫法是這樣的:
```javascript
if (result.resultCode == 0) {
var a = result && result.data && result.data.imgUrl || 'http://img.smyhvae.com/20160401_01.jpg';
}
```
上方代碼的意思是,獲取返回結果中的`result.data.imgUrl`這個圖片資源;如果返回結果中沒有 `result.data.imgUrl` 這個字段,就用 `http://img.smyhvae.com/20160401_01.jpg` 作為**兜底**圖片。這種寫法,在實際開發中經常用到。
5、賦值運算符
可以將符號右側的值賦值給符號左側的變量。
舉例:
- `=` 直接賦值。比如 `var a = 5`
- `+=`。a += 5 等價於 a = a + 5
- `-=`。a -= 5 等價於 a = a - 5
- `*=`。a *= 5 等價於 a = a * 5
- `/=`。a /= 5 等價於 a = a / 5
- `%=`。a %= 5 等價於 a = a % 5
6、比較運算符
比較運算符可以比較兩個值之間的大小關系,如果關系成立它會返回true,如果關系不成立則返回false。
比較運算符有很多種,比如:
```
> 大於號
< 小於號
>= 大於或等於
<= 小於或等於
== 等於
=== 全等於
!= 不等於
!== 不全等於
```
**比較運算符,得到的結果都是布爾值:要么是true,要么是false**。
舉例如下:
```javascript
var result = 5 > 10; // false
```
非數值的比較
(1)對於非數值進行比較時,會將其轉換為數字然后再比較。
舉例如下:
```javascript
console.log(1 > true); //false
console.log(1 >= true); //true
console.log(1 > "0"); //true
//console.log(10 > null); //true
//任何值和NaN做任何比較都是false
console.log(10 <= "hello"); //false
console.log(true > false); //true
```
(2)特殊情況:如果符號兩側的值都是字符串時,**不會**將其轉換為數字進行比較。比較兩個字符串時,比較的是字符串的**Unicode編碼**。【非常重要,這里是個大坑,很容易踩到】
比較字符編碼時,是一位一位進行比較。如果兩位一樣,則比較下一位。
比如說,當你嘗試去比較`"123"`和`"56"`這兩個字符串時,你會發現,字符串"56"竟然比字符串"123"要大。也就是說,下面這樣代碼的打印結果,其實是true:(這個我們一定要注意,在日常開發中,很容易忽視)
```javascript
// 比較兩個字符串時,比較的是字符串的字符編碼,所以可能會得到不可預期的結果
console.log("56" > "123"); // true
```
**因此**:當我們在比較兩個字符串型的數字時,**一定一定要先轉型**再比較大小,比如 `parseInt()`。
(3)任何值和NaN做任何比較都是false。
`==`符號的強調
注意`==`這個符號,它是**判斷是否等於**,而不是賦值。
(1)`== `這個符號,還可以驗證字符串是否相同。例如:
```javascript
console.log("我愛你中國" == "我愛你中國"); // 輸出結果為true
```
(2)`== `這個符號並不嚴謹,會做隱式轉換,將不同的數據類型,**轉為相同類型**進行比較(大部分情況下,都是轉換為數字)。例如:
```javascript
console.log("6" == 6); // 打印結果:true。這里的字符串"6"會先轉換為數字6,然后再進行比較
console.log(true == "1"); // 打印結果:true
console.log(0 == -0); // 打印結果:true
console.log(null == 0); // 打印結果:false
```
(3)undefined 衍生自 null,所以這兩個值做相等判斷時,會返回true。
```javascript
console.log(undefined == null); //打印結果:true。
```
(4)NaN不和任何值相等,包括他本身。
```javascript
console.log(NaN == NaN); //false
console.log(NaN === NaN); //false
```
問題:那如果我想判斷 b的值是否為NaN,該怎么辦呢?
答案:可以通過isNaN()函數來判斷一個值是否是NaN。舉例:
```javascript
console.log(isNaN(b));
```
如上方代碼所示,如果 b 為 NaN,則返回true;否則返回false。
`===`全等符號的強調
**全等在比較時,不會做類型轉換**。如果要保證**絕對等於(完全等於)**,我們就要用三個等號`===`。例如:
```javascript
console.log("6" === 6); //false
console.log(6 === 6); //true
```
上述內容分析出:
- `==`兩個等號,不嚴謹,"6"和6是true。
- `===`三個等號,嚴謹,"6"和6是false。
另外還有:**`==`的反面是`!=`,`===`的反面是`!==`**。例如:
```javascript
console.log(3 != 8); //true
console.log(3 != "3"); //false,因為3=="3"是true,所以反過來就是false。
console.log(3 !== "3"); //true,應為3==="3"是false,所以反過來是true。
```
7、三元運算符
三元運算符也叫條件運算符。
語法:
```
條件表達式 ? 語句1 : 語句2;
```
**執行的流程**:
條件運算符在執行時,首先對條件表達式進行求值:
- 如果該值為true,則執行語句1,並返回執行結果
- 如果該值為false,則執行語句2,並返回執行結果
如果條件的表達式的求值結果是一個非布爾值,會將其轉換為布爾值然后再運算。
二、運算符的優先級
運算符的優先級如下:(優先級從高到低)
- `.`、`[]`、`new`
- `()`
- `++`、`--`
- `!`、`~`、`+`(單目)、`-`(單目)、`typeof`、`void`、`delete`
- `%`、`*`、`/`
- `+`(雙目)、`-`(雙目)
- `<<`、`>>`、`>>>`
- 關系運算符:`<`、`<=`、`>`、`>=`
- `==`、`!==`、`===`、`!==`
- `&`
- `^`
- `|`
- `&&`
- `||`
- `?:`
- `=`、`+=`、`-=`、`*=`、`/=`、`%=`、`<<=`、`>>=`、`>>>=`、`&=`、`^=`、`|=`
- `,`
注意:邏輯與 `&&` 比邏輯或 `||` 的優先級更高。
備注:你在實際寫代碼的時候,如果不清楚哪個優先級更高,可以把括號運用上。
三、Unicode 編碼
引申Unicode編碼的使用。
1、在字符串中可以使用轉義字符輸入Unicode編碼。格式如下:
```
\u四位編碼
```
舉例如下:
```javascript
console.log("\u2600"); // 這里的 2600 采用的是16進制
console.log("\u2602"); // 這里的 2602 采用的是16進制。
```
打印結果:

2、我們還可以在 HTML 網頁中使用Unicode編碼。格式如下:
```
&#四位編碼;
```
PS:我們知道,Unicode編碼采用的是16進制,但是,這里的編碼需要使用10進制。
舉例如下:
```html
<h1 style="font-size: 100px;">⚄</h1>
```
效果:

