# :-: 易混零散
[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、