JavaScript中總共有6種數據類型。可分為兩大類:簡單數據類型和復雜數據類型。
說明一下:上面這句話現在來說應該是不對的,因為ES6中新增了數據類型。不過我們暫時不涉及ES6。
簡單數據類型即基本數據類型,共有5種:Undefined、Null、Boolean、Number、String,其值分別對應undefined、null、布爾值true和false、數值、字符串值。
復雜數據類型只有一種,就是Object——對象。JS中的對象就是一組無序鍵值對外面套一個大括號{}所構成。Object非常常用、非常強大、非常有意思,而且對于JS這門語言結構來說,Object意義不一般。這些,之后的文章再來討論吧。
ECMAScript不支持任何創建自定義類型的機制,而所有值最終都將是上述6種數據類型之一。
上面這句話引用自《JavaScript高級程序設計(第3版)》(之后簡稱J3),其實不用多解釋,這句話說的很明白了。這就是說,你“定義”的所有變量,它的類型都是唯一確定的,必定是上述6種之一。
這里的“定義”兩個字,我加了引號,是想表示這個詞廣義上的意思。在一般的編程語言中,當你想“定義”一個變量時,不外乎3種情況:聲明,定義,初始化。聲明就如字面意思一樣,僅僅是宣稱一個命名;定義就是給這個命名分配內存空間;初始化則是給這個內存空間賦值。顯然,他們3個是循序漸進的。在JS中,我們所說的初始化其實做的事是分配內存并賦值,也就是定義并初始化。所以在JS中,我們一般只說聲明和初始化。看如下代碼:
var value1; //聲明變量
value1 = 'Hello'; //(定義并)初始化
var value2 = 'Hello'; //聲明并初始化
再摘錄博客園的一句話,對于聲明、定義與初始化大家應該就能完全理解了:
因為javascript為動態語言,其變量并沒有固定的類型,其存儲空間大小會隨初始化與賦值而變化,所以其變量的“定義”就不像傳統的靜態語言一樣了,其定義顯得無關緊要。
http://www.cnblogs.com/silentjesse/p/4024536.html
接下來,讓我們來具體看一看JavaScript的6種數據類型。
不過首先,必須先了解一個操作符—typeof
。顧名思義,這個操作符的作用就是返回某個變量的數據類型。對某個值使用typeof
操作符始終會返回以下6個字符串之一:'undefined'
、'boolean'
、'number'
、'string'
、'object'
、'function'
。你肯定發現了一個問題,就是這6個字符串為什么不和6種數據類型完全對應?沒有'null'嗎?'function'
又是哪兒來的?請看下面的測試代碼:
console.log(typeof null) //'object'
var f = function(){};
console.log(typeof f); //'function'
注意到,對Null
類型的唯一值null
使用typeof
操作符返回的不是什么'null',而是'object'
,這是為什么呢?這是因為null
這個值比較特殊,它是基本數據類型Null
的唯一值,但同時,它又被認為是一個空的對象(Object
)引用。
有些時候,typeof 操作符會返回一些令人迷惑但技術上卻正確的值。比如,調用typeof null會返回"object",因為特殊值null 被認為是一個空的對象引用。——《J3》
對于typeof
可以返回'function'
,這么理解吧:
從技術角度講,函數在ECMAScript 中是對象,不是一種數據類型。然而,函數也確實有一些特殊的屬性,因此通過typeof 操作符來區分函數和其他對象是有必要的。——《J3》
在JS中,Function
和Object
的關系很微妙也很復雜,需要對原型構造、原型鏈等一些知識有所理解之后才能進一步理解這兩者的關系。不過這并不影響我們現在的理解,站在數據類型的角度,我們可以明確地認為Function
就是一類特殊的Object
。至于對一個Function
使用typeof
操作符的返回結果是'function'
而不是'object'
,原因就像書上說的,只是因為我們有必要知道它是一個函數而不是一般的對象。
介紹完typeof
操作符這個實用的工具,下面就真的具體來看看JS的6種數據類型吧。
Undefined 類型
- 只有一個唯一值,即
undefined
。 - 所有只進行了聲明而未初始化的變量,其值都是
undefined
。比如:
var a;
console.log(a); //undefined(注意,這可不是字符串)
需要明白的是,undefined
是一個明確的、合法的值,而不是一個錯誤。真正會導致錯誤的是如下的代碼:
console.log(b); //Uncaught ReferenceError: b is not defined
這行代碼會報一個空引用異常的錯誤,因為變量b沒有聲明。這很好理解。
- 還有一點需要了解,對于上邊兩段示例代碼中的變量 a 和 b,執行
typeof
操作都會返回'undefined'
:
var a;
console.log(typeof a); //'undefined'
console.log(typeof b); //'undefined'
看起來,你可能會覺得對 b 執行typeof
應該報錯才對,但因為typeof
必然會返回6個字符串之一,所以并不會報錯。而且,無論是 a 還是 b,都無法執行真正的操作,那么就讓 b 和 a 一樣返回'undefined'
好了。看一下書上的解釋:
結果表明,對未初始化和未聲明的變量執行typeof 操作符都返回了undefined 值;這個結果有其邏輯上的合理性。因為雖然這兩種變量從技術角度看有本質區別,但實際上無論對哪種變量也不可能執行真正的操作。——《J3》
由此可知,當你使用typeof
操作符檢測變量的數據類型時,如果返回的是'undefined'
,那么這個變量可能是未初始化,也可能是未聲明。因此,從規范性上來說,為了避免這種模糊,我們在定義變量時最好直接進行初始化。這樣的話,如果還返回'undefined'
,那么我們立即就能知道是因為這個變量壓根就沒聲明了。
Null 類型
- 只有一個唯一值,即
null
。 -
null
表示一個空對象(Object
)引用,因此typeof null
會返回'object'
。 - 實際上,
undefined
派生自null
,因此undefined == null
返回true
,但是undefined === null
會返回false
,因為這兩個值的數據類型不一樣。這里補充一下:==
是相等操作符,===
是全等操作符,前者會對操作數自動進行轉型,而后者不會,后者只有在兩個操作數未經轉換就相等的情況下才返回true
。 - 還有一點,如果某個變量用來在以后保存對象,那么最好將其初始化為
null
,以方便區分和判斷。
Boolean 類型
- 布爾類型,有2個值:
true
和false
。 - 其他所有數據類型都有與
true
和false
對應的值,通過轉型函數Boolean()
可以得到某個值所對應的布爾值。如:
var s = 'Hello';
console.log(Boolean(s)); //true
轉換規則如下表:
在流程控制語句中,比如在
if
語句的小括號內,會自動對操作數調用轉型函數Boolean()
再求最終的布爾值。如下:
var s = 'Hello';
if(s){
//do something //后臺自動對s調用轉型函數`Boolean()`,因為s不是空串,會返回true
}
Number 類型
數值類型。了解幾個知識點即可。
- 保存浮點數所需的內存空間是整數值的2倍;
- 永遠不要測試特定的浮點數值,如:
var a = 0.1;
var b = 0.2;
console.log(a + b); //0.30000000000000004 有誤差,并不會是0.3
-
NaN
是一個特殊的Number
值,它的存在是為了避免程序直接報錯,比如0/0
的結果就是NaN
;NaN
的任何操作都會返回NaN
;NaN
與任何值都不相等,包括它本身:NaN === NaN
會返回false
; - 另外,還有
parseInt()
和parseFloat()
等常用轉型函數的用法自行Google即可。
String 類型
字符串類型。在這里了解幾個點即可,之后在引用類型等處會做詳細介紹。
單引號
''
和雙引號""
都可以使用且沒有任何差別。ECMAScript 中的字符串是不可變的,也就是說,字符串一旦創建,它們的值就不能改變。要改變某個變量保存的字符串,首先要銷毀原來的字符串,然后再用另一個包含新值的字符串填充該變量。——《J3》
將某個值轉換為字符串,可以使用以下3種方法:
toString()
方法、轉型函數String()
、加空串+ ''
。
Object 類型
對象類型。Object
是所有對象的基礎,其所具有的屬性和方法其他對象也必然擁有。這里只列幾個Object
的屬性和方法:
-
constructor
:保存著用于創建當前對象的構造函數; -
hasOwnProperty('屬性名')
:用于檢查給定的屬性在當前對象實例中是否存在(不查找原型鏈); -
isPrototypeOf(某一Object類型)
:用于檢查對象實例是否是傳入對象的原型; -
propertyIsEnumerable('屬性名')
:用于檢查傳入的屬性是否可以枚舉; -
toString()
:返回該對象的字符串表示; -
toLocalString()
:同上,與所在地區有關 -
valueOf()
:返回對象最有意義的那個值,返回的可能是字符串、數值或者布爾值。