# :-: 易混零散
[TOC]
## 1、NaN == NaN 結果輸出 false
NaN 是一個特殊的 **number** 類型的值。
任何與 NaN 進行運算的結果均為 NaN,所以 NaN 不要用于算術運算。
NaN與自身不相等(NaN也不與任何值相等),所以不要用NaN來做判斷條件。
當我們要判斷一個值是否**不是數值**可以用 **isNaN()** 函數。
```
alert(typeof NaN); //輸出 "number"
alert(NaN + 5); //輸出 "NaN"
alert(NaN == NaN); //輸出 "false"
//------------------- LINE -------------------
alert(isNaN()); //輸出 "true"
alert(isNaN(true)); //輸出 "false"
alert(isNaN(NaN)); //輸出 "true"
alert(isNaN(1024)); //輸出 "false"
alert(isNaN("1024")); //輸出 "false"
alert(isNaN("seeyoubug")); //輸出 "true"
```
## 2、 slice() 和 substring() 和 substr() 函數的異同
(1)、slice 和 substring 和 substr 方法,三者都可以截取子串,都接收一個或兩個參數,第一個接收的參數都是截取子串的**起始位置**,第二個參數,slice 和 substring 都是截取子串的**結束位置** (結束位置不包含在返回的子串內,用區間表示為:**\[起始位置, 結束位置)**,簡記為左閉右開) ,而 substr 是截取子串的**長度**。
```
var str = "seeyoubug";
alert(str.slice(3)); //輸出 "youbug"
alert(str.substring(3)); //輸出 "youbug"
alert(str.substr(3)); //輸出 "youbug"
alert(str.slice(3, 6)); //輸出 "you"
alert(str.substring(3, 6)); //輸出 "you"
alert(str.substr(3, 6)); //輸出 "youbug"
```
(2)、當接收的參數為負數時,slice 方法會用該字符串的長度加上參數,結果作為參數;substr 方法則僅僅是將第一個參數與該字符串長度相加后的結果作為第一個參數;而 substring 方法則將其作為0處理。
```
var str = "seeyoubug";
alert(str.slice(-6)); //輸出 "youbug"
alert(str.substring(-6)); //輸出 "seeyoubug"
alert(str.substr(-6)); //輸出 "youbug"
alert(str.slice(3, -3)); //輸出 "you"
alert(str.substring(3, -3)); //輸出 "see"
alert(str.substr(-3, 3)); //輸出 "bug"
```
str.slice(3, -3) 中參數 -3 相當于 9 + (-3) = 6,也就是等同于 str.slice(3, 6) 。
str.substring(3, -3) 中參數 -3 相當于 0,也就是等同于 str.substring(3, 0) 。
str.substr(-3, 3) 中參數 -3 相當于 6,也就是等同于 str.substr(6, 3) 。
(3)、substring 方法是以兩個參數中較小一個作為起始位置,較大的參數作為結束位置。
```
var str = "seeyoubug";
alert(str.substring(3, -3)); //輸出 "see"
//等同于 ↓
alert(str.substring(3, 0)); //輸出 "see"
//即 ↓
alert(str.substring(0, 3)); //輸出 "see"
```
(4)、slice 方法可從已有的數組中返回選定的元素,不修改原始數組。
```
var arr = ["see", "you", "bug", "1024"];
console.log(arr.slice(-3, -1)); //輸出 ["you", "bug"]
```
## 3、undefined 和 null 和 0 和 NaN 和 空字符串 均為 **false**
## 4、比較數字和字符串的大小
對于字符串比較,在第一個字符串中依次取每個字符的ASCII碼與第二個字符串中對應位置字符的ASCII碼進行數值大小比較,通常兩個首字符不同的ASCII碼值的字符串比較,比較完第一個字符的ASCII碼值就可以得到比較結果,遇到相同的ASCII碼值會繼續取下一位字符來比較,完成比較操作后會返回一個 Boolean 值作為比較結果。
```
alert("Beta" < "ajax"); //輸出 "true"
alert("beta" < "ajax"); //輸出 "false"
alert("ab" < "abc"); //輸出 "true"
alert("" < "c"); //輸出 "true"
```
B 的ASCII碼為 66 ,a 的ASCII碼為 97 ,b 的ASCII碼為 98 。
"Beta" < "ajax" => 首字符ASCII碼比較 66 < 97 返回結果為 true 。
"beta" < "ajax" => 首字符ASCII碼比較 98 < 97 返回結果為 false 。
上面是純字符串的比較,如果是值為數字的字符串比較呢?結果會如何,一起看看下面的例子。
```
alert("512" > "abc"); //輸出 "false"
alert("512" > "1024"); //輸出 "true"
alert( 512 > "1024"); //輸出 "false"
```
"1" 的ASCII碼值為 49 ,"5" 的ASCII碼值為 53 ,a 的ASCII碼為 97。
"512" > "abc" =>首字符ASCII碼比較 53 > 97結果為 false。
"512" > "1024" =>首字符ASCII碼比較 53 > 49 結果為 true。
512 > "1024" => "1024" 會先被隱式轉換成 number 類型再做比較 512 > 1024 結果為 false。
還有下面這種情況也較為特殊。
```
alert(1024 < "abc"); //輸出 "false"
```
按照規則:"abc" 會先被隱式轉換成 number 類型再做比較,我們知道 "abc" 不能轉換成有意義的數字。如果調用 Number() 方法,強制把 "abc" 轉為 number 類型,我們知道結果返回的是 NaN。因為任何包含 NaN 的關系運算符都會返回 false (**!= 和 !== 除外**),因此這里 1024 < NaN 的比較結果為 false 。
**ps:** charCodeAt() 和 String.fromCharCode() 方法為字符和ASCII碼互相轉換的方法。
簡單總結一下:
(1)、純字符串比較,先轉換成ASCII碼再進行數值比較。
(2)、數字和字符串比較,先將字符串隱式轉換成數字再進行數值比較。
(3)、任何包含 NaN 的關系運算符都返回 false 。
## 5、!= 、== 、!== 、=== 之間的區別
先來看看幾個例子
```
alert("1024" == 1024); //輸出 "true"
alert("1024" === 1024); //輸出 "false"
alert("1024" != 1024); //輸出 "false"
alert("1024" !== 1024); //輸出 "true"
```
**ps:** == 和 != 比較,若類型不同,先償試轉換類型,再作值比較,最后返回值比較結果?,而?=== 和 !== 只有在相同類型下,才會比較其值。
幾個比較特例
```
alert(true == 1); //輸出 "true"
alert(false == 0); //輸出 "true"
alert(NaN != NaN); //輸出 "true"
alert(undefined == 0); //輸出 "false"
alert(null == 0); //輸出 "false"
alert(null == undefined); //輸出 "true"
```
true == 1 和 false == 0 比較前會先轉換類型,false 轉換成 0,true 為 1 之后再做值比較。
## 6、+= 、-= 、\*= 、/= 、%= 之間的賦值運算
```
var a = 10, b = 10, c = 10, d = 10, e = 10;
//a = a + 10 <=> a += 10
alert(a += 10); //輸出 "20"
alert(b -= 10); //輸出 "0"
alert(c *= 10); //輸出 "100"
alert(d /= 10); //輸出 "1"
alert(e %= 10); //輸出 "0"
```
## 7、