第2章 基本構成
本章主要內容
● JavaScript變量
● 數據類型
● JavaScript運算符
● JavaScript流程控制
每個編程語言都有自己一套完整的基礎語法,當然這些語法之間會有一些類似,如果讀者之前有了解過其他語言,將很容易上手。無論哪門語言,都會涉及變量、函數、對象等最基礎的知識。
我們在編程過程中更多的是對不同類型的數據在不同的條件下進行不同的操作。每個應用中都會涉及各種類型的數據以及對數據的操作。
本章將介紹JavaScript中有關變量的基礎語法以及數據類型、常見運算符和流程控制。
2.1 JavaScript變量
在應用編程中,需要使用變量作為值的符號,而且操作最多的就是變量。變量是整個JavaScript語法最基礎的概念。
2.1.1 變量的概念
在代數計算中,通常會使用一個字母來保存值,如字母x上保存一個數值2,字母y上保存一個數值3,之后通過表達式z=x+y,可以計算出z的值為5。
在JavaScript 中,這些字母稱為變量。讀者可以將變量理解為就是一個用來存儲數據的容器。JavaScript 中的變量可以保存和引用任意類型的數據。變量在內存中的存儲如圖2-1所示。

圖2-1
在JavaScript 中,變量除了可以用單個的字母來命名,也可以用一些更語義化的名稱來命名,如num、sum等。這和它的松散類型關系密切。這里讀者需要牢記JavaScript 中的命名規范:
1)嚴格區分字母的大小寫。JavaScript 是區分大小寫的語言,即變量名、函數名、關鍵字都必須采取一致的大小寫形式。例如,變量名“num”“Num”“NUM”是3 個不同的變量名;函數名也類似;關鍵字“var”必須寫成“var”,而不能寫成“Var”或者“VAR”。
2)變量名必須以字母、下畫線、$符號作為開始,后面可以跟任意的字母、數字、下畫線、$符號。
3)不能使用關鍵字或保留字命名。關鍵字就是JavaScript 中用來執行特定操作的代碼,如var。保留字是JavaScript預留的用于執行特定操作的代碼,如int。
4)JavaScript 有自己的命名習慣,例如,駝峰命名法:getElementById;首字母大寫法:Object()。
5)命名盡量要有實際意義,這樣代碼的可讀性比較高。
在JavaScript中,常常用到標識符(即一個名字)對變量和函數進行命名。在JavaScript中規定了一些標識符專門為自己所用,即關鍵字,見表2-1。
表2-1

除了關鍵字以外,和其他語言一樣,JavaScript 也保留了一些標識符在后續的版本中可能會用到,稱為保留字,見表2-2。
表2-2

2.1.2 變量的聲明和賦值
在ES6之前,變量的聲明一般使用var來完成,在ES6中新增了使用let來聲明變量的方式。
1.var聲明變量
使用var聲明和賦值變量有以下4種形式:
1)聲明的同時賦值:
說明:在上述示例中通過var定義一個變量url,并同時通過賦值運算符給它賦值。
2)先聲明后賦值:
說明:在上述示例中通過var先聲明一個變量url,聲明后可以在之后使用時再對它進行賦值操作。在上述示例中存在變量覆蓋問題,詳見2.1.3節。
3)一次聲明多個變量,同時賦值:
說明:上述示例和第1種方式聲明類似,只不過此處同時聲明了多個變量并同時進行賦值,需要特別注意的是,多個變量間要用逗號隔開。
注意:
1)此處有的值上加了引號,有的沒加,加了引號的聲明是字符串類型的數據,數字17是數值類型的數據。
2)一次性聲明多個變量必須要用逗號隔開。
3)一次聲明多個變量,然后賦值:
說明:同第3種聲明方式,需要注意多個變量間用逗號隔開。
2.Iet聲明變量
let是ES6 新增的命令,用法類似于var,但是它所聲明的變量只在let 命令所在的代碼塊內有效。let方式與var方式的區別主要體現在作用域上,這里暫且不做討論。
不像var存在變量提升現象,即變量可以在聲明之前使用,值為undefined。為糾正這種奇怪的現象,let命令改變了語法行為,即變量一定要先聲明后使用,否則會報錯。
示例:
說明:在上述示例中,通過關鍵字var 聲明的變量foo 可以在聲明之前進行訪問,只不過結果為undefined,undefined是個數據類型,并不是報錯。而通過let聲明的變量bar在聲明之前進行訪問會報錯,并非變量未定義。
3.const方式
可以使用關鍵字const 聲明一個只讀的常量。常量標識符的命名規則和變量相同。此外需要注意,const必須在聲明的同時賦值,并且不能重新聲明和賦值。
示例1:
說明:以上示例表明常量不可以通過賦值來改變原來的值,也不可以在腳本運行時重新聲明,它必須初始化為某個值。
示例2:
說明:以上示例表明const 一旦聲明變量,就必須立即初始化,不能留到以后賦值,否則會報錯。
2.1.3 聲明變量的其他注意事項
1)變量在沒有被賦值的情況下會被自動賦值為undefined,undefined 也是一種數據類型,不是錯誤。
2)不使用var 或者let 聲明的變量,如果直接賦值,不會報錯,這個變量會被當作window對象的屬性存在,擁有全局的作用域,本書不推薦這樣的寫法。
3)如何覆蓋已有變量?變量在聲明之后是可以重新賦值的,使用var 的方式可以重新聲明和賦值,使用let則只能重新賦值,不能重新聲明。
示例:
說明:上述示例表明,通過關鍵字var 聲明的變量可以重新聲明和賦值,通過let 聲明的變量只能重新賦值不能重新聲明,那么在寫程序的過程中,let就能很好地幫助開發人員避免一些不必要的錯誤。
2.2 數據類型
在JavaScript 變量中,我們會將一些值保存在變量中以備后續使用,那么在編程過程中,經常需要對值進行操作,而能夠表示并操作值的類型稱為數據類型。本節將重點介紹JavaScript中的數據類型。
JavaScript的數據類型大致可以分為初始類型和引用類型。
1.初始類型
1)Number:數值,如10或3.1415。
2)String:字符串,如UEK。
3)Boolean:布爾值,只有true 和false。
4)undefined:變量未定義時的屬性。
5)null:空。
6)ES6中新增的Symbol類型:一種數據類型,它的實例是唯一且不可變的。
2.引用類型
1)對象。
2)數組。
3)函數。
通過這幾種數據類型,我們就可以在應用程序中執行和實現不同的功能。接下來將對每個類型進行詳細講解。
2.2.1 typeof操作符
鑒于JavaScript是松散型的弱類型語言,需要通過一種手段來檢測已有變量的數據類型,而typeof操作符正好可以幫助我們檢測,通常返回的結果是一個字符串,可能的情況如下。
1)number:數值。
2)string:字符串值。
3)boolean:布爾值。
4)undefined:未定義。
5)object:(對象)或者null。
6)function:函數。
2.2.2 初始類型
初始類型在內存中是在棧區保存的,因為一個初始類型的數據在內存中所占的長度總是固定的。
1.Number(數值)
和其他編程語言不同,在JavaScript 中不區分整型和浮點型數值,即數值類型包括整型和浮點型,支持二進制(0b)、八進制(0o)、十進制、十六進制(0x)。用科學計數法來表示,還包括一些特殊的值:Number.MAX_VALUE(最大值);Number.MIN_VALUE(最小值)。
示例:
ES6中規定:二進制使用0b開頭,八進制不再使用0開頭,而是使用0o開頭,十六進制依然使用0x開頭。
示例:
2.String(字符串)
用單雙引號來說明,它所包圍的值都可以是字符串。
單雙引號的用法:效率是一樣的;只能成對出現,不能相互交叉使用;可以相互嵌套。
還包括一些特殊的字符,具體見表2-3。
表2-3

在ES6中還新增了模板字符串。模板字符串使用反引號(``)來代替普通字符串中的雙引號和單引號。之所以稱為模板字符串,是因為模板字符串中的插值特性。
在模板字符串中可以方便地引入變量:
說明:在上述示例中,${year}、${month}和${date}稱為模板占位符,這樣就可以很方便、很優雅地將JavaScript的值插入到字符串中。
在模板字符串中可以進行變量運算,示例如下:
說明:模板占位符可以是任何JavaScript 表達式,故函數調用以及四則運算都是合法的。
3.booIean(布爾值)
只有兩個特殊的值true和false,用來表示真或假。
4.undefined(未定義)
當一個變量聲明了但未被賦值時就會被默認賦值為undefined。此外,在一些其他地方,如對象未被賦值的屬性、函數沒有定義的返回值等都會被自動賦值為undefined。
5.nuII(空對象)
空類型,表示一個占位符或清空一個對象,通常用于清空對象。
對象的屬性名現在可以有兩種類型,一種是原來就有的字符串,另一種就是新增的Symbol類型。
6.SymboI
Symbol 類型是一種特殊的、不可變的數據類型,表示唯一的值,可以保證不會與其他屬性名產生沖突。
Symbol函數的參數只是表示對當前Symbol 值的描述,因此相同參數的Symbol函數的返回值是不相等的。
示例:
說明:每一個Symbol值都是不相等的,所以Symbol值可以作為標識符。
屬性名的遍歷:
1)Symbol.for()。
有時,我們希望重新使用同一個Symbol 值,Symbol.for 方法可以做到這一點。它接受一個字符串作為參數,然后搜索有沒有以該參數作為名稱的Symbol 值。如果有,就返回這個Symbol值,否則就新建并返回一個以該字符串為名稱的Symbol值。
Symbol.for()與Symbol()這兩種寫法,都會生成新的Symbol。它們的區別是,前者會被登記在全局環境中供搜索,而后者不會。
示例:
2)Symbol.keyFor()。
Symbol.keyFor方法用來獲取Symbol注冊表中與某個Symbol關聯的鍵。
示例:
注意:使用Symbol作為屬性名時,該屬性將不會被for...in遍歷,不會被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。
2.2.3 引用類型
引用類型在內存中存儲在堆區,當訪問一個引用類型時,只是在訪問它的應用地址。關于引用類型的詳細介紹,參見第5章。
2.3 JavaScript運算符
在JavaScript 程序中,不僅要定義不同數據類型的變量,還要對這些變量進行操作。操作時采用JavaScript 本身提供的運算符。本節主要描述了JavaScript 的運算符,包括算術、關系、賦值、邏輯、一元、三元、特殊運算符等。
在介紹運算符之前,我們先來了解一個常見的概念——表達式。
表達式是一組可以計算出一個數值的有效的代碼的集合。簡單地說,任何即將賦值或已經賦值的都是一個表達式。除了表達式以外的都是運算符。
JavaScript中有如下類型的運算符:
1)算術運算符。
2)關系運算符。
3)賦值運算符。
4)邏輯運算符。
5)一元運算符。
6)三元運算符。
7)特殊運算符。
2.3.1 算術運算符
算術運算符取數值作為其操作數,并且返回一個數值。標準的算術運算符就是加、減、乘、除。
算術運算符包括“+”“-”“*”“**”“/”“%”“i++”“++i”“i--”“--i”。
加號(+)運算符和代數中的用法一樣,用來進行數值的求和運算,在JavaScript 中還有一個用法就是進行字符串的拼接。
1)用于數值的求和運算:
2)用于字符串的拼接:
說明:任何的數據類型和字符串相加都是等于相加以后的字符串。
減法(-)、乘法(*)和除法(/)跟代數中是一樣的運算方式,需要注意的是,不僅是數值,其他類型的數據也可以進行這些運算。
說明:上述示例中,操作數a 和b 都是標準數值的字符串類型,當進行算術運算時,會發生隱式的轉換:先將操作數轉換為數值類型再進行操作;如果轉換不成功,即得不到一個數值結果,則會得到一個NaN(not a number)。有關數據類型的轉換詳見3.2.2節。
取余(%)用來取某個數的余數,或用于取一段范圍的值。
一般不用于小數,因為結果不確定(不精確)。
i++是先運行,再自增。++i是先自增,再運行。
示例:
i--是先運行,再自減。--i是先自減,再運行。用法同自增。
指數運算符(**)是ES6中新增的一個運算符操作,即可以進行指數運算。
示例:
2.3.2 關系運算符(或比較運算符)
關系運算符會比較它的操作數并返回一個基于表達式是否為真的boolean類型的值。操作數可以是任何類型的數據。遇到字符串類型的數據做比較時,會使用Unicode 值。具體見表2-4。
表2-4

注意,=>不是運算符,是箭頭函數的標記符號。
== 和===的區別:
1)== 對數值比較是否相等。
2)===對數值比較是否相等,并且比較數據類型是否相同。
示例:
注意:
1)如果兩個操作數都是字符串,則比較兩個字符串對應的字符編碼值,直到比較出大小。
2)如果一個數值和布爾值進行比較,則會把布爾值轉換為數值再進行比較,true為1,false為0。
3)當一個是字符串,另一個是數值時,則把字符串嘗試轉換成數值類型,然后進行比較,如果轉換不成功,則返回false。
等性運算特例,見表2-5。
表2-5

2.3.3 賦值運算符
賦值運算符旨在將它右邊操作數的值賦值給左邊的操作數,見表2-6。
表2-6

示例:
說明:如上述示例中的x+=y的加法賦值運算,就相當于計算x=x+y。
2.3.4 邏輯運算符
邏輯運算符分為3 部分:邏輯與“&&”、邏輯或“||”、邏輯非“!”,常用于布爾值之間。當用于非布爾值時,返回的是一個特定的操作數的值,即返回的值可能是非布爾值。
邏輯運算符的運算一旦得到結果,運算立即停止,最終結果取決于運算停止的表達式。
1. 邏輯與
關于邏輯與運算,下面分兩種情況進行介紹。
情況1:運算數為布爾類型的值,具體見表2-7(1)。
表2-7(1)

情況2:運算數為其他類型的值。
示例:
總結見表2-7(2)。
表2-7(2)

2. 邏輯或
關于邏輯或運算也分兩種情況進行討論。
情況1:運算數為布爾類型的值,具體見表2-8(1)。
表2-8(1)

情況2:運算數為其他類型的值。
示例:
總結見表2-8(2)。
表2-8(2)

3. 邏輯非
! 運算符,即執行取反操作,假的變成真的,真的變成假的,該運算符返回的一定是布爾值。
示例:
小結:
邏輯運算符可以對任何類型的數據進行運算,但是在運算后,可以轉換為對應的布爾值,具體見表2-9。
表2-9

能轉換為false的值有undefined、null、0、NaN、空字符串。
短路原則:
1)如果第一個運算數決定了結果,則不再計算第二個運算數。
2)對于邏輯與運算來說,如果第一個運算數是false,那么無論第二個運算數的值是什么,結果都不可能為true,所以將不會計算第二個運算數。
3)對于邏輯或運算來說,如果第一個運算數是true,那么無論第二個運算數的值是什么,結果都不可能為false,所以將不會計算第二個運算數。
示例:
2.3.5 一元運算符
1.typeof運算符
typeof運算符可以返回任意一個數據的數據類型,示例如下:
2.自增/自減運算符
所謂自增/自減運算符就是,數值進行加1或減1的操作,示例如下:
第2行代碼對num進行了加1操作,實質上等價于:
3.new運算符
new 運算符的作用是創建一個對象實例,詳見第4章。
4.deIete運算符
delete 運算符用來刪除一個對象或一個對象的屬性,詳見第4章。
示例:
說明:上述示例表明,如果delete操作成功,則變量會變成undefined。但是如果變量是通過關鍵字聲明的,則刪除不成功。
5.+(正)和-(負)運算符
示例:
2.3.6 三元運算符
三元運算符是JavaScript 中唯一需要3 個操作數的運算符,運算結果根據給定條件在兩個值中取其一為變量賦值。
格式:
如果條件為真,則結果為值1,否則為值2,示例如下:
說明:當age 大于等于25 時,將“老師”賦值給position,當age 小于25時,將“學生”賦值給position。
示例:
說明:三元運算符可以等同于if…else流程控制結構。有關流程控制將在下節中詳細介紹。
2.3.7 特殊運算符
1. 逗號運算符
逗號運算符常用在變量聲明中,用來一次性聲明多個變量或for 循環,在每次循環時對多個變量進行更新。
示例:
2. 小括號運算符
小括號運算符在運算時可以確定計算一個表達式的順序,即改變運算的優先級。
示例:
2.4 JavaScript流程控制
HTML 中存在默認的文檔流順序,才能讓代碼在頁面中對應的位置正確地呈現。同樣地,JavaScript 中程序代碼的執行也有一定的順序,但是通常情況下需要讓程序代碼按照我們指定的方式去執行,為此JavaScript提供了一套靈活的語句集——流程控制。
流程控制是每一個高級語言的核心語法,也是程序之所以能稱之為程序、程序之所以能有思想并按照我們的意愿去執行的必要條件。本書中寫的每一個功能、每一個應用都有流程控制的語法。其中,if…else 是管控邏輯的,循環是用來幫助我們程序化處理大量流程和數據的。
2.4.1 名詞解釋
1.流程
流程就是程序代碼的執行順序,一條一條語句地執行。
2.流程控制
通過規定的語句(在JavaScript 中,任何一條表達式都可以看作一條語句,每條語句間用分號隔開)讓程序代碼有條件地按照一定的方式執行。
3.3種流程控制
(1)順序結構
按照書寫順序來執行,一行行地解釋執行,順序結構是程序中最基本的流程結構。
如果想讓程序代碼在某種條件下執行,就必須用到接下來的選擇結構。
(2)選擇結構(分支結構、條件結構)
根據給定的條件有選擇地執行相應的語句。
(3)循環結構
在給定的條件滿足的情況下,反復地執行同一段代碼。
2.4.2 選擇結構
在選擇結構中,會根據if 語句指定的條件執行特定的語句,返回對應的結果。if 語句是一種較為基本的控制語句,這種語句有兩種形式,一種是:
在這種形式中,當條件或值是真值時,后面只能緊跟著一條執行語句。當執行語句有多條時,可以將多條語句合并成一條,具體形式如下:
示例:
1.分支結構
(1)單路分支
當判斷一個邏輯條件為真時,用if語句執行一個語句,否則不做任何處理。
示例:
若條件不成立或值為假,則不執行內部代碼。可理解為:跳過。
示例:
說明:在上述示例中,通過方法prompt()輸入隨機的成績并保存在變量cords 中,通過條件判斷,若獲取的成績比60大,則彈出“及格”,否則不做任何處理。
(2)雙路分支
相比較于單路分支,當判斷一個邏輯條件為真時,多路分支用if語句執行一條語句;當條件或值為假時,使用else從句來執行這個語句。
必定執行,且只能執行其中的一段代碼。
示例:
說明:在上述示例中,將輸入的成績與60 進行比較,當成績大于60 時,彈出“及格”,后面的代碼將不再執行。當成績小于60 時,先判斷是否大于60,若該條件不滿足,則繼續執行else 語句,最終彈出“不及格”。若讀者不清楚代碼到底是如何執行的,可以打開火狐瀏覽器的FireBug工具或者谷歌瀏覽器的開發者工具進入Sources一欄,給代碼添加斷點進行調試。
(3)多路分支
當需要判斷多個條件或值時,可以采用多路分支。多路分支是組合語句通過else if來測試連續的多個條件或值的判斷。
第1種形式:
第2種形式:
示例:
(4)嵌套分支
if語句還可以相互嵌套來使用,語法格式如下:
示例:
說明:在多路分支示例的基礎上,這里實現嵌套分支。在成績大于等于90 的條件下,再來判斷它是否等于100并彈出“滿分”。
下面通過分支結構來實現一個有關成績錄入的示例,代碼如下:
注意:條件滿足的情況不可重復,以免造成不可預期的結果,示例代碼如下:
2.條件結構
在if語句中,可以通過else if創建多條分支,以處理不同的情況,但是這么多分支如果都依賴于同一個表達式的值,則重復地使用多條if語句會很麻煩。而這種情況,switch語句可以很好地處理。在switch 語句中允許一個程序請求一個表達式的值并且嘗試去匹配表達式的值到一個case 標簽。如果匹配成功,則這個程序執行相關的語句。switch 語句的語法格式如下:
注意:break 語句與每一個case 語句相關聯,用來保證匹配的語句在執行完成后可以跳出switch 并繼續執行switch 后面的語句。如果不寫break,則程序會從匹配的語句開始執行,并繼續執行下一條語句,直到全部執行完。
示例:
說明:在上述示例中,通過條件結構實現了星期幾的輸出。需要注意的是,通過prompt()輸入的數據都是字符串類型的,所以每個表達式的值都必須是字符串類型的。有興趣的讀者也可以參考第3章,將得到的成績轉換成數值類型的,再進行匹配。
總結:
當判斷某種范圍時最好用if 語句,當判斷單個值時用switch 語句。例如,分支結構示例中成績的判斷,若使用switch語句實現,那么就要寫100種情況,比較麻煩,不適合。
2.4.3 循環結構
循環結構是一系列反復執行直到找到符合特定條件的命令。對于比較簡單的循環情況,完全可以用if語句來完成,示例如下:
說明:如上述示例,當a 的值比7 大,甚至超過100 時,再用if 語句來完成就比較麻煩。為了更方便地實現循環,JavaScript中專門提供了用來實現循環的for、while和do while語句。另外,可以在循環語句中使用break和continue語句來中斷或跳出循環。
示例:
1.for
for語句會反復循環直到一個特定的條件計算為假。同時for語句對循環做出了簡化,即每次開始循環之前都會初始化變量,每次執行循環之前都會檢測變量的值,最后變量做自增或自減操作。語法示例如下:
說明:在上述示例中,通過for循環在頁面中輸出金字塔,輸出結果如圖2-2所示。

圖2-2
2.whiIe
while 語句是一個基本循環語句,在執行循環之前,會先檢測條件得到的結果是否為真值,如果為真就會執行循環體,否則跳過循環體執行程序中的下一條語句。語法示例如下:
說明:在上述示例中,當條件表達式a < 5的值為false時,循環體內的語句停止執行,會跳出循環體執行之后的語句。故此處a的值最終為6。
3.do whiIe
do while 語句和while 語句非常相似,不同的是,它的循環體每次至少會執行一次,主要原因是由于它檢測條件得到的結果是否為真值是在循環的尾部執行。語法如下:
do while語句第一次執行時會在條件判斷之前先執行一次,然后再進行條件判斷。在每次語句執行完畢時都會執行條件判斷。若條件表達式為false,則跳出循環繼續執行下面的語句。
示例:
說明:在上述示例中,do while循環至少執行一次,然后重復執行直到a不再小于5。
小結:
(1)do while 和while的區別
1)while:當條件滿足時,執行循環體,當不滿足的時候退出循環,先判斷后執行。
2)do while:先最少執行一次,再進行條件判斷,如果條件滿足則繼續執行,如果不滿足則退出循環。
(2)for和while的區別
1)for:一般用于循環次數已指定的情況。
2)while:根據條件的真假來循環,當為真時進行循環,為假時則退出循環。
(3)break和continue
在循環結構中,當條件滿足需求時需要跳出循環或者從一個位置跳到另一個位置。在JavaScript中能實現跳轉的語句有break和continue。
1)break:跳出并終止當前循環,并繼續執行后面的語句。
示例:
說明:在上述示例中,循環輸出i,直到i的值為3跳出循環。
2)continue:跳出并終止當前循環,和break 不同的是,如果下個值還滿足,則繼續執行下一次循環體,而不是終止整個循環。
示例:
說明:在上述示例中,當i 的值為3 時,輸出當前的值并跳出循環,但它只是跳出了當前循環,并沒有跳出整個循環。
小結:
1)break經常出現在switch語句和循環語句中。
2)在switch語句中,當條件滿足時,break用于退出switch語句。
3)在循環中,可以在任何地方通過break來提前退出當前循環。
4)continue在循環中,會跳出并終止當前循環,轉而繼續執行下一次循環。
5)continue只能出現在循環體內,所以最好還是用適當的語句代替continue。
4. 標簽語句
標簽語句可以提供一種使開發人員在同一程序的另一處能找到它的標識,并用break 或者continue來說明是中斷整個循環,還是跳出當前循環繼續執行。
語法格式如下:
注意:標簽名只可以作用于break 或continue。
示例:
說明:如上述示例中,out標簽定義了一個for循環,當第一層循環i = 0的時候,會循環1次第二層循環,此時當j=3的時候,用break語句中斷out標簽定義的for循環。
- 中文版Dreamweaver CC基礎培訓教程(移動學習版)
- OPENStack云框架應用管理實踐
- P2P網絡測量與分析
- 現代網絡控制技術及應用
- 信息主導論
- 綜合布線實訓教程(第2版)
- 深度學習:主流框架和編程實戰
- 用Microsoft Project 2007構建企業項目管理信息系統
- JavaScript+jQuery前端開發基礎教程(微課版)
- Python Network Programming
- Wireshark網絡分析從入門到實踐
- Google Plus First Look:a tip-packed,comprehensive look at Google+
- 系統工程的藝術:用基于模型的系統工程方法構建復雜系統(原書第2版)
- 中文版Dreamweaver CS6基礎培訓教程(第2版)
- Bootstrap 4 Web設計與開發實戰