1. 程式人生 > >JavaScript變數與資料型別詳解

JavaScript變數與資料型別詳解

變數

變數來源於數學,是計算機語言中能儲存計算結果或能表示值抽象概念。變數可以通過變數名訪問。

變數的作用就是用於儲存值。

語法:

宣告變數時,總是以關鍵字var打頭。任何情況下都應該這樣做。然後給變數指定名稱。在宣告變數時,也可以給它賦值,方法是在變數名後面加上等號和值。賦值語句總是以分號結束。

var 變數名;
//或
var 變數名 = 值;

說明:儘管省略關鍵字var,JavaScript也不會報錯,但是這會導致變數變成全域性變數,在JavaScript使用全域性變數並不是一個好習慣。分號也不是必須的,但是加上分號可讀性更好,同時也能避免程式碼壓縮時出錯。

示例:

var msg;
var age = 20;
var sex = 'Male';
var isReal = true;

JavaScript的變數是鬆散型別的,在JavaScript中宣告變數無需指定資料型別,它可以用來儲存任何型別的資料。正是由於定義變數時無需指定型別,所以在JavaScript中變數的型別並不是固定的,比如上面的isReal變數本來是布林型的,但是你也可以再把一個字串賦給isReal變數,如isReal = "ABC";,所以說,變數僅僅是一個用於儲存值的佔位符。

對於未賦值的變數,系統會預設給一個undefined值,上面示例中的msg的值就是undefined

變數的資料型別

ECMAScript中有5種基本資料型別和1種引用型別。

基本資料型別:

undefined, null, boolean, number, string

引用資料型別:

object

typeof操作符

鑑於ECMAScript是鬆散型別的,因此需要有一種手段來檢測給定變數的資料型別——typeof 就是負責提供這方面資訊的操作符。對一個值使用 typeof 操作符可能返回下列某個字串:

  • "undefined"——如果這個值未定義;
  • "boolean"——如果這個值是布林值;
  • "string"——如果這個值是字串;
  • "number"——如果這個值是數值;
  • "object"——如果這個值是物件或 null;
  • "function"——如果這個值是函式。

下面是幾個使用 typeof 操作符的例子:

var msg = "itbsl";
alert(typeof msg);  //string
alert(typeof(msg)); //string
alert(typeof 25);   //number

這幾個例子說明,typeof 操作符的運算元可以是變數(msg),也可以是數值字面量。注意,typeof 是一個操作符而不是函式,因此例子中的圓括號儘管可以使用,但不是必需的。

有些時候,typeof 操作符會返回一些令人迷惑但技術上卻正確的值。比如,呼叫 typeof null
會返回"object",因為特殊值 null 被認為是一個空的物件引用。

從技術角度講,函式在 ECMAScript 中是物件,不是一種資料型別。然而,函式也確實有一些特殊的屬性,因此通過 typeof 操作符來區分函式和其他物件是有必要的。

undefined

Undefined 型別只有一個值,即特殊的 undefined。在使用 var 宣告變數但未對其加以初始化時, 這個變數的值就是 undefined,例如:

var message;
alert(message == undefined); //true

這個例子只聲明瞭變數 message,但未對其進行初始化。比較這個變數與 undefined 字面量,結果表明它們是相等的。

一般而言,不存在需要顯式地把一個變數設定為 undefined 值的情況。字面值undefined 的主要目的是用於比較,而 ECMA-262 第 3 版之前的版本中並沒有規定這個值。第 3 版引入這個值是為了正式區分空物件指標與未經初始化的變數。

哪些情況下的值會是undefined呢?

  • 沒有return語句的函式的返回值
  • 未賦值的變數的值
  • 稀疏陣列中不存在的陣列元素的值
  • 訪問不存在的屬性的值
  • 訪問已刪除屬性的值

稀疏陣列是有些索引處有值,而其他索引處沒有值得陣列。假設有一個長度為10的陣列,在索引1000處新增一個新元素後,索引10~999處的值都是undefined。你可以這樣認為,這猶如建立了989個變數,但沒有對它們進行初始化。雖然這些變數沒有值,但它們都要佔用計算機記憶體,因此除非有充分的理由,否則千萬不要建立稀疏陣列。請注意,undefined是一個值,而不是字串,undefined和字串"undefined"並不是一個東西。

undefined到底是什麼呢?它其實並不複雜。你可以這麼認為:對於任何還沒值(即還未初始化)的東西,都會將undefined賦給它。

undefined值的型別為什麼是undefined?

我認為原因如下:它不是物件,不是數字、字串或布林值,也不是任何明確的東西。既然如此,為何不將這種型別也視為未定義的呢?這是JavaScript怪異的灰色地帶之一,你不得不接受。

null

Null 型別是第二個只有一個值的資料型別,這個特殊的值是 null。從邏輯角度來看,null 值表示一個空物件指標,而這也正是使用 typeof 操作符檢測 null 值時會返回"object"的原因,如下面
的例子所示:

var car = null;
alert(typeof car); //"object"

如果定義的變數準備在將來用於儲存物件,那麼最好將該變數初始化為 null 而不是其他值。這樣一來,只要直接檢查 null 值就可以知道相應的變數是否已經儲存了一個物件的引用。

實際上,undefined 值是派生自 null 值的,因此 ECMA-262 規定對它們的相等性測試要返回 true:

alert(null == undefined);    //true

這裡,位於 null 和 undefined 之間的相等操作符(==)總是返回 true,不過要注意的是,這個操作符出於比較的目的會轉換其運算元。

儘管 null 和 undefined 有這樣的關係,但它們的用途完全不同。如前所述,無論在什麼情況下都沒有必要把一個變數的值顯式地設定為 undefined,可是同樣的規則對 null 卻不適用。換句話說,只要意在儲存物件的變數還沒有真正儲存物件,就應該明確地讓該變數儲存 null 值。這樣做不僅可以體現 null 作為空物件指標的慣例,而且也有助於進一步區分 null 和 undefined。

我們在使用getElementById獲取dom物件時,如果指定的id不存在,它返回的值是null,而不是undefined。null到底是什麼?getElementById為何不返回undefined?

答: 在很多語言中,都有一個表示”無物件“的概念,這挺好。就拿方法document.getElementById來說吧,是不是要求它返回一個物件?如果它無法返回一個物件呢?在這種情況下,我們希望返回一個含義如下的值:要是有物件,我就會是一個物件,可當前沒有。這正是null的含義。我們以後還會經常碰到將變數的值顯式的設定為null,意思是說我原本要將一個物件賦給這個變數,但現在沒有這樣的物件。你可能撓著頭說,為何不使用undefined來表達這種意思呢?很多人都這麼想。原因是JavaScript剛面世時時這麼想的:用一個值表示變數還未初始化,用另一個值表示沒有物件可賦給變數。這並不完美,而且顯得有些多餘,但現實情況就是如此。你只需牢記undefined和null各自的用途,並知道下面一點就行了:在應該提供一個物件,但無法建立或找到時,將提供null;在變數未初始化、物件沒有指定屬性或陣列沒有指定元素時,將返回undefined。

boolean

Boolean 型別是 ECMAScript 中使用得最多的一種型別,該型別只有兩個字面值:true 和 false。這兩個值與數字值不是一回事,因此 true 不一定等於 1,而 false 也不一定等於 0。以下是為變數賦Boolean 型別值的例子:

var found = true;
var lost = false;

需要注意的是,Boolean 型別的字面值 true 和 false 是區分大小寫的。也就是說,True 和 False(以及其他的混合大小寫形式)都不是 Boolean 值,只是識別符號。

雖然 Boolean 型別的字面值只有兩個,但 ECMAScript 中所有型別的值都有與這兩個 Boolean 值等價的值。要將一個值轉換為其對應的 Boolean 值,可以呼叫轉型函式 Boolean(),如下例所示:

var message = "Hello world!";
var messageAsBoolean = Boolean(message);

在這個例子中,字串 message 被轉換成了一個 Boolean 值,該值被儲存在 messageAsBoolean變數中。可以對任何資料型別的值呼叫 Boolean()函式,而且總會返回一個 Boolean 值。至於返回的這個值是 true 還是 false,取決於要轉換值的資料型別及其實際值。下表給出了各種資料型別及其對應的轉換規則。

資料型別 轉換為true的值 轉換為false的值
Boolean true false
String 任何非空字串 ""(空字串)
Number 任何非零數字值(包括無窮大) 0和NaN
Object 任何物件 null
Undefined undefined

這些轉換規則對理解流控制語句(如if語句)自動執行相應的Boolean轉換非常重要,請看下面的程式碼:

var message = "Hello world!";
if (message){
    alert("Value is true");
}

執行這個示例,就會顯示一個警告框,因為字串 message 被自動轉換成了對應的 Boolean 值 (true)。由於存在這種自動執行的 Boolean 轉換,因此確切地知道在流控制語句中使用的是什麼變數 至關重要。錯誤地使用一個物件而不是一個 Boolean 值,就有可能徹底改變應用程式的流程。

number

Number 型別應該是 ECMAScript 中最令人關注的資料型別了,這種型別使用 IEEE754 格式來表示整數和浮點數值(浮點數值在某些語言中也被稱為雙精度數值)。

數值範圍

由於記憶體的限制,ECMAScript 並不能儲存世界上所有的數值。ECMAScript 能夠表示的最小數值保 存在 Number.MIN_VALUE 中——在大多數瀏覽器中,這個值是 5e-324;能夠表示的最大數值儲存在 Number.MAX_VALUE 中——在大多數瀏覽器中,這個值是 1.7976931348623157e+308。如果某次計算的 結果得到了一個超出 JavaScript 數值範圍的值,那麼這個數值將被自動轉換成特殊的 Infinity 值。具 體來說,如果這個數值是負數,則會被轉換成-Infinity(負無窮),如果這個數值是正數,則會被轉 換成 Infinity(正無窮)。

如上所述,如果某次計算返回了正或負的 Infinity 值,那麼該值將無法繼續參與下一次的計算, 因為 Infinity 不是能夠參與計算的數值。要想確定一個數值是不是有窮的(換句話說,是不是位於最 小和最大的數值之間),可以使用 isFinite()函式。這個函式在引數位於最小與最大數值之間時會返 回 true,如下面的例子所示:

var result = Number.MAX_VALUE + Number.MAX_VALUE;
alert(isFinite(result)); //false

儘管在計算中很少出現某些值超出表示範圍的情況,但在執行極小或極大數值的計算時,檢測監控這些值是可能的,也是必需的。

NaN

NaN,即非數值(Not a Number)是一個特殊的數值,這個數值用於表示一個本來要返回數值的運算元未返回數值的情況(這樣就不會丟擲錯誤了)。例如,在其他程式語言中,任何數值除以 0 都會導致錯誤, 從而停止程式碼執行。但在 ECMAScript 中,0除以 0 會返回 NaN,正數除以 0 返回 Infinity,負數除以 0 返回-Infinity,因此不會影響其他程式碼的執行。

NaN 本身有兩個非同尋常的特點。首先,任何涉及 NaN 的操作(例如 NaN/10)都會返回 NaN,這個特點在多步計算中有可能導致問題。其次,NaN 與任何值都不相等,包括 NaN 本身。例如,下面的程式碼會返回 false:

alert(NaN == NaN); //false

針對 NaN 的這兩個特點,ECMAScript 定義了 isNaN()函式。這個函式接受一個引數,該引數可以
是任何型別,而函式會幫我們確定這個引數是否“不是數值”。isNaN()在接收到一個值之後,會嘗試
將這個值轉換為數值。某些不是數值的值會直接轉換為數值,例如字串"10"或 Boolean 值。而任何
不能被轉換為數值的值都會導致這個函式返回 true。請看下面的例子:

alert(isNaN(NaN));    //true
alert(isNaN(10));     //false(10 是一個數值)
alert(isNaN("10"));   //false(可以被轉換成數值 10)
alert(isNaN("blue")); //true(不能轉換成數值)
alert(isNaN(true));   //false(可以被轉換成數值 1)

這個例子測試了 5 個不同的值。測試的第一個值是 NaN 本身,結果當然會返回 true。然後分別測試了數值 10 和字串"10",結果這兩個測試都返回了 false,因為前者本身就是數值,而後者可以被轉換成數值。但是,字串"blue"不能被轉換成數值,因此函式返回了 true。由於 Boolean 值 true可以轉換成數值 1,因此函式返回false。

既然NaN(Not a Number)指的是”不是數字“,那它是什麼呢?如果指出它是什麼,而非它不是什麼,是不是更容易理解呢?那你認為它是什麼呢?為獲得一點線索,可檢查型別:

var test = 0/0;
console.log(typeof test); //number

到底是怎麼回事兒?NaN的型別是數字?一個不是數字的東西,其型別怎麼可能是數字呢?你可以這樣想:NaN是一個糟糕的名稱;與其稱之為”不是數字“,還不如稱之為”無法表示的數字“(必須承認,這樣首字母縮寫將不那麼出色)。如果這樣想,就可以認為NaN是一個數字,只是無法表示而已(至少對計算機來說如此)。

string

String 型別用於表示由零或多個 16 位 Unicode 字元組成的字元序列,即字串。字串可以由雙引號(")或單引號(')表示,因此下面兩種字串的寫法都是有效的:

var firstName = "Nicholas";
var lastName = 'Zakas';

與 PHP 中的雙引號和單引號會影響對字串的解釋方式不同,ECMAScript 中的這兩種語法形式沒有什麼區別。用雙引號表示的字串和用單引號表示的字串完全相同。

其它型別資料和字串進行+操作時,會將其它型別資料轉為字串,然後同字串拼接。

var num = 3;
var isTrue = true;
var str = "123";

var result1 = num + str;
var result2 = isTrue + str;
alert(result1); //3123
alert(result2); //true123