JavaScript的數據類型

js數據類型.png

JavaScript中總共有6種數據類型。可分為兩大類:簡單數據類型復雜數據類型

說明一下:上面這句話現在來說應該是不對的,因為ES6中新增了數據類型。不過我們暫時不涉及ES6。

簡單數據類型即基本數據類型,共有5種:UndefinedNullBooleanNumberString,其值分別對應undefinednull、布爾值truefalse數值字符串值。

復雜數據類型只有一種,就是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中,FunctionObject的關系很微妙也很復雜,需要對原型構造、原型鏈等一些知識有所理解之后才能進一步理解這兩者的關系。不過這并不影響我們現在的理解,站在數據類型的角度,我們可以明確地認為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個值:truefalse
  • 其他所有數據類型都有與truefalse對應的值,通過轉型函數Boolean()可以得到某個值所對應的布爾值。如:
var s = 'Hello';
console.log(Boolean(s));    //true

轉換規則如下表:

Boolean()轉型函數的轉換規則

在流程控制語句中,比如在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的結果就是NaNNaN的任何操作都會返回NaNNaN與任何值都不相等,包括它本身:NaN === NaN會返回false
  • 另外,還有parseInt()parseFloat()等常用轉型函數的用法自行Google即可。

String 類型
字符串類型。在這里了解幾個點即可,之后在引用類型等處會做詳細介紹。

  • 單引號''和雙引號""都可以使用且沒有任何差別。

  • ECMAScript 中的字符串是不可變的,也就是說,字符串一旦創建,它們的值就不能改變。要改變某個變量保存的字符串,首先要銷毀原來的字符串,然后再用另一個包含新值的字符串填充該變量。——《J3》

  • 將某個值轉換為字符串,可以使用以下3種方法:toString()方法、轉型函數String()、加空串+ ''

Object 類型
對象類型。Object是所有對象的基礎,其所具有的屬性和方法其他對象也必然擁有。這里只列幾個Object的屬性和方法:

  • constructor:保存著用于創建當前對象的構造函數;
  • hasOwnProperty('屬性名'):用于檢查給定的屬性在當前對象實例中是否存在(不查找原型鏈);
  • isPrototypeOf(某一Object類型):用于檢查對象實例是否是傳入對象的原型;
  • propertyIsEnumerable('屬性名'):用于檢查傳入的屬性是否可以枚舉;
  • toString():返回該對象的字符串表示;
  • toLocalString():同上,與所在地區有關
  • valueOf():返回對象最有意義的那個值,返回的可能是字符串、數值或者布爾值。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容