書名: 15天學會JavaScript(視頻教學版)作者名: 王金柱本章字數: 9657字更新時間: 2019-12-06 14:00:32
2.3 ECMAScript類型
本節介紹關于ECMAScript類型的知識,這是ECMAScript語法基礎中非常重要的部分。
2.3.1 原始值與引用值
根據Ecma-262規范中的定義,變量可以為兩種類型的值,即原始值和引用值。那么這兩種類型的值有什么區別呢?我們先看一下官方給出的原始值和引用值的定義。
- 原始值:原始值是存儲在棧(stack)中的簡單數據段,換句話解釋就是原始值是直接存儲在變量訪問的位置。
- 引用值:引用值是存儲在堆(heap)中的對象,簡單解釋就是存儲在變量處的值是一個指針(pointer),指向存儲對象的內存處。
另外,這里提到關于指針的概念,對于學習過C語言的讀者會比較容易理解引用值的概念。如果讀者對指針的概念比較模糊,建議最好選一本C語言教材認真閱讀一下,相信一定有很大的幫助。
2.3.2 變量賦值機制
根據Ecma-262規范,在為變量賦值時,ECMAScript解釋程序必須判斷該值是原始類型還是引用類型。ECMAScript解釋程序在處理原始類型和引用類型的變量賦值機制上,采用了不同的方式。
ECMAScript的原始類型包括Undefined、Null、Boolean、Number和String五大類型。因此,ECMAScript解釋程序在為變量賦值時,就會先判斷該值是否為這五大原始類型。而Ecma-262規范對于引用類型的定義比較抽象,其實引用類型就是一個對象,類似于Java語言中類(class)的概念。如果ECMAScript解釋程序判斷出值不是原始類型,那么就是引用類型。
由于原始類型的值所占據的空間是固定的,因此可將其存儲在占用較小內存區域的“棧”中,這種存儲機制便于ECMAScript解釋程序迅速查找變量的值。而如果一個值是引用類型,那么其存儲空間將從“堆”中分配。
“棧”與“堆”是計算機操作系統中兩個十分重要的概念,這是因為二者作用的重要性。從數據結構上理解,“棧”是一種“先進后出、后進先出”的存儲結構;“堆”是一種樹形存儲結構。從計算機操作系統原理上理解,“棧”一般位于一級緩存中;而“堆”一般位于二級緩存中,一級緩存的存取速度自然是快于二級緩存的。
“棧”與“堆”的結構關系到變量的存儲機制。由于ECMAScript引用值的大小會改變,因此不能將其存儲在“棧”中,否則會降低變量查找訪問的速度。而指向引用值的指針(pointer)是存儲在“棧”中的,該值是該引用值對象存儲在堆中的地址,因為地址的大小是固定的,所以將其存儲在棧中是沒有任何問題的。
提示
在許多編程語言中,字符串都是被當作引用類型處理的,而不是原始類型。這是因為字符串的長度大小是可變的,不適于作為原始類型來處理。不過,ECMAScript語法改變了這一點,字符串在ECMAScript中是作為原始類型來處理的。自然,ECMAScript字符串的處理速度會更快。
2.3.3 原始類型
ECMAScript語法定義五種原始類型(primitive type),即前文中提到的Undefined、Null、Boolean、Number和String。根據ECMA-262規范中的描述,將術語“類型(type)”定義為“值的一個集合”,其中每種原始類型均定義了其所包含值的范圍及其字面量的表示形式。
ECMAScript語法提供“typeof”運算符來判斷一個值是否在某種類型的范圍內。設計人員不但可以用該運算符判斷一個值是否表示一種原始類型,還可以判斷出其具體表示哪種原始類型。在JS腳本中使用“typeof”運算符將返回下列值之一:
- undefined:如果變量是Undefined類型的會返回該類型;
- boolean:如果變量是Boolean類型的會返回該類型;
- number:如果變量是Number類型的會返回該類型;
- string:如果變量是String類型的會返回該類型;
- object:如果變量是一種引用類型或Null類型的會返回該類型。
下面的幾個小節,將為讀者逐一講解ECMAScript語法定義的這五種原始類型及其應用實例。
2.3.4 Undefined原始類型
首先介紹ECMAScript語法中的第一種原始類型——Undefined。對于Undefined類型其實只有一個值,即“undefined”。當聲明的變量未進行初始化時,該變量的默認值就是undefined。
ECMAScript語法中的Undefined類型學習起來是一個難點,通過文字描述來概括總結多少還是有點晦澀難懂,下面還是通過具體實例幫助讀者學習理解Undefined原始類型的概念與用法。
先看第一個關于Undefined類型的代碼示例(詳見源代碼ch02目錄中ch02-js-undefineda.html文件)。
【代碼2-5】
01 <script type="text/javascript"> 02 console.log("print undefined is : " + undefined); 03 console.log("print typeof undefined is : " + typeof undefined); 04 </script>
關于【代碼2-5】的分析如下:
第02行代碼直接在瀏覽器控制臺窗口中輸出了“undefined”,目的是看一下Undefined類型在頁面中的輸出結果;
第03行代碼直接在瀏覽器控制臺窗口中輸出了“typeof undefined”,目的是看一下通過“typeof”運算符操作后的Undefined類型在頁面中的輸出效果。
頁面效果如圖2.5所示。Undefined類型和通過“typeof”運算符操作后的Undefined類型,在控制臺中的輸出結果均是“undefined”。

圖2.5 Undefined原始類型(1)
下面,繼續看第二個關于Undefined類型的代碼示例(詳見源代碼ch02目錄中ch02-js-undefined-b.html文件)。
【代碼2-6】
01 <script type="text/javascript"> 02 var v_undefined; 03 console.log(v_undefined); 04 console.log(typeof v_undefined); 05 </script>
頁面效果如圖2.6所示。如果變量定義后未初始化,則無論是直接輸出該變量,或是通過“typeof”運算符操作后,在控制臺中的輸出結果均是“undefined”。

圖2.6 Undefined原始類型(2)
下面,繼續看第三個關于Undefined類型的代碼示例(詳見源代碼ch02目錄中ch02-js-undefined-c.html文件)。
【代碼2-7】
01 <script type="text/javascript"> 02 console.log(typeof v_undefined); 03 console.log(v_undefined); 04 </script>
頁面效果如圖2.7所示。如果變量未聲明,則通過“typeof”運算符操作后的變量在控制臺中的輸出結果仍是“undefined”。但如果未經過“typeof”運算符操作,直接在控制臺中輸出該未聲明的變量(也未初始化),就會提示JS腳本錯誤,如圖2.7中箭頭所示。

圖2.7 Undefined原始類型(3)
下面,繼續看第四個關于Undefined類型的代碼示例(詳見源代碼ch02目錄中ch02-js-undefined-d.html文件)。
【代碼2-8】
01 <script type="text/javascript"> 02 var v_undefined; 03 if(v_undefined == undefined) { 04 console.log("if v_undefined == undefined is true."); 05 } else { 06 console.log("if v_undefined == undefined is false."); 07 } 08 </script>
聲明后未初始化定義的變量,在邏輯判斷上與Undefined原始類型是相等的,如圖2.8中箭頭所指的結果所示。

圖2.8 Undefined原始類型(4)
最后,看一下第五段關于Undefined類型的代碼示例(詳見源代碼ch02目錄中ch02-js-undefined-e.html文件)。
【代碼2-9】
01 <script type="text/javascript"> 02 var v_func_undefined = (function(){})(); 03 console.log(v_func_undefined); 04 </script>
頁面效果如圖2.9所示。當函數未定義明確的返回值時,函數表達式變量(v_func_undefined)獲取的返回值也是“undefined”,如圖2.9中箭頭所指的結果所示。
以上就是關于Undefined類型的一組代碼示例,希望通過這組代碼示例能夠幫助讀者進一步加深對ECMAScript原始類型“Undefined”的理解。

圖2.9 Undefined原始類型(5)
2.3.5 Null原始類型
在這一小節中,我們繼續介紹ECMAScript語法中的第二種原始類型——Null。Null與Undefined類似,也是只有一個值的原始類型,其只有一個專用值,即“null”。嚴格意義上講,值“undefined”實際上是從值“null”派生而來的。正因為如此,ECMAScript語法將“undefined”和“null”定義為相等的。
ECMAScript語法中的Null類型學習起來也是一個難點,僅僅通過文字描述估計還是無法讓讀者掌握其真正的使用方法,下面還是通過具體實例來幫助讀者學習理解Null原始類型的概念與用法。
先看第一個關于Null類型的代碼示例(詳見源代碼ch02目錄中ch02-js-null-a.html文件)。
【代碼2-10】
01 <script type="text/javascript"> 02 console.log("print null is : " + null); 03 console.log("print typeof null is : " + typeof null); 04 </script>
關于【代碼2-10】的分析如下:
第02行代碼直接在瀏覽器控制臺窗口中輸出了“null”,目的是看一下Null類型在頁面中的輸出結果;
第03行代碼直接在瀏覽器控制臺窗口中輸出了“typeof null”,目的是看一下通過“typeof”運算符操作后的Null類型在頁面中的輸出結果。
頁面效果如圖2.10所示。瀏覽器控制臺中直接輸出Null類型的結果是“null”,而通過“typeof”運算符操作后的Null類型在瀏覽器控制臺中輸出的結果卻是“object”。

圖2.10 Null原始類型(1)
讀者也許會有疑問了,為什么通過“typeof”運算符操作后的“null”值會返回“object”的結果呢?其實這源于JavaScript腳本語言的最初實現版本中的一個錯誤,然后又恰恰被ECMAScript語法沿用了。現在,“null”值被認為是對象的占位符,這樣似乎能夠解釋這一矛盾。但是,從嚴格意義的技術上來講,“null”仍然是原始值,Null也仍然是ECMAScript原始類型。
下面,繼續看第二個關于Null類型的代碼示例(詳見源代碼ch02目錄中ch02-js-null-b.html文件)。
【代碼2-11】
01 <script type="text/javascript"> 02 var v_null = null; 03 console.log(v_null); 04 console.log(typeof v_null); 05 </script>
頁面效果如圖2.11所示。瀏覽器控制臺中直接輸出了變量(v_null)類型的結果是“null”,而通過“typeof”運算符操作后的變量(v_null)在瀏覽器控制臺中輸出的結果是預想中的“object”。

圖2.11 Null原始類型(2)
下面,繼續看一個關于Null類型與Undefined類型比較有趣的的代碼示例(詳見源代碼ch02目錄中ch02-js-null-c.html文件)。
【代碼2-12】
01 <script type="text/javascript"> 02 if(null == undefined) { 03 console.log("if null == undefined is true."); 04 } else { 05 console.log("if null == undefined is false."); 06 } 07 </script>
頁面效果如圖2.12所示。值(null)與值(undefined)在邏輯等于判斷上是相等的,如圖2.12中箭頭所指的結果所示。

圖2.12 Null原始類型與Undefined原始類型比較
不過,盡管值(null)與值(undefined)在邏輯等于判斷上是相等的,但是這兩個值的具體含義還是有所區別的。為變量賦“null”值表示該對象目前并不存在,也可以理解為僅僅是一個空的占位符(如前文所述)。而將變量定義為“undefined”值則是聲明了變量但未對其進行初始化賦值(如前文代碼示例)。
另外,當為函數方法定義返回的是對象類型時,如果找不到該對象,則返回值通常就是“null”。而當嘗試獲取函數方法的返回值時,如果該函數方法未定義返回值,則返回值通常就是“undefined”。
2.3.6 Boolean原始類型
本小節繼續介紹ECMAScript語法中的第三種原始類型——Boolean。Boolean原始類型是ECMAScript語法中定義的非常常用的類型之一。Boolean類型有兩個值,即大家所熟悉的“true”和“false”。
下面來看一個關于Boolean類型的代碼示例(詳見源代碼ch02目錄中ch02-js-boolean.html文件)。
【代碼2-13】
01 <script type="text/javascript"> 02 var v_b_true = true; 03 console.log(v_b_true); 04 console.log(typeof v_b_true); 05 if(v_b_true) { 06 console.log("v_b_true is true."); 07 } else { 08 console.log("v_b_true is false."); 09 } 10 if(v_b_true == 1) { 11 console.log("v_b_true == 1."); 12 } else { 13 console.log("v_b_true != 1."); 14 } 15 var v_b_false = false; 16 console.log(v_b_false); 17 console.log(typeof v_b_false); 18 if(v_b_false) { 19 console.log("v_b_false is true."); 20 } else { 21 console.log("v_b_false is false."); 22 } 23 if(v_b_false == 0) { 24 console.log("v_b_false == 0."); 25 } else { 26 console.log("v_b_false != 0."); 27 } 28 </script>
關于【代碼2-13】的分析如下:
第02行代碼定義了一個變量(v_b_true),并初始化賦值為“true”;
第03行代碼直接在瀏覽器控制臺窗口中輸出了變量(v_b_true),目的是看一下Boolean類型在頁面中的輸出效果;
第04行代碼直接在瀏覽器控制臺窗口中輸出了“typeof v_b_true”,目的是看一下通過“typeof”運算符操作后的Boolean類型在頁面中的輸出效果;
第05~09行代碼直接通過“if”條件運算符判斷變量(v_b_true)的邏輯值,并根據邏輯運算結果在瀏覽器控制臺窗口中進行相應的輸出;
第10~14行代碼直接通過“if”條件運算符判斷變量(v_b_true)與數值“1”是否邏輯相等,并根據邏輯運算結果在瀏覽器控制臺窗口中進行相應的輸出。這樣測試的目的是源于C語言和Java語言的語法中,布爾值“真”與數值“1”是邏輯相等的,因此查看一下在ECMAScript語法中是否也是如此;
第15~27行代碼與第02~14行代碼的功能類似,只不過第15行代碼定義的變量(v_b_false),其初始化賦值為“false”,目的就是測試一下布爾值“false”的輸出結果。
頁面效果如圖2.13所示。瀏覽器控制臺中直接輸出變量(v_b_true)的結果是“true”,而通過“typeof”運算符操作后的變量(v_b_true)在瀏覽器控制臺中輸出的結果就是“Boolean”類型;而通過“if”條件運算符判斷變量(v_b_true)與數值“1”是否邏輯相等的結果表明,Boolean值“true”在邏輯上是等于數值“1”的;同樣,Boolean值“false”與數值“0”在邏輯也是相等的。

圖2.13 Boolean原始類型
通過以上的測試結果的學習,相信讀者對于ECMAScript語法中的Boolean類型的使用會有一個比較清楚的理解。
2.3.7 Number原始類型
本小節繼續介紹ECMAScript語法中的第四種原始類型——Number。Number原始類型是ECMAScript語法中定義的比較特殊的類型之一。特殊之處就在于Number類型既可以表示32位整數值,也可以表示64位浮點數值。對于直接定義的任意類型數值,ECMAScript語法均識別為Number類型的值,故而Number類型使用起來也是非常靈活的。
下面,先看第一個關于Number類型十進制數值的代碼示例(詳見源代碼ch02目錄中ch02-js-number-dec.html文件)。
【代碼2-14】
01 <script type="text/javascript"> 02 var i = 123; 03 var j = 456; 04 var sum = i + j; 05 console.log("sum = " + sum); 06 console.log(i.toString() + j.toString()); 07 </script>
關于【代碼2-14】的分析如下:
第04行代碼定義了變量(sum),并初始化賦值為變量(i)和變量(j)相加的和;
第06行代碼分別通過Number對象的toString()方法將變量(i)和變量(j)轉換為字符串類型,并通過運算符“+”執行字符串連接操作,然后將操作后的結果在瀏覽器控制臺窗口中進行了輸出。
頁面效果如圖2.14所示。可以看出Number類型十進制數值可以通過toString()方法轉換為字符串類型。

圖2.14 Number原始類型(1)
下面,繼續看第二個關于Number類型八進制數值的代碼示例(詳見源代碼ch02目錄中ch02-js-number-oct.html文件)。
【代碼2-15】
01 <script type="text/javascript"> 02 var v_dec = 147; 03 console.log("147 = " + v_dec); 04 var v_oct = 0147; // TODO: 定義八進制數值 05 console.log("0147 = " + v_oct); 06 var v_oct_oct = v_oct + v_oct; 07 console.log("0147 + 0147 = " + v_oct_oct); 08 var v_dec_oct = v_dec + v_oct; 09 console.log("147 + 0147 = " + v_dec_oct); 10 </script>
頁面效果如圖2.15所示。第05行代碼在瀏覽器控制臺窗口中輸出變量(v_oct)的內容為“103”,而不是初始化定義的數值“0147”,這說明ECMAScript語法對八進制變量返回的是換算后的十進制數值;同樣,第07行代碼在瀏覽器控制臺窗口中輸出的變量(v_oct_oct)的內容為“206”,也是十進制相加運算得出的結果。
另外,第09行代碼在瀏覽器控制臺窗口中輸出的變量(v_dec_oct)的內容為250,是十進制數值147和十進制數值103相加運算得出的結果。這就表明在ECMAScript語法中,八進制與十進制運算時,默認都是換算成十進制來計算的。八進制數值如此,十六進制數值也是一樣的。

圖2.15 Number原始類型(2)
下面,繼續看第三個關于Number類型十六進制數值的代碼示例(詳見源代碼ch02目錄中ch02-js-number-hex.html文件)。
【代碼2-16】
01 <script type="text/javascript"> 02 var v_dec = 1234; 03 console.log("1234 = " + v_dec); 04 var v_oct = 0147; // TODO: 定義八進制數值 05 console.log("0147 = " + v_oct); 06 var v_hex = 0x12ff; // TODO: 定義十六進制數值 07 console.log("0x12ff = " + v_hex); 08 var v_hex_hex = v_hex + v_hex; 09 console.log("0x12ff + 0x12ff = " + v_hex_hex); 10 var v_dec_hex = v_dec + v_hex; 11 console.log("1234 + 0x12ff = " + v_dec_hex); 12 var v_oct_hex = v_oct + v_hex; 13 console.log("0147 + 0x12ff = " + v_oct_hex); 14 </script>
頁面效果如圖2.16所示。第07行代碼在瀏覽器控制臺窗口中輸出的變量(v_hex)的內容為4863,而不是初始化定義的數值“0x12ff”,這說明ECMAScript語法對十六進制變量同樣返回的是換算后的十進制數值。第09行代碼在瀏覽器控制臺窗口中輸出的變量(v_hex_hex)的內容為9726,也是十進制運算相加得出的結果。
另外,第11行代碼在瀏覽器控制臺窗口中輸出的變量(v_dec_hex)的內容為6097,是十進制數值1234和十進制數值4863相加運算得出的結果。這就表明在ECMAScript語法中,十進制與十六進制運算時,默認都是換算成十進制來計算的。同樣,第13行代碼在瀏覽器控制臺窗口中輸出的變量(v_oct_hex)的內容為4966,是十進制數值103和十進制數值4863相加運算得出的結果。這同樣表明在ECMAScript語法中,八進制與十六進制運算時,也默認都是換算成十進制來計算的。

圖2.16 Number原始類型(3)
下面,繼續看第四個關于Number類型浮點數值的代碼示例(詳見源代碼ch02目錄中ch02-js-number-float.html文件)。
【代碼2-17】
01 <script type="text/javascript"> 02 // TODO: 定義浮點數值必須使用小數點和至少一位小數 03 var v_f = 16.8; 04 console.log("16.8 = " + v_f); 05 var v_f_f = v_f + v_f; 06 console.log("16.8 + 16.8 = " + v_f_f); 07 var v_i = 168; 08 var v_i_f = v_i + v_f; 09 console.log("168 + 16.8 = " + v_i_f); 10 var v_str = "16.8"; 11 var v_f_str = v_f + v_str; 12 console.log("16.8 + '16.8' = " + v_f_str); 13 </script>
頁面效果如圖2.17所示。第06行代碼在瀏覽器控制臺窗口中輸出的變量(v_f_f)的內容為33.6,正是兩個浮點數16.8相加后的結果;第09行代碼在瀏覽器控制臺窗口中輸出的變量(v_i_f)的內容為184.8,正是整數168和浮點數16.8相加后的結果,且整數與浮點數運算后自動保存為浮點數類型。
另外,第12行代碼在瀏覽器控制臺窗口中輸出的內容為“16.816.8”,這明顯是一個字符串類型。這就明顯表明在ECMAScript語法中,浮點數與字符串通過運算符“+”連接時,浮點數會被當成字符串來處理,而此時的運算符“+”不再是加法運算,而是字符串連接運算。

圖2.17 Number原始類型(浮點數)
其實,讀者可以測試一下整數類型與字符串類型通過運算符“+”連接后的結果,同樣是字符串連接運算。由此可以推斷出,無論是整數或是浮點數,在運算之前均是被存儲成字符串類型的,而ECMAScript語法中確實也是這樣規定的。這就與傳統的C語言不同,【代碼2-17】中第11行代碼的表達式在C語言中,編譯時一定會報錯。這也恰恰說明JavaScript語言的弱類型性。
最后,對于Number類型中的非常大或非常小的數值,一般采用科學記數法來表示浮點數。具體說就是把一個很大或很小的數值表示為數字(包括十進制數字)加e(或E),后面加乘以10的冪。
接下來,繼續看第五個關于Number類型科學記數法的代碼示例(詳見源代碼ch02目錄中ch02-js-number-e.html文件)。
【代碼2-18】
01 <script type="text/javascript"> 02 // TODO: 科學記數法使用 e加上10的冪來表示 03 var v_e_plus = 1.68e8; // TODO: 很大的數的表示方法 04 console.log("1.68e8 = " + v_e_plus); 05 var v_e_neg_6 = 0.000000168; // TODO: 很小的數的表示方法 06 console.log("0.000000168 = " + v_e_neg_6); 07 var v_e_neg_5 = 0.00000168; // TODO: 很小的數的表示方法 08 console.log("0.000000168 = " + v_e_neg_5); 09 </script>
提示
變量(v_e_neg_6)與變量(v_e_neg_5)的區別就是小數點后的前導0的個數不同,變量(v_e_neg_6)是六個0,而變量(v_e_neg_5)是五個0。
頁面效果如圖2.18所示。第04行代碼在瀏覽器控制臺窗口中輸出的變量(v_e_plus)的內容為168000000,正是科學記數法1.68e8(1.68×108)通過運算后的結果。
第06行代碼在瀏覽器控制臺窗口中輸出的變量(v_e_neg_6)的內容為1.68e-7,正是浮點數0.000000168轉換為科學記數法后的結果。而第08行代碼在瀏覽器控制臺窗口中輸出的變量(v_e_neg_5)的內容,并沒有轉換為科學記數法。這是因為ECMAScript語法規定,默認會把具有6個或6個以上前導0的浮點數自動轉換成科學記數法。

圖2.18 Number原始類型(科學記數法)
2.3.8 特殊的Number類型值
ECMAScript語法中為Number原始類型定義了幾個特殊值。下面,我們就逐一介紹這些Number類型特殊值。
首先,就是Number.MAX_VALUE和Number.MIN_VALUE這兩個特殊值,其分別定義了Number值集合的上下界限。ECMAScript語法規定所有數值都必須介于這兩個值之間。不過,如果是通過計算生成的數值則可以不在這兩個值之間。
下面來看一個關于特殊值Number.MAX_VALUE和Number.MIN_VALUE的代碼示例(詳見源代碼ch02目錄中ch02-js-number-min-max.html文件)。
【代碼2-19】
01 <script type="text/javascript"> 02 // TODO: Number 特殊值 03 console.log("Number類型上界限:"+Number.MAX_VALUE); // TODO: Number上限值 04 console.log("Number類型下界限:"+Number.MIN_VALUE); // TODO: Number下限值 05 </script>
關于【代碼2-19】的分析如下:
這段代碼直接在瀏覽器控制臺窗口中輸出了Number.MAX_VALUE和Number.MIN_VALUE這兩個特殊值的內容。頁面效果如圖2.19所示。

圖2.19 Number類型特殊值(上下界限)
當通過計算生成的數值大于Number.MAX_VALUE時,其會被賦予特殊值Number.POSITIVE_INFINITY,該值表示正無限大的數值,也就是不再有具體的數值。同樣的,當通過計算生成的數值小于Number.MIN_VALUE時,其會被賦予特殊值Number.NEGATIVE_INFINITY,該值表示負無限大的數值,同樣也是不再有具體的數值。當通過計算返回的是無窮大值時,該值也就不能再用于其他計算。
ECMAScript語法中有專用值表示正無窮大(Infinity)和負無窮大(-Infinity)。事實上,Number.POSITIVE_INFINITY的值就是Infinity,而Number.NEGATIVE_INFINITY的值就是-Infinity。
下面來看一個關于特殊值Number.POSITIVE_INFINITY和Number.NEGATIVE_INFINITY的代碼示例(詳見源代碼ch02目錄中ch02-js-number-posi-nega-infinity.html文件)。
【代碼2-20】
01 <script type="text/javascript"> 02 // TODO: Number 特殊值 03 console.log("Number.POSITIVE_INFINITY(正無窮大) : " + Number.POSITIVE_INFINITY); 04 console.log("Number.NEGATIVE_INFINITY(負無窮大) : " + Number.NEGATIVE_INFINITY); 05 </script>
關于【代碼2-20】的分析如下:
這段代碼直接在瀏覽器控制臺窗口中輸出了Number.POSITIVE_INFINITY和Number.NEGATIVE_INFINITY這兩個特殊值的內容。
頁面效果如圖2.20所示。瀏覽器控制臺中輸出了特殊值Number.POSITIVE_INFINITY和Number.NEGATIVE_INFINITY的具體值,分別就是特殊值正無窮大(Infinity)和負無窮大(-Infinity)。
既然無窮大數可以是正數也可以是負數,所以可用一個方法判斷一個數是否是有窮的。ECMAScript語法中提供了一個isFinite()函數方法,其可以判斷數值是否為非無窮大。

圖2.20 Number類型特殊值(無窮大)
下面來看一個通過isFinite()函數方法判斷數值是否為無窮大的代碼示例(詳見源代碼ch02目錄中ch02-js-number-isInfinity.html文件)。
【代碼2-21】
01 <script type="text/javascript"> 02 // TODO: Number 特殊值 03 if(isFinite(1)) { 04 console.log("isFinite(1) is not Infinity."); 05 } else { 06 console.log("isFinite(1) is Infinity."); 07 } 08 if(isFinite(Number.MAX_VALUE)) { 09 console.log("isFinite(Number.MAX_VALUE) is not Infinity."); 10 } else { 11 console.log("isFinite(Number.MAX_VALUE) is Infinity."); 12 } 13 if(isFinite(Number.MAX_VALUE * 2)) { 14 console.log("Number.MAX_VALUE * 2 = " + Number.MAX_VALUE * 2); 15 console.log("isFinite(Number.MAX_VALUE * 2) is not Infinity."); 16 } else { 17 console.log("Number.MAX_VALUE * 2 = " + Number.MAX_VALUE * 2); 18 console.log("isFinite(Number.MAX_VALUE * 2) is Infinity."); 19 } 20 if(isFinite(Number.POSITIVE_INFINITY)) { 21 console.log("isFinite(Number.POSITIVE_INFINITY) is not Infinity."); 22 } else { 23 console.log("isFinite(Number.POSITIVE_INFINITY) is Infinity."); 24 } 25 </script>
頁面效果如圖2.21所示。數值1為非無窮大;特殊值Number.MAX_VALUE同樣也為非無窮大;而兩倍的特殊值Number.MAX_VALUE和特殊值Number.POSITIVE_INFINITY則為無窮大。

圖2.21 Number類型特殊值(判斷是否為非無窮大)
最后要介紹的Number類型特殊值是NaN,其表示非數值(Not a Number)。在ECMAScript語法中,NaN是一個非常奇怪的特殊值,奇怪之處就是其與自身邏輯判斷上是不相等的。NaN與Infinity一樣都是不能用于算術計算的。另外,ECMAScript語法中提供了一個isNaN()函數方法,其可以判斷某個數據類型是否為非數值。
下面來看一個關于特殊值NaN和isNaN()函數方法的代碼示例(詳見源代碼ch02目錄中ch02-js-isNaN.html文件)。
【代碼2-22】
01 <script type="text/javascript"> 02 console.log("NaN is " + NaN); 03 console.log("typeof NaN is " + typeof NaN); 04 if(isNaN(NaN)) { 05 console.log("isNaN(NaN) return true."); 06 } else { 07 console.log("isNaN(NaN) return false."); 08 } 09 if(isNaN(123)) { 10 console.log("isNaN(123) return true."); 11 } else { 12 console.log("isNaN(123) return false."); 13 } 14 if(isNaN("123")) { 15 console.log("isNaN('123') return true."); 16 } else { 17 console.log("isNaN('123') return false."); 18 } 19 if(isNaN("abc")) { 20 console.log("isNaN('abc') return true."); 21 } else { 22 console.log("isNaN('abc') return false."); 23 } 24 if(NaN == NaN) { 25 console.log("NaN == NaN return true."); 26 } else { 27 console.log("NaN == NaN return false."); 28 } 29 </script>
關于【代碼2-22】的分析如下:
第02行代碼直接在瀏覽器控制臺窗口中輸出了特殊值NaN的內容;
第03行代碼通過typeof運算符對特殊值NaN進行了操作,并在瀏覽器控制臺窗口中輸出運算后的結果;
第04~08行代碼通過isNaN()函數方法判斷特殊值NaN是否為非數值,并根據判斷結果在瀏覽器控制臺窗口中進行相應的輸出;
第09~13行代碼通過isNaN()函數方法判斷數值123是否為非數值,并根據判斷結果在瀏覽器控制臺窗口中進行相應的輸出;
第14~18行代碼通過isNaN()函數方法判斷字符串“123”是否為非數值,并根據判斷結果在瀏覽器控制臺窗口中進行相應的輸出;
第19~23行代碼通過isNaN()函數方法判斷字符串“abc”是否為非數值,并根據判斷結果在瀏覽器控制臺窗口中進行相應的輸出;
第24~28行代碼通過if語句判斷特殊值NaN自身是否為邏輯相等,并根據判斷結果在瀏覽器控制臺窗口中進行相應的輸出。
頁面效果如圖2.22所示。第03行代碼通過typeof運算符操作特殊值NaN后的結果為Number類型,這與NaN的定義是一致的。
第04~08行代碼通過isNaN()函數方法判斷特殊值NaN是否為非數值的結果為“true”,表示NaN為非數值;
第09~13行代碼通過isNaN()函數方法判斷數值123是否為非數值的結果為“false”,表示123不是非數值;
而第14~18行代碼通過isNaN()函數方法判斷字符串“123”是否為非數值的結果為“false”,表示“123”同樣不是非數值;
第19~23行代碼通過isNaN()函數方法判斷字符串“abc”是否為非數值的結果為“true”,表示“abc”為非數值;
第24~28行代碼通過if語句判斷特殊值NaN自身是否為邏輯相等的結果為“false”,表示特殊值NaN與其自身邏輯不相等,這就是前文中提到的特殊值NaN的奇怪之處。

圖2.22 Number類型特殊值(NaN)
2.3.9 String原始類型
下面,我們介紹ECMAScript語法中的第五種原始類型——String(字符串)。String類型與前幾種原始類型的區別之處在于其是唯一沒有固定大小的原始類型。我們可以用字符串存儲0或更多的Unicode字符(Unicode是一種國際通用字符集標準,又稱為統一字符編碼)。
String類型字符串中的每個字符都有固定的位置,首字符從位置標記0開始,第二個字符在位置標記1處,依此類推。因此,字符串中的最后一個字符的位置標記一定是字符串的長度減1。
ECMAScript語法中規定String類型字符串是通過雙引號(")或單引號(')來定義聲明的,這與Java語言是有區別的,Java語言必須是使用雙引號(")來定義聲明字符串,而用單引號(')定義聲明的僅僅是字符。由于ECMAScript語法中沒有定義字符類型,所以定義聲明字符串既可使用雙引號("),也可以使用單引號(')。
下面,先看第一個關于String類型的代碼示例(詳見源代碼ch02目錄中ch02-js-string-a.html文件)。
【代碼2-23】
01 <script type="text/javascript"> 02 var v_str_a = "Hello EcmaScript!"; 03 var v_str_b = "Hello 'EcmaScript!'"; 04 var v_str_c = 'Hello "EcmaScript!"'; 05 console.log(v_str_a); 06 console.log(v_str_b); 07 console.log(v_str_c); 08 </script>
關于【代碼2-23】的分析如下:
第02~04行代碼通過“var”關鍵字定義了三個變量(v_str_a、v_str_b、v_str_c),并初始化字符串。其中,第03行和第04行代碼初始化的字符串中,演示如何在定義字符串時以嵌套方式使用雙引號(")和單引號(');
第05~07行代碼在瀏覽器控制臺窗口中輸出了三個變量(v_str_a、v_str_b、v_str_c)相應的內容。
頁面效果如圖2.23所示。如果想輸出帶有雙引號(")或單引號(')的字符串,那么在定義字符串時必須以嵌套方式將雙引號(")或單引號(')加進去。

圖2.23 String原始類型(1)
下面,我們繼續看第二個關于String類型的代碼示例(詳見源代碼ch02目錄中ch02-js-string-b.html文件)。
【代碼2-24】
01 <script type="text/javascript"> 02 var v_str_a = "Hello"; 03 var v_str_b = "Ecma"; 04 var v_str_c = "Script"; 05 console.log(v_str_a + " " + v_str_b + v_str_c + "!"); 06 </script>
頁面效果如圖2.24所示。使用運算符“+”就可以有效地將字符串進行連接,比操作方式在具體設計中十分有用。

圖2.24 String原始類型(2)
最后,看一下ECMAScript語法中定義的一些特殊字符串,詳見表2-2,這些特殊字符串在某些特定環境下非常有用。
表2-2 ECMAScript特殊字符串

下面,就看一段使用String類型特殊字符串的代碼示例(詳見源代碼ch02目錄中ch02-js-string-c.html文件)。
【代碼2-25】
01 <script type="text/javascript"> 02 var v_str_a = "Hello"; 03 var v_str_b = "Ecma"; 04 var v_str_c = "Script"; 05 console.log(v_str_a + "\b\'\n" + v_str_b + "\"\n\r" + v_str_c + "\t!\\"); 06 </script>
頁面效果如圖2.25所示。從圖中可以看出,使用特殊字符串就可以實現空格、換行和添加標點符號的效果,這在具體設計中是非常實用的。

圖2.25 String原始類型(3)
2.3.10 獲取字符串長度
本小節介紹ECMAScript語法中獲取字符串長度的方法。ECMAScript語法中規定通過String類型的“length”屬性可以獲取字符串的長度。
下面來看一個關于獲取String類型字符串長度的代碼示例(詳見源代碼ch02目錄中ch02-js-string-length.html文件)。
【代碼2-26】
01 <script type="text/javascript"> 02 var v_str = "Hello EcmaScript!"; 03 console.log(v_str.length); 04 var v_i = 123; 05 console.log(v_i.length); 06 var v_null = null; 07 console.log(v_null.length); 08 </script>
關于【代碼2-26】的分析如下:
第02行代碼通過“var”關鍵字定義了第一個變量(v_str),并初始化賦值一個字符串;
第03行代碼通過length屬性獲取字符串變量(v_str)的長度,然后將操作后的結果在瀏覽器控制臺窗口中進行了輸出;
第04行代碼通過“var”關鍵字定義了第二個變量(v_i),并初始化賦值一個整數數值;
第05行代試圖通過length屬性獲取整數變量(v_i)的長度,然后將操作后的結果在瀏覽器控制臺窗口中進行了輸出。定義這行代碼的目的就是想測試一下length屬性是否對Number類型的變量有效;
第06行代碼通過“var”關鍵字定義了第三個變量(v_null),并初始化賦值“null”原始值;
第07行代試圖通過length屬性獲取變量(v_null)的長度,然后將操作后的結果在瀏覽器控制臺窗口中進行了輸出。同樣,定義這行代碼的目的也是想測試一下length屬性是否對Null類型的變量有效。
頁面效果如圖2.26所示。length屬性對于字符串有效,而對于Number類型數值和Null類型無效(即使可以使用length屬性),這一點需要設計人員在使用length屬性時注意。

圖2.26 獲取字符串長度
- 演進式架構(原書第2版)
- 從零構建知識圖譜:技術、方法與案例
- Web交互界面設計與制作(微課版)
- 算法精粹:經典計算機科學問題的Java實現
- Python從入門到精通(精粹版)
- Responsive Web Design with HTML5 and CSS3
- Learning SQLite for iOS
- Mastering KnockoutJS
- Hands-On Microservices with Kotlin
- Learning Vaadin 7(Second Edition)
- 編程與類型系統
- C#程序設計教程(第3版)
- Quantum Computing and Blockchain in Business
- PHP 7從零基礎到項目實戰
- Mastering Apache Camel