本章主要講述JavaScript中的資料類型(基本類型與參考型別),變數(包括變數的範圍),操作符(主要是一些較為常見,但是不容易從字面上理解的操作符)。由於JavaScript中的“一切皆對象”,在掌握了這些基本的概念之後,讀者就可以較為輕鬆的理解諸如範圍,調用對象,閉包,currying等等較難理解的概念了。
資料類型
有程式設計經驗的讀者肯定知道,在C或者Java這樣的語言中,資料是有類型的,比如用以表示使用者名稱的屬性是字串,而一個僱員的年齡則是一個數字,表示UI上的一個開關按鈕的資料模型則為布爾值等等,對數字可能還可以細分為浮點數,整型數,整型數又可能分為長整型和短整型,總而言之,它們都表示語言中的資料的值的類型。
JavaScript中的資料類型分為兩種:基礎資料型別 (Elementary Data Type)和物件類型,其中物件類型包含對象,數組,以及函數(事實上,函數,數組等也都是對象,這個在後邊的章節詳述)。
1.1.1 基礎資料型別 (Elementary Data Type)
在JavaScript中,包含三種基本的資料類型,字串(String),數值(Number),布爾值(boolean),下面是一些簡單的例子:
- <strong>var str = "Hello, world";//字串
- var i = 10;//整型數
- var f = 2.3;//浮點數
-
- var b = true;//布爾值</strong>
我們可以分別查看變數的值及變數的類型:
- print(str);
- print(i);
- print(f);
- print(b);
-
- print(typeof str);
- print(typeof i);
- print(typeof f);
- print(typeof b);
注意,在此處使用的print()函數為rhino解譯器的頂層對象的方法,可以用來列印字串,通常情況下,在用戶端,程式員多使用alert()進行類似的動作,alert()是瀏覽器中JavaScript解譯器的頂層對象(window)的一個方法。
- Hello, world
- 10
- 2.3
- true
-
- string
- number
- number
- Boolean
在JavaScript中,所有的數字,不論是整型浮點,都屬於“數字”基本類型。typeof是一個一元的操作符,在本章的另外一個小節會專門講到。
1.1.2 物件類型
這裡提到的對象不是對象本身,而是指一種類型,我們在第三章會對對象進行詳細的討論,此處的對象包括,對象(屬性的集合,即索引值的散列表),數組(有序的列表),函數(包含可執行檔代碼)。
物件類型是一種複合的資料類型,其基本元素由基礎資料型別 (Elementary Data Type)組成,當然不限於基本類型,比如物件類型中的值可以是其他的物件類型執行個體,我們通過例子來說明:
- <strong>var str = "Hello, world";
- var obj = new Object();
- obj.str = str;
- obj.num = 2.3;
-
- var array = new Array("foo", "bar", "zoo");
-
- var func = function(){
- print("I am a function here");
- }</strong>
可以看到,對象具有屬性,如obj.str, obj.num,這些屬性的值可以是基本類型,事實上還可以更複雜,我們來看看他們的類型:
- print(typeof obj);
- print(typeof array);
- print(typeof func);
-
- //將列印出
- object
- object
- function
讀者可能會對print(typeof array)列印出object感到奇怪,事實上,對象和數組的界限並不那麼明顯(事實上它們是屬於同一類型的),但是他們的行為卻非常不同,本書的後續章節將兩個重要的資料類型做了分別介紹。
2.1.3 兩者之間的轉換
類似與Java中基礎資料型別 (Elementary Data Type)的自動裝箱拆箱,JavaScript也有類似的動作,基礎資料型別 (Elementary Data Type)在做一些運算時,會臨時封裝一個對象,做完運算後,又自動釋放該對象。我們可以通過幾個例子來說明:
- <strong>var str = "JavaScript Kernal";
- print(str.length);//列印17</strong>
str為一個字串,通過typeof運算子可知其type為”string”,而:
- <strong>var str2 = new String("JavaScript Kernal");
- print(typeof str2);</strong>
可知,str2的type為”object”,即這兩者並不相同,那麼為什麼可以使用str.length來的到str的長度呢?事實上,當使用str.length時,JavaScript會自動封裝一個臨時的String對象,內容為str的內容,然後擷取該對象的length屬性,最後,這個臨時的對象將被釋放。
而將對象轉換為基本類型則是通過這樣的方式:通過調用對象的valueOf()方法來取得對象的值,如果和內容相關的類型匹配,則使用該值。如果valueOf取不到值的話,則需要調用對象的toString()方法,而如果上下文為數值型,則又需要將此字串轉換為數值。由於JavaScript是弱類型的,所以JavaScript引擎需要根據上下文來“猜測”對象的類型,這就使得JavaScript的效率比編譯型的語言要差一些。
valueOf()的作用是,將一個對象的值轉換成一種合乎上下文需求的基本類型,toString()則名副其實,可以列印出對象對應的字串,當然前提是你已經“重載”了Object的toString()方法。
事實上,這種轉換規則會導致很多的問題,比如,所有的非Null 物件,在布爾值環境下,都會被轉成true,比如:
- <strong>function convertTest(){
- if(new Boolean(false) && new Object() &&
- new String("") && new Array()){
- print("convert to boolean")
- }
- }
-
- convertTest();//convert to Boolean</strong>
初學者容易被JavaScript中的類型轉換規則搞暈掉,很多情況下會覺得那種寫法看著非常彆扭,其實只需要掌握了規則,這些古怪的寫法會大大的提高代碼的效能,我們通過例子來學習這些規則:
- <strong>var x = 3;
- var y = x + "2";// => 32
- var z = x + 2;// => 5
-
- print(y);
- print(z);</strong>
通常可以在JS代碼中發現這樣的代碼:
- <strong>if(datamodel.item){
- //do something...
- }else{
- datamodel.item = new Item();
- }</strong>
這種寫法事實上具有更深層次的含義:
應該注意到,datamodel.item是一個對象(字串,數字等),而if需要一個boolean型的運算式,所以這裡進行了類型轉換。在JavaScript中,如果上下文需要boolean型的值,則引擎會自動將對象轉換為boolean類型。轉換規則為,如果該對象非空,則轉換為true,否則為false.因此我們可以採取這種簡寫的形式。
而在傳統的程式設計語言(強型別)中,我們則需要:
- <strong>if(datamodel.item != null){
- //do something...
- }else{
- datamodel.item = new Item();
- }</strong>