在 JavaScript 中,共有 6 種數據類型,其中有 5 種簡單數據類型(String、Number、Boolean、Undefined、Null)和 1 種復雜數據類型(Object)。
## String 類型
`Strinng` 類型,即字符串類型,一般是包含在雙引號(")或單引號(')之內。字符串類型有一個特點,就是一但創建,就不能改變它的值,如果需要改變,只能是將原來的字符串銷毀,重新創建一個字符串。
~~~
var msg = "Howie"; //定義了一個變量 name ,值為字符串類型的 "howie"
var sex = '男'; //單引號也可以定義字符串
var msg = "Hello " + msg; //此時會重新創建一個新的 9 位數的字符串,再將原來的字符串銷毀掉
~~~
* 將其它類型轉換為字符串
想要將其它類型轉換成字符串類型,需要使用到 `toString()`方法
~~~
var age = 20; //此時的值為一個 number 類型
var ageString = age.toString(); //此時變量 ageString 的值已經變為字符串類型的 “20”了
var flag = true; //此時的值為 boolean 型
var flagStrig = flag.toString(); //此時的值已經是字符串類型的 “true”了
~~~
>[danger] 字符串、數值型、布爾型和對象都會有一個 `toString()` 方法,但 `Null` 和 `Undefined` 沒有該方法
如果不知道需要轉換的值是什么類型,則可以使用 `String()` 方法進行轉換,如果是 `null` 類型,則會轉換為 `"null"`,如果是 `undefined` 類型,則會轉換為 `"undefined"` 。
~~~
var value1 = 10;
var value2 = true;
var value3 = null;
var value4;
alert(String(value1)); // "10"
alert(String(value2)); // "true"
alert(String(value3)); // "null"
alert(String(value4)); // "undefined"
~~~
>[danger] 當然,除了上面這兩種方法可以將其它類型轉換為字符串類型,使用操作符加號(+)也可以進行轉換。
* 字符字面量
String 數據類型包含一些特殊的字符字面量,也叫轉義序列,用于表示非打印字符,或者具有其他用途的字符。
~~~
\n 換行
\t 制表
\b 空格
\r 回車
\f 進紙
\\ 斜杠
\' 單引號( ' ),在用單引號表示的字符串中使用。例如: 'He said, \'hey.\''
\" 雙引號( " ),在用雙引號表示的字符串中使用。例如: "He said, \"hey.\""
\xnn 以十六進制代碼 nn 表示的一個字符(其中 n 為0~F)。例如, \x41 表示 "A"
\unnnn 以十六進制代碼 nnnn 表示的一個Unicode字符(其中 n 為0~F)。例如, \u03a3 表示希臘字符Σ
~~~
## Number 類型
Number 類型,即數值類型,包含整數類型及浮點類型,包含八進制、十進制及16進制
~~~
var num1 = 20; //最常用的 10 進制整數
var num2 = 3.14; //數值型中的浮點數
var num3 = 075; //8 進制,0 開頭,其余位數為 0-7
var num4 = 080; //無效的 8 進制,會解析成為 10 進制的 80
var num5 = 059; //無效的 8 進制,會解析成為 10 進制的 59
var num6 = 0x9A5E; //16 進制,0x 開頭,其余位數為 0-F,此值轉為 10 進制為 39518
~~~
Number 類型分為兩種,即整型和浮點型
1. 整型即平時所說的整數,包含 10 進制整數、8 進制整數和 16 進制整數。
1. 浮點型即平時所說的小數,最大的特點就是有一個小數點,并且小數點后面至少得有一位數字,浮點型的最高精度是17位小數,但精度遠不如整數,如 `0.1 + 0.2` 的結果并不等于 `0.3` 而是 `0.30000000000000004`,是不是很吃驚?這是因為使用基于IEEE754 數值的浮點計算的通病,并不是ECMAScript 才會這樣,其它語言使得這種格式的也會存在這個問題。
~~~
var a = 0.2;
var b = 0.1;
if(a+b == 0.3){
alert('等于');
}else{
alert('不等于');
}
//結果是 “不等于”
~~~
* 儲存范圍:
在大多數瀏覽器中,最大值為 `1.7976931348623157e+308`,如果超出這個值,就會自動轉為 `Infinity` (正無窮),最小值為 `5e-324`,如果是負數溢出,則會自動轉為 `-Infinity`(負無窮)
判斷當前瀏覽器的最大值可以使用 `Number.MAX_VALUE`,判斷當前瀏覽器的最小值可以使用 `Number.MIN_VALUE`。
~~~
alert(isFinite(5 / 0); //true 溢出,0不能作為除數進行運算
~~~
>[danger] 判斷一個值是否溢出,可以使用 `isFinite()` 方法,如果沒有溢出,返回的是`true`,溢出則返回 `false`
* NaN
NaN(Not a Number),即不是數值的數值類型,在 ECMAScript 中,當運算無法返回正常數值時,就會返回 `NaN`。值得注意的是,任何值與 `NaN` 進行運算后返回值均是 `NaN`,并且`NaN`不與任何值相等,包括`NaN`本身。
判斷某個值是否是 `NaN`,可以使用 `isNaN()`函數,該函數接受一個參數,這個參數可以是任何類型,如果是`NaN`則返回 `true`,否則返回`false`。
~~~
alert(isNaN(NaN)); // true
alert(isNaN(20)); // false
alert(isNaN(true)); // false 因為 true 會自動轉換為1
alert(isNaN("8")) // fals 因為會被轉換為 8
alert(isNaN("Howie")); // true 因為轉換后不是一個數字
alert(NaN == NaN); // false NaN不與任何值相等,包括NaN自己
~~~
* 將其它類型轉換為數值型
將其它類型轉換為數值型,有三個函數:`Number()`、`parseInt()`和`parseFloat()`,其中`Number()`函數可以將任何數據類型轉換為數值型,`parseInt()`和`parseFloat()`只能將字符串類型轉換為數值型。而這三個函數對同一個數據轉換的結果可能會不同,下面看這三個函數的區別:
1.Number()函數
`Number()`函數默認會將數據轉換為10進制數值型,如果不能轉為數值型,則返回 `NaN`。
~~~
Number(10); // 10 如果本身就是數字,則會原樣輸出
Number("3.14"); // 3.14 字符串類型的"3.14"會被轉換為數值型的 3.14
Number("0010"); // 10 字符串類型的"10"會轉換為數值型的 10,忽略前導 0
Number("10abc"); // NaN 無法轉換,返回 NaN
Number(true); // 1 boolean 類型的 true 會轉換為 1
Number(false); // 0 boolean 類型的 fasle 會轉換為 0
Number(undefined); // NaN undefined 會轉換為 NaN
Number(null); // 0 Null 直接轉換為 0
Number("0xa15"); // 2581 會直接轉為 10 進制
Number(""); // 0 空字符串會直接被轉換為 0
~~~
>[danger] 如果是對象,則調用對象的 valueOf()方法,然后依照前面的規則轉換返回的值。如果轉換的結果是 NaN,則調用對象的 toString()方法,然后再次依照前面的規則轉換返回的字符串值
由于在實際使用中,`Number()` 函數轉換起來過程比較復雜,所以使用的較少
2. parseInt() 函數
`parseInt()`函數是將字符串類型轉為數值型的整型,從第一個字符開始找,如果遇到 `0` 直接忽略,繼續向后找,如果遇見正負號或數字,則開始,直到遇到其它字符,則結束,如果一直未遇見其它字符串,則會一直找到字符串末尾。不論是遇到八進制還是十六進制,一律轉為十進制。
~~~
var num1 = parseInt("1234blue"); // 1234
var num2 = parseInt(""); // NaN
var num3 = parseInt("a123def"); // NaN
var num4 = parseInt(22.5); // 22
var num5 = parseInt("070"); // 70 // ECMAScrpt 會認為是10進制
var num6 = parseInt("70"); // 70(十進制數)
var num7 = parseInt("0xf"); // 15(十六進制數)
var num8 = parseInt("-8abc"); // -8
~~~
因為在 ECMAScript 5 中,像`070`這種本來應該是 8 進制,但是 ECMAScript 5 認為這是十進制的前導 0,會直接忽略,解析出來的是十制制的 70,所以在 ECMAScript 5 中,`parseInt()`函數提供了第二個參數,八進制直接寫 8,16 進制直接寫 16,如:
~~~
var num1 = parseInt("070",8); // 56
var num2 = parseInt("0x99",16); // 153
var num3 = parseInt("AB"); // NaN
var num4 = parseInt("AB",16); // 171 同樣的字符串,加上第二個參數 16,就會被認為是 16 進制
var num5 = parseInt("101",2); // 5 會被認為是 2 進制
var num6 = parseInt("102",2); // NaN 不合法的 2 進制會被轉為 NaN
~~~
3. parseFloat()函數
與` parseInt()`函數類似,`parseFloat()`也是從第一個字符開始解析每個字符。而且也是一直解析到字符串末尾,或者解析到遇見一個無效的浮點數字字符為止。也就是說,字符串中的第一個小數點是有效的,而第二個小數點就是無效的了,因此它后面的字符串將被忽略。舉例來說,"22.34.5"將會被轉換為 22.34。
~~~
var num1 = parseFloat("1234blue"); //1234 (整數)
var num2 = parseFloat("0xA"); //0
var num3 = parseFloat("22.5"); //22.5
var num4 = parseFloat("22.34.5"); //22.34
var num5 = parseFloat("0908.5"); //908.5
var num6 = parseFloat("3.125e7"); //31250000
~~~
>[danger] 建議在使用`parseInt()` 函數時,始終都加上第二個參數,通常都是使用的十進制,所以一般第二個參數為 10
`parseFloat()`是沒有第二個參數的,所有的字符串都會被轉為十進制數值。
### Boolean 類型
***
Boole 類型也叫“布爾型”,該類型有兩個字面值:`true`(真)和`false`(假)。這兩個值只能用小寫,大寫或大小寫混合都屬于錯誤語法。布爾型通常用于分支流程控制語句判斷。其定義方法為:
~~~
var found = true;
var lost = flase;
~~~
* 將其它類型轉換為布爾型
如果想要將其它類型的值轉換為布爾型,可以使用 `Boolean()`函數。下面列出各種數據類型轉換為布爾型的情況:
| 數據類型 | 轉換為`true`的值 | 轉換為 `false` 的值 |
| --- | --- | --- |
| Boolean |`true` | `false` |
| String | 任何非空自符串,包括`"0"` | 空字符串(`""`或`''`) |
| Number | 任何非零數值 | `0`和`NaN` |
| Object | 任何對象,包括`[]`和`{}` | `null` |
| Undefined | | `undefined` |
### Undefined 類型
***
`Undefined` 類型只有一個值,即 `undefined`,一般用 `var` 關鍵字定義的變量,但未賦值或直接賦值為`undefined`時,此時的值就是`undefined`。
~~~
var name = ''; // undefined
var email = undefined // undefined
~~~
### Null 類型
***
Null類型也是只有一個值,就是`null`,用來表示尚未存在的對象,常用來表示函數企圖返回一個不存在的對象。
* `null` 與 `undefined` 的區別
說區別之前,先說一下`null`和`undefined`相同的地方。`null`和`undefined`在轉換為布爾值時,都會被轉換為`false`。
~~~
alert(null == undefined); // true
~~~
區別:
`null`表示"沒有對象",即該處不應該有值。而`undefined`表示"缺少值",就是此處應該有一個值,但是還沒有定義。
`null`在用`Number()`函數轉為數值型時會被轉換為`0`,而`undefined`會被轉換為`NaN`,`parseInt()`和`parseFloat()`轉換時,兩者都會被轉換為`NaN`。
~~~
Number( null ); // 0
Number( undefined ); // NaN
parseInt( undefined ); // NaN
parseFloat( null ); // NaN
~~~
>[danger] 如果使用`typeof`操作符來判斷`null`的話,那么得到的結果將會是`object`
### Object 類型
***
Object 類型即對象類型,而對象其實就是一組數據和功能的集合。對象可以通過執行 new 操作符后跟要創建
的對象類型的名稱來創建。
~~~
var obj = new Object();
var obj2 = nwe Object;
~~~
>[danger] 如果在創建對象時,不給構造函數傳送參數,那么后面那對小括號是可以省略的,但并不推薦這么做。
Object 的每個實例都具有以下的屬性和方法
* `constructor`:保存著用于創建當前對象的函數。對于前面的例子而言,構造函數(`constructor`)就是 `Object()`。
* `hasOwnProperty(propertyName)`:用于檢查給定的屬性在當前對象實例中(而不是在實例的原型中)是否存在。其中,作為參數的屬性名(`propertyName`)必須以字符串形式指定(例如: `o.hasOwnProperty("name")`)。
* `isPrototypeOf(object)`:用于檢查傳入的對象是否是傳入對象的原型。
* `propertyIsEnumerable(propertyName)`:用于檢查給定的屬性是否能夠使用 `for-in` 語句來枚舉。與` hasOwnProperty()`方法一樣,作為參數的屬性名必須以字符串形式指定。
* `toLocaleString()`:返回對象的字符串表示,該字符串與執行環境的地區對應。
* `toString()`:返回對象的字符串表示。
* `valueOf()`:返回對象的字符串、數值或布爾值表示。通常與 toString()方法的返回值相同。
### typoof 操作符
***
如果不確定某個數據是哪種類型,可以使用 `typeof`操作符來判斷。`typeof`會將判斷結果以自符串名形式返回。語法如下
~~~
var name = "Howie";
var age = 20;
alert(typeof name); // string
alert(typeof age); // number
alert(typeof true); // boolean
alert(typeof undefined);// undefined
alert(typeof null); // object
alert(typeof {}); // object
alert(typeof []); // object
~~~
>[danger] typeof 的返回值是該數據類型名稱的字符串,因為歷史原因, `null`會返回`object`,因為特殊值`null`會被當做一個空的對象引用