為了構建更健壯的大型JavaScript應用程序,應先測試,后編碼
資深開發人員仍然在與大型JavaScript應用程序的失敗做斗爭,而這往往是由于應用程序自身的規模而導致的。本書以測試驅動工作流的形式提供了解決方案,它將產生經得起時間考驗的健壯應用程序。本書將使用單元測試解釋、演示和采用各種JavaScript模式和結構。隨著本書的學習,你將成為JavaScript測試驅動開發的專家,勝任開發商業軟件。如果準備在JavaScript開發中引入高級軟件工程,那么本書正是*佳之選。
主要特色
◆展示了如何編寫開始就被確認為正確的代碼,并使用測試讓代碼在接下來的維護過程中仍然保持正確
◆概述用于測試、依賴注入和面向方面編程的JavaScript框架目前的現狀
◆解釋可測試性特征以及構建可測試對象的方式
◆演示常見設計模式以及高級JavaScript特性和架構的實現和使用
◆涵蓋DOM訪問測試,包括過度更新、在循環中的過度訪問以及XHR/JSONP請求
本書分為5個部分:
第Ⅰ部分“奠定堅實的基礎”涵蓋了軟件工程的關鍵概念,例如SOLID和DRY原則,還討論了單元測試和測試驅動開發的優點。
在第Ⅱ部分“測試基于模式的代碼”中,我們描述并使用測試驅動開發創建了幾個有用的代碼模式。
第Ⅲ部分“測試和編寫高級JavaScript特性”描述了如何使用和測試JavaScript語言更高級的特性。
第Ⅳ部分“測試中的特殊主題”提供了測試DOM操作的樣例,還演示了用于增強代碼標準的靜態分析工具的使用。
第Ⅴ部分“總結”回顧了測試驅動開發的概念,還展示了一些本書用到的JavaScript習語。
當我們與開發者同仁分享本書的書名《編寫可靠的JavaScript代碼》時,我們收到了如下反饋:
“‘可靠的’和‘JavaScript代碼’這兩個詞現在能放在一塊?”
“這一定是一本非常薄的書。”
“我是否會在書店的小說區域John Grisham最近的驚悚小說附近找到它?”
不,本書不是小說。
我們收到的關于本書書名的反饋表明了一些具有經典的、編譯語言經驗的開發者對于JavaScript的普遍看法:JavaScript被用于創建華麗的作品集網站或者簡單的應用程序,它與任務關鍵的企業應用程序沒有關系。
在過去這種觀點是事實,但現在已經改變了。
JavaScript作為一流語言崛起
JavaScript作為野孩子的聲譽是應得的,在接下來的兩個小節中我們將揭示它的一些漏洞。不過,就像被寵壞的繼承者一樣,在繼承了家族事業之后,通過提出挑戰讓所有人都感到震驚。但最近他變得嚴肅和負責,顯示出真正偉大的能力。
JavaScript早期僅僅被托付一些短“腳本”任務。任務非常簡單:如果所需的字段未被填充,就將它標記為紅色;如果按鈕被單擊了,就應該將另一個頁面帶入視圖。盡管它的責任有限,但易于相處。到今天為止,大多數程序員使用JavaScript的經驗都是此類。
接著,在重新定義JavaScript的變革中,世界轉向了Web。這一直是JavaScript游樂場,當The Old Boys Club的成員在服務器上完成真正的工作時,他就在Web中娛樂自己。
在20世紀90年代末期,當微軟引入iframes和XMLHTTP時,變革開始被阻礙。而當Google在2004年和2005年分別使Ajax成為Gmail應用程序和Google Maps的一部分時,變革開始崩潰。世界突然注意到當瀏覽器被賦予更多任務時(不只是顯示服務器分配的內容),Web體驗可以如此豐富。
所以JavaScript被賦予了更多的責任,超出了任何人的計劃。JavaScript需要得到幫助。
此時幫助也應運而來,以工具包和框架的形式存在,例如jQuery、 Ext JS、 Ember.js、 Knockout、Backbone和AngularJS。這些有價值的顧問完成了所有他們能做的事情,為JavaScript帶來了準則和結構。
使用JavaScript編寫真正糟糕的代碼是非常簡單的
問題的部分原因是JavaScript作為頁面腳本語言存在多年。在那個有限的范圍內,使用全局變量或全局函數并沒有問題。如果變量拼寫錯誤,影響非常有限、也易于追蹤(另外,影響可能是創建了另一個全局變量)。如果架構非常草率……那么有多少架構甚至可以只存在于一個Web頁面上呢?
編譯器的缺少隱藏了潛在的錯誤。使用C#或Java編寫的服務器端程序在運行之前至少可以保證語法上是正確的。而JavaScript則必須啟動,然后就只能預祝好運了。拼寫錯誤的變量或者調用不存在的函數都可能潛伏在代碼中數月之久,直到遵循了特定的執行路徑。
接著就是JavaScript的怪癖,一些可愛的、瘋狂的怪癖。
這個列表的頂部一定就是==(使用類型強制轉換的相等)和===(不使用類型強制轉換的相等)。這是一個好想法,但是對于主要使用其他語言的程序員來說是如此難以適應!
JavaScript擁有“真”和“假”的概念,它們讓很多人感到糊涂。0是假值,因此多虧了類型強制轉換(type coercion),表達式:
false == '0'
的結果是真。值false被強制轉換成一個數字,也就是0(真被轉換為1)。接下來,字符串‘0’也被強制轉換成數字,也是0,所以表達式的結果是真。
不過,false == 'false'的結果是假,因為左側的false再次被強制轉換成0,與右側字符串‘false’相比,也被強制轉換成數字。因為‘false’根本不是數字,所以第二個轉換將產生NaN(Not a Number),相等性檢測失敗。
如果聲明了下面的函數:
function letsHaveFun(me, you) {
// Fun things happening between me and you
}
然后調用它,因此:
letsHaveFun(me);
JavaScript將在變量you未定義的情況下執行調用,只是為了開心地看著你與某個不存在的人玩耍。
這個代碼清單可以不斷擴展下去。還有令人吃驚的作用域規則、獨特的“原型”繼承機制、自動的和有時不正確的分號插入、一個對象從另一個完全無關的對象借用函數的功能等 。
伴隨著全局變量的不請自來、幾乎完全缺少的架構設計、與真理的可疑關系以及比動漫大會上發現的更多的怪癖,JavaScript能做到如此好的地步真是一個奇跡。
無論你相信與否,它在變好之前會變得更糟糕。即使你是正確的,它也可能會非常容易出現問題。
JavaScript代碼容易被無意間破壞
JavaScript有一種病態的幽默感。在一門穩重的編譯語言中,如果有一行完全正確的調試代碼在生產環境中運行得非常完美,例如:
myVariable = myObject.myProperty;
這時如果不小心碰到了鍵盤上的x鍵,那么它就變成了:
myVariable = myObject.myPropxerty;
編譯器就會立即發出一條嚴厲的消息,警告下次一定要更加小心。而JavaScript則會高興地運行該代碼,并將undefined的值賦給myVariable。
當你希望改變屬性的名稱時,JavaScript喜歡玩捉迷藏。你可能會認為在整個源目錄中搜索.myProperty就可以找到所有需要改動的地方。“不,不,不!”JavaScript笑著說。“你忘了搜索['myProperty']。”
實際上,應該使用正則表達式進行搜索,允許在括號和引號之間含有空格。你曾經這樣做過嗎?我們都沒有。
你還應該搜索下面這樣的結構:
var prop = 'myProperty';
// . . .
myObject[prop] = something;
即使是如此小的重構也很難完成,因此可以想象錯誤的產生是多么容易。不適合重構的代碼幾乎是單詞“脆弱”的定義。
如何才能避免這些問題呢?如果有一個我們希望在本書進行宣揚并實踐的概念,那么就是測試驅動開發。在不存在編譯器的情況下,測試是針對錯誤的最佳防御。
JavaScript也更加適用于按照軟件工程的規則進行開發。實際上,由于JavaScript具有創造性,因此比其他語言更需要這些規則。
我們見過許多開發人員都對這個信息抱著開放的態度,并且希望學習更多相關知識。我們希望你是其中一員。
本書面向的讀者
因為本書不是一本JavaScript入門書籍,所以我們假設你已經有一些JavaScript經驗。下面勾勒了本書理想讀者的特點。
從其他語言轉向JavaScript的開發人員
我們的職業生涯都不是從JavaScript開發人員開始的,可能也不是當JavaScript遇到大規模應用開發時才進入程序開發領域的。
JavaScript與我們曾經使用過的任何語言都大不相同。我們來自于編譯的、靜態類型語言C#的舒適世界。
當我們在保持C#程序員的架構和準則,并擁抱JavaScript的動態特性時,JavaScript就會容易掌握。
如果你具有使用JavaScript之外的語言(例如C#或Java)進行思考和編程的背景的話,本書是適合你的。數據結構和架構方面的知識將為你掌握JavaScript的大規模開發提供牢固的基礎。
許多小節都演示了C#和Java中的語言特性(例如繼承和接口)是如何對應于JavaScript中的功能的。我們還強調了JavaScript和其他語言之間的許多主要區別,例如作用域規則和類型強制轉換相等性比較。掌握JavaScript功能和特性的相關知識將改善你用JavaScript思考的能力。
本書的另一個關注點是如何將C#和Java開發中更常見的軟件工程概念和實踐應用到JavaScript中,例如設計模式、單元測試和測試驅動開發。合理的軟件工程可以緩和JavaScript的本性,創建可靠的和可維護的代碼。
具有小規模JavaScript經驗的開發人員
在我們努力為團隊增加具有JavaScript經驗的開發人員時,我們遇到了許多候選人,都覺得具有小規模JavaScript開發經驗(例如輸入域驗證和jQuery元素轉換)就值得將“JavaScript”列在簡歷的重要位置。
在面試中,判斷這樣的候選人不需要花費太多時間:可能在ASP.NET Web Forms應用程序中,他們可以輕松地使用按鈕處理程序,但是創建一個JavaScript模塊,并在其中使用防止被外部操作的變量就比較困難了。
隨著機構對JavaScript使用的進一步深化,我們對擁有JavaScript經驗的定義也隨之嚴格。數年之前,如果開發人員有點jQuery經驗,我們就會對他的JavaScript經驗非常滿意了。
不過,現在我們需要更多的經驗。使用JavaScript編寫整個應用程序已經不再是鳳毛麟角了。在所謂的單頁面應用(Single-Page Application,SPA)中,JavaScript代碼將組成整個應用程序,與過去瞬間的單擊處理程序相比,現在它承擔著更多的責任。為了參與大規模JavaScript應用程序的開發,開發人員必須知道如何以結構化和規定的方式使用該語言,并同時使用它的許多獨特功能和特性。
通過本書的樣例,我們希望你——小規模JavaScript開發人員——能夠參與大規模JavaScript應用程序的開發。
負責為新項目挑選編程語言的開發人員
可能你已經聽過這個諺語:“沒有人會因為購買IBM產品而被解雇”。這個諺語反映了一種感覺:在為IT項目選擇技術合作伙伴時,選擇穩定的、有信譽的公司(例如IBM)是不會受到質疑的。即使項目費用超支、逾期或完全失敗,選擇IBM也是無可指責的。
如果你正處于為新應用選擇開發語言的位置,那么就處于與IT管理者選擇技術合作伙伴一樣的位置。有許多具有悠久歷史并經過眾人嘗試和驗證的語言,例如C#和Java,它們都是由大型、穩定的技術公司所支持的,已經被用于構建Web和桌面應用超過十年。沒有人會因為選擇C#被解雇。
從新程序設計項目的安全選擇來看,尤其是企業級的項目,JavaScript明顯與C#不同。JavaScript不是一門成熟、穩定、正式的編程語言。
與C#和Java這樣的語言相比,它沒有大規模軟件項目的、長期的成功記錄。這不是說使用C#和Java的項目就一定成功。不過,如果使用了其中一種語言的項目不成功,語言的選擇可能不會被包含在失敗的原因中。
如我們在之前小節中所提到的,使用JavaScript非常容易編寫出災難性的代碼。這為它帶來了一點糟糕的名聲,降低了選擇它的可能性。
不應該因為JavaScript的聲譽而自動將它排除在項目的考慮之外,因為我們可以從它的強大功能中獲益。Node.js——一個服務器端的JavaScript引擎——是輕量級的并且高度可伸縮的;對于實時和數據敏感應用程序來說是非常完美的選擇。JavaScript可以被用于在瀏覽器中創建富用戶界面。客戶端框架(例如Ember和AngularJS)可以被用于構建完整的、基于瀏覽器的應用程序,可以通過將展示邏輯轉移到客戶端的方式減輕Web服務器的負擔。
盡管我們不能保證它會成功,但是接下來的章節將展示如何通過應用我們在自己項目中所學到的教訓,在下一個項目選擇JavaScript時降低風險。
成功不是偶然的,尤其是在使用JavaScript時。它要求牢固掌握軟件工程原則,這是第1章的主題。
本書的組織結構
我們將本書劃分為5個部分。
第Ⅰ部分“奠定堅實的基礎”涵蓋了軟件工程的關鍵概念,例如SOLID和DRY原則,還討論了單元測試和測試驅動開發的優點。第Ⅰ部分還介紹了本書使用的工具和JavaScript庫。最后,討論了JavaScript中的對象和它們的可測試性。
在第Ⅱ部分“測試基于模式的代碼”中,我們描述并使用測試驅動開發創建了幾個有用的代碼模式。其中一些模式(例如單例)可能與其他你所熟悉的語言中的模式類似。其他(例如承諾)主要是與JavaScript相關的。
第Ⅲ部分“測試和編寫高級JavaScript特性”描述了如何使用和測試JavaScript語言更高級的特性。它還涵蓋了使用了高級編程架構的應用的創建和測試,例如中介者和觀察者模式。
第Ⅳ部分“測試中的特殊主題”提供了測試DOM操作的樣例,還演示了用于增強代碼標準的靜態分析工具的使用。
第Ⅴ部分“總結”回顧了測試驅動開發的概念,還展示了一些本書用到的JavaScript習語。
使用本書所需的工具
為了運行本書的樣例,需要使用下列工具:
● 文本編輯器
● Web瀏覽器
樣例的源代碼可以從Wrox網站下載:
www.wrox.com/go/reliablejavascript
基于本書的開源軟件可以在GitHub上找到:
www.github.com/reliablejavascript
源代碼
當你瀏覽本書的樣例時,可能會選擇手動輸入所有代碼,或者使用隨書提供的源代碼。本書使用的所有源代碼都可以從www.wrox.com和www.tupwk.com.cn/downpage下載。對于本書來說,代碼下載文件在下面網址的Download Code選項卡中:
www.wrox.com/go/reliablejavascript
也可以在www.wrox.com中通過ISBN搜索本書找到代碼。所有當前Wrox圖書的代碼下載的完整文件列表在www.wrox.com/dynamic/books/download.aspx 中。
www.wrox.com的大多數代碼都采用.ZIP、.RAR或者適用于特定平臺的類似歸檔模式進行了壓縮。下載了代碼之后,只需要使用適當的壓縮工具解壓即可。
注意:
因為許多書都有相似的書名,所以你可能發現使用ISBN搜索是最容易的;本書英文版的ISBN是978-1-119-02872-7。
勘誤表
盡管我們竭盡所能來確保在正文和代碼中沒有錯誤,但人無完人,錯誤難免會發生。如果你在Wrox出版的書中發現了錯誤(例如拼寫錯誤或代碼錯誤),我們將非常感謝你的反饋。發送勘誤表將節省其他讀者的時間,同時也會幫助我們提供更高質量的信息。
要找到本書的勘誤頁面,可以進入www.wrox.com,使用Search搜索框或書名列表找到本書,然后在本書的詳細信息頁面上單擊Book Errata鏈接。在這個頁面上可以查看為本書提交的、Wrox編輯粘貼上去的所有錯誤。完整的書名列表(包括每本書的勘誤表)也可以從www.wrox.com/misc-pages/booklist.shtml上獲得。
如果在本書的勘誤頁面上沒有看到你發現的錯誤,則可以到www.wrox.com/contact/ techsupport.shtml 上填寫表單,把你發現的錯誤發給我們。我們會檢查這些信息,如果屬實,就把它添加到本書的勘誤頁面上,并在本書隨后的版本中更正錯誤。
p2p.wrox.com
如果想和作者或同行進行討論,請加入p2p.wrox.com 上的P2P論壇。該論壇是一個基于Web的系統,你可以發布有關Wrox圖書及相關技術的消息,與其他讀者或技術人員交流。該論壇提供了訂閱功能,當你感興趣的主題有新帖子發布時,系統會郵件通知。Wrox的作者、編輯、其他業界專家和像你一樣的讀者都會出現在這些論壇中。
在p2p.wrox.com網站上,你會找到很多不同的論壇,它們不但有助于你閱讀本書,還有助于你開發自己的應用程序。加入論壇的步驟如下:
(1) 進入p2p.wrox.com,單擊Register鏈接。
(2) 閱讀使用條款,然后單擊Agree按鈕。
(3) 填寫加入該論壇必需的信息和其他你愿意提供的信息,單擊Submit按鈕。
(4) 你將收到一封電子郵件,描述如何驗證你的賬戶和完成加入過程。
加入之后,就可以發布新的消息和回復其他用戶發布的消息。可以隨時在Web上閱讀論壇里的消息。如果想讓某個論壇的新消息以電子郵件的方式發給你,可以單擊論壇列表中論壇名稱旁邊的Subscribe to this Forum圖標。
要了解如何使用Wrox P2P的更多信息,請閱讀P2P FAQ,其中回答了論壇軟件如何使用的問題,以及許多與P2P和Wrox圖書相關的問題。要閱讀FAQ,單擊任何P2P頁面上的FAQ鏈接即可。
……
查看全部↓
Lawrence D. Spencer,領導SeerIS的一個國際開發者團隊,SeerIS公司是波士頓附近的一家軟件和服務公司。他擁有超過35年的工作經驗,曾經擔任過管理人員、開發人員、咨詢師以及講師,經常出席編程大會。
Seth H. Richards,從2002年開始一直專業制作軟件。他的工作專注于基于Web的企業級地理信息系統應用。
第Ⅰ部分 奠定堅實的基礎
第1章 實踐軟件工程 3
1.1 編寫從開始就正確的代碼 4
1.1.1 掌握JavaScript的特性 4
1.1.2 在大型系統中規避JavaScript陷阱 15
1.1.3 應用軟件工程原則 17
1.2 編寫保持正確的代碼 22
1.2.1 投資單元測試的未來 22
1.2.2 實踐測試驅動開發 22
1.2.3 編寫易于測試的代碼 23
1.3 小結 26
第2章 準備工具 27
2.1 使用測試框架 27
2.1.1 辨別不正確的代碼 30
2.1.2 可測試性設計 32
2.1.3 編寫最少的代碼 33
2.1.4 安全維護和重構 33
2.1.5 可運行規范 34
2.1.6 當前的開源和商業框架 34
2.1.7 介紹Jasmine 36
2.2 使用依賴注入框架 41
2.2.1 依賴注入的定義 41
2.2.2 使用依賴注入讓代碼更可靠 43
2.2.3 掌握依賴注入 43
2.2.4 案例研究:編寫一個輕量級依賴注入框架 43
2.2.5 使用依賴注入框架 50
2.2.6 當前的依賴注入框架 52
2.3 使用切面工具 53
2.3.1 案例研究:使用和不使用AOP進行緩存 53
2.3.2 案例研究:構建Aop.js模塊 55
2.3.3 其他AOP庫 67
2.3.4 結論 68
2.4 使用代碼檢查工具 68
2.4.1 使用linting工具讓代碼更可靠 68
2.4.2 JSHint簡介 71
2.4.3 其他工具 73
2.4.4 嚴格模式 74
2.5 小結 74
第3章 構造可靠的對象 75
3.1 使用原生數據 75
3.2 使用對象字面量 77
3.3 使用模塊模式 78
3.3.1 創建任意模塊 78
3.3.2 創建立即執行模塊 79
3.3.3 創建可靠的模塊 80
3.4 使用對象原型和原型繼承 80
3.4.1 默認對象原型 80
3.4.2 原型繼承 81
3.4.3 原型鏈 82
3.5 使用new創建對象 83
3.6 使用類繼承 88
3.6.1 模擬類繼承 88
3.6.2 重復將殺死Kangaroo 89
3.7 使用函數式繼承 91
3.8 猴子補丁(Monkey-Patching) 92
3.9 小結 95
第Ⅱ部分 測試基于模式的代碼
第4章 瀏覽各種模式的優點 99
4.1 案例分析 99
4.2 通過更廣泛的詞匯產生更加優雅的代碼 100
4.3 使用擁有良好設計、良好測試的構建塊產生可靠的代碼 101
4.4 小結 102
第5章 確保回調模式的正確使用 103
5.1 通過單元測試了解回調模式 104
5.1.1 編寫和測試使用了回調函數的代碼 104
5.1.2 編寫和測試回調函數 109
5.2 避免問題 113
5.2.1 扁平化回調箭頭 113
5.2.2 注意this變量 115
5.3 小結 119
第6章 確保承諾模式的正確使用 121
6.1 通過單元測試了解承諾 122
6.1.1 使用承諾 122
6.1.2 構造和返回承諾 127
6.1.3 測試XMLHttpRequest 130
6.2 串聯承諾 133
6.3 使用承諾封裝器 134
6.4 了解狀態和命運 135
6.5 區分標準承諾和jQuery承諾 135
6.6 小結 136
第7章 確保正確使用散函數應用程序 137
7.1 對散函數應用程序進行單元測試 137
7.2 為散函數應用程序創建切面 139
7.3 區分散函數應用程序和柯里化 140
7.3.1 柯里化 140
7.3.2 散函數應用程序 141
7.4 小結 141
第8章 確保備忘錄模式的正確使用 143
8.1 通過單元測試了解備忘錄模式 144
8.2 使用AOP添加備忘錄 147
8.2.1 創建備忘錄切面 147
8.2.2 為restaurantApi應用returnValueCache切面 150
8.3 小結 152
第9章 確保單例模式的正確實現 153
9.1 通過單元測試了解單例模式 154
9.1.1 使用對象字面量實現單例共享緩存 154
9.1.2 使用模塊實現單例共享緩存 158
9.2 小結 162
第10章 確保工廠模式的正確實現 163
10.1 為工廠編寫單元測試 163
10.2 實現工廠模式 169
10.3 考慮其他工廠類型 171
10.4 小結 171
第11章 確保沙箱模式的正確實現和使用 173
11.1 通過單元測試了解沙箱模式 173
11.1.1 創建部件沙箱 174
11.1.2 創建和測試沙箱工具 187
11.1.3 創建與沙箱一起使用的函數 191
11.2 小結 193
第12章 確保裝飾器模式的正確實現 195
12.1 使用測試驅動的方式開發裝飾器 196
12.1.1 為被裝飾的對象編寫一個假對象 197
12.1.2 為錯誤的傳遞編寫測試 198
12.1.3 編寫空白裝飾器 199
12.1.4 添加傳遞功能到裝飾器 200
12.1.5 驗證成功傳遞 202
12.1.6 添加裝飾器的特性 204
12.1.7 通用化裝飾器 210
12.2 小結 211
第13章 確保策略模式的正確實現 213
13.1 通過單元測試了解該模式 213
13.1.1 在不使用策略模式的情況下實現transportScheduler 214
13.1.2 使用策略模式實現transportScheduler 216
13.2 小結 227
第14章 確保代理模式的正確實現 229
14.1 通過測試驅動的方式開發代理 230
14.2 小結 245
第15章 確保正確實現可鏈接方法 247
15.1 通過單元測試了解該模式 248
15.2 鏈接then方法 255
15.3 小結 257
第Ⅲ部分 測試和編寫高級JavaScript特性
第16章 在無接口語言中遵守接口 261
16.1 了解接口的優點 262
16.2 了解接口隔離原則 263
16.3 使用測試驅動開發創建契約注冊表 265
16.3.1 定義契約 266
16.3.2 判斷是否履行了契約 267
16.3.3 斷言契約被履行了 271
16.3.4 繞過契約執行 273
16.3.5 創建在被返回(創建)的對象上實施契約的切面 273
16.4 小結 277
第17章 確保正確的參數類型 279
17.1 了解JavaScript無類型參數帶來的機會和風險 280
17.2 擴展ContractRegistry檢查參數 280
17.2.1 界定任務范圍 280
17.2.2 判斷集合中的所有變量是否都履行了它的契約 281
17.2.3 斷言集合中的所有變量都履行了它的契約 289
17.2.4 在切面中打包參數檢查功能 290
17.3 支持契約庫 292
17.4 綜合起來 293
17.4.1 創建契約模塊 293
17.4.2 創建應用程序的ContractRegistry 296
17.4.3 為生產發布繞過契約 297
17.5 比較面向切面的解決方案和靜態解決方案 297
17.5.1 考慮TypeScript的優點 297
17.5.2 考慮切面的優點 297
17.6 小結 298
第18章 確保正確使用call、apply和bind 299
18.1 瀏覽this是如何綁定的 299
18.1.1 默認綁定 300
18.1.2 隱式綁定 302
18.1.3 new綁定 303
18.1.4 顯式綁定 305
18.2 創建和測試使用call、apply和bind的代碼 305
18.2.1 使用call和apply 305
18.2.2 使用測試驅動開發創建一個Array.prototype.forEach Polyfill 307
18.2.3 使用bind 316
18.3 小結 321
第19章 確保正確使用方法借用 323
19.1 確保借用對象符合需求 324
19.1.1 讓被借用的函數驗證借用者的資格 324
19.1.2 向被借用的對象附加切面 326
19.1.3 使用borrow()方法 329
19.1.4 在ContractRegistry中添加對象驗證器 330
19.2 預期借用者的副作用 331
19.2.1 考慮被隔離函數的副作用 331
19.2.2 考慮調用其他函數的函數的副作用 332
19.3 預期捐贈者對象的副作用 338
19.4 小結 339
第20章 確保正確使用混合 341
20.1 創建和使用混合 343
20.1.1 創建和使用傳統混合 344
20.1.2 創建和使用函數式混合 361
20.2 小結 367
第21章 測試高級程序架構 369
21.1 確保觀察者模式的可靠使用 369
21.1.1 檢查觀察者模式 370
21.1.2 增強觀察者模式的可靠性 376
21.2 確保中介者模式的可靠使用 380
21.2.1 了解中介者模式 381
21.2.2 增強基于中介者代碼的可靠性 382
21.3 小結 395
第Ⅳ部分 測試中的特殊主題
第22章 測試DOM訪問 399
22.1 對UI進行單元測試 399
22.1.1 檢查難于測試的UI代碼 400
22.1.2 使用TDD創建UI組件 401
22.2 使用分析器優化代碼 411
22.2.1 檢測低效代碼 411
22.2.2 避免不成熟的優化 418
22.3 小結 418
第23章 確保符合標準 419
23.1 使用ESLint 420
23.1.1 安裝ESLint 420
23.1.2 運行ESLint 424
23.1.3 使用ESLint實施代碼標準 427
23.2 實施架構分離 432
23.2.1 家庭秘密技術 433
23.2.2 銘記技術 435
23.2.3 不可能任務(Mission Impossible)技術 437
23.2.4 魔術棒(Magic Wand)
技術 441
23.2.5 不要使用調用棧技術 442
23.2.6 其他技術 442
23.2.7 其他架構 442
23.3 小結 443
第Ⅴ部分 總結
第24章 測試驅動開發原則的總結 447
24.1 回顧值得使用測試驅動開發的原因 447
24.2 練習測試驅動開發 448
24.3 編寫可單元測試的代碼 448
24.4 掌握測試驅動開發的
技術 448
24.4.1 在編碼之前編寫測試 448
24.4.2 保持測試DRY 449
24.4.3 首先測試錯誤條件 449
24.4.4 測試要先易后難 449
24.4.5 具體 449
24.4.6 只測試一件事情 450
24.4.7 測試數據如同測試一樣重要 450
24.4.8 高效地使用Jasmine 450
24.5 測試本書描述的模式 450
24.5.1 測試面向切面編程 450
24.5.2 測試對象構造 451
24.5.3 測試回調 451
24.5.4 測試基于承諾的代碼 451
24.5.5 測試散函數應用程序 451
24.5.6 測試備忘錄模式 452
24.5.7 測試單例模式 452
24.5.8 測試工廠模式 452
24.5.9 測試沙箱 452
24.5.10 測試裝飾器模式 453
24.5.11 測試策略模式 453
24.5.12 測試代理模式 453
24.5.13 測試可鏈接方法 453
24.5.14 測試接口一致性 453
24.5.15 測試call和apply的
使用 453
24.5.16 測試方法借用模式 454
24.5.17 測試混合 454
24.5.18 測試中介者和觀察者模式 454
24.5.19 測試DOM訪問 454
24.5.20 實施架構分離的測試 454
24.6 小結 455
第25章 本書JavaScript習語的總結 457
25.1 回顧對象 457
25.1.1 可以添加和刪除的對象屬性 457
25.1.2 可以將對象用作詞典 458
25.2 回顧變量 459
25.2.1 提升變量聲明 459
25.2.2 變量有函數作用域 460
25.3 回顧函數 463
25.3.1 函數是對象 463
25.3.2 提升函數聲明 463
25.3.3 函數沒有返回類型 464
25.3.4 函數可以是匿名的 465
25.3.5 函數可以被嵌套 465
25.3.6 函數調用可以使用任意數量的參數 466
25.3.7 函數可以立即被調用 467
25.4 回顧布爾操作 468
25.4.1 在測試相等性時類型可能會被強制轉換 468
25.4.2 值可以是真或假 469
25.5 小結 469
查看全部↓
前言/序言