隨著 JavaScript 應用的復雜性逐漸提高,開發(fā)者需要有力的調(diào)試工具來幫助他們快速發(fā)現(xiàn)問題的原因,并且能高效地修復它。Chrome DevTools 提供了一系列實用的工具使得調(diào)試 JavaScript 應用不再是一件痛苦的事。
在這個部分,我們會通過調(diào)試 Google Closure hovercard demo 以及其他的動態(tài)示例來讓你了解怎么去使用這些工具。
注意:如果你是 Web 開發(fā)者并且希望獲得最新版的 DevTools,你應該使用 Chrome Canary
源面板允許你調(diào)試 JavaScript 代碼。它提供了 V8 調(diào)試器的圖形化接口。請通過以下步驟來使用源面板:
源面板允許你查看正在瀏覽的頁面上所有的腳本。面板底部的圖標按鈕分別提供了標準的暫停、恢復以及逐條語句運行等操作。窗口底部還有一個按鈕,在出現(xiàn)異常時可以強制暫停。在不同選項卡中,Sources 都是可見的,而且只要點擊 就可以打開文件定位并且顯示全部腳本。
執(zhí)行控制相關的按鈕就在側面板的頂端,它們使得你能夠單步執(zhí)行代碼??捎玫陌粹o有:
在源面板中,有許多相關的快捷鍵可用:
F8
或者 Command
+ \
,其他平臺上為 Ctrl
+ \
。F10
或者 Command
+ '
,在其他平臺上為 Ctrl
+ '
。F11
或者 Command
+ ;
,在其他平臺上為 Ctrl
+ ;
。Shift
+ F11
或者 Shift
+ Command
+ ;
,在其他平臺上為 Shift
+ Ctrl
+ ;
。Ctrl
+ .
。(適用于全平臺)Ctrl
+ ,
。(適用于全平臺)如果想要查看其他支持的快捷鍵,請參考 Shortcuts。
斷點是在腳本中處于某種目的而停止或者暫停代碼運行的地方。在 DevTools 中使用斷點可以調(diào)試 JavaScript 代碼, DOM 更新以及網(wǎng)絡調(diào)用。
在源面板中,打開一份 JavaScript 文件用于調(diào)試。在下面的例子中,我們調(diào)試了來自 AngularJS version of TodoMVC 中的 todoCtrl.js 文件。
點擊行號前的空格來在那一行設置斷點。之后一個藍色的標記將會出現(xiàn),這說明斷點已經(jīng)被設置好了:
你可以添加多個斷點。點擊其他行行號前的空格就可以繼續(xù)設置斷點,你所設置的全部斷點都會在右邊的側欄下 Breakpoints 選項中顯示出來。
斷點前的復選框可以選擇是否啟用斷點,如果斷點被禁用了,那么藍色的標簽會變色。
點擊斷點的入口可以跳轉(zhuǎn)到源文件中的對應行:
點擊藍色的標簽可以刪除斷點。
右擊藍色標簽會打開一個菜單,其中包括:Continue to Here,Remove Breakpoint,Edit Breakpoint 以及 Disable Breakpoint。
想要設置條件斷點,選擇 Edit Breakpoint ,或者,右鍵點擊行號前的空白然后選擇 Add Conditional Breakpoint。在輸入域中,可以輸入任何能夠返回 true 或者 false 的表達式。當條件返回 true 的時候,斷點會中斷代碼的執(zhí)行。
在你想要分析循環(huán)或者經(jīng)常觸發(fā)的回調(diào)事件的代碼時,條件斷點是非常有用的。
注意:有時候你可能不需要從 DevTools 接口來設置斷點。此時你希望從代碼中來啟動調(diào)試器,那么你可以使用 debugger 關鍵字來實現(xiàn)這一操作。
當你設置了一個或多個斷點的時候,返回到瀏覽器窗口并且與頁面進行交互。在下面的例子中,我們在 removeTodo() 方法中加入了斷點?,F(xiàn)在任何想要在 TodoMVC 應用中刪除 todo 選項的行為都將觸發(fā)斷點:
要恢復代碼的運行,在 DevTools 窗口中點擊 Continue 按鈕或者使用
F8
鍵盤快捷鍵。
當腳本暫停運行的時候,你可以使用右邊側欄中的 Watch Expressinos, Call Stack 以及 Scope Variables 面板。
調(diào)用棧面板展示了代碼到暫停處的完整執(zhí)行路徑,這讓我們能夠深入代碼去找出導致錯誤的原因。
如果要查看包括計時器和 XHR 事件在內(nèi)的異步 JavaScript 回調(diào)函數(shù)的執(zhí)行路徑,請點擊 Async 復選框。
更多關于異步調(diào)用棧的信息和示例請參考 HTML5Rocks.com 網(wǎng)頁上的 Debuggin Asynchtonous JavaScript with Chrome DevTools
當你把一個 JavaScript 源文件放到黑盒中時,你在調(diào)試代碼的時候無法跳轉(zhuǎn)到那個文件中了。你可以在你感興趣的代碼嘗試一下。
你可以使用設置面板來將腳本文件放入黑盒,或者右鍵點擊 sources 面板中的文件然后選擇 Blackbox Script。
更多關于黑盒的信息請參考 Blackboxing JavaScript file
DevTools 中的 consle drawer 允許你在調(diào)試器當前暫停的位置附近進行試驗。點擊 Esc 鍵在視圖中打開控制臺,再次按 Esc 鍵就會關閉該控制臺。
F8
來繼續(xù)執(zhí)行提示:注意 dynamicScript.js 文件結尾處的 "//# sourceURL=dynamicScript.js" 這一行。這種方式可以給由 eval 函數(shù)創(chuàng)建的腳本命名,更多的信息會在 Source Maps 這一節(jié)中說明。只有當用戶為動態(tài)的 JavaScript 文件提供了名稱時才能為其設置斷點。
右鍵點擊下面的 "Parent Element" 并且從文本菜單中選擇 Inspect Element(審查元素)
function appendChildButtonClicked() {var parentElement = document.getElementById("parent");var childElement = document.createElement("div");childElement.setAttribute("style", "border: 2px solid; padding: 5px; margin: 5px; text-align: center; width: 120px");childElement.textContent = "Child Element";parentElement.appendChild(childElement);}appendChild
函數(shù)調(diào)用處停止send
函數(shù)調(diào)用處停止提示:要編輯 URL 過濾器,雙擊 XHR Breakpoints 邊欄的 XBR 斷點,具有空的 URL 過濾器的 XHR 斷點會匹配任何 XHR。
mouseout
事件處理器處停止提示:下列事件是支持的
Keyboard:松開按鍵,按下按鍵,輸入文字
Mouse:點擊,雙擊,鼠標鍵按下,鼠標鍵松開,鼠標懸浮,鼠標移動,鼠標從元素上離開。
Control:重新設置大小,滾動,縮放,焦點,失焦,選擇,變化,重置 Clipboard:復制,剪切,粘貼,beforecopy,beforecut,beforepaste Load:加載,卸載,廢除,出錯。 DOM Mutation:DOMActivate,DOMFocusin,DOMAttrModified,DOMCharacterDataModified,DOMNodeInserted,DOMNodeInsertedIntoDocument,DOMNodeRemoved,DOMNodeRemovedFromDocument,DOMSubtreeModified,DOMContentLoaded Device:面向設備,設備運動。
當暫停的時候,點擊并且不放開恢復按鈕可以讓 ”所有的暫停都阻塞 500 毫秒后恢復“。這會讓所有的斷點在半秒內(nèi)都無法使用,可以使用該方法進入到下一個循環(huán)中,這樣就可以避免為了退出循環(huán)而不斷讓斷點繼續(xù)執(zhí)行。
專業(yè)建議:當使用 DevTools 啟動“刷新”的時候(焦點在 DevTools 的時候使用 Ctrl + R),全部暫停都會被禁用,直到新的頁面開始加載(或者作為備用方案,直到用戶按下 “Pause” 按鈕)。然而,如果你從瀏覽器的按鈕來啟動刷新操作的時候(或者當焦點在 DevTools 之外的時候使用 Ctrl + R),將會命中所有剩余的斷點。這實際上可對那些對頁面卸載過程感興趣的人非常有用。
在創(chuàng)作和工作流章節(jié)中,我們討論了怎么通過 Source 面板來對腳本進行修改。在斷點處,同樣也可以通過點擊主編輯面板來做出修改,并且能夠?qū)崟r修改腳本文件。
這允許你在不退出瀏覽器的情況下通過使用 DevTools 來保存修改的內(nèi)容。
讓我們現(xiàn)在來看一下怎么處理異常以及如何利用 Chrome 的 DevTools 使用堆棧追蹤。異常處理是對于出現(xiàn)的異常的響應 - 除了有些需要特定處理過程的情況 - 并且一般會改變 JavaScript 代碼執(zhí)行的正常流程。
注意:如果是 Web 開發(fā)者并且希望獲得最新版的 DevTools,你需要使用 Chrome Canary
當程序出現(xiàn)異常的時候,你可以打開 DevTools 控制臺(Ctrl + Shift + J/Cmd + Option + J),然后你會發(fā)現(xiàn)有許多 JavaScript 出錯信息。每條信息都指出了相應的文件名以及行號,你可以通過這些信息來定位到源代碼中的相關位置。
導致出錯的執(zhí)行路徑可能會有多條,并且究竟是哪一條出現(xiàn)了錯誤并不明顯。只要 DevTools 窗口是打開的,控制臺中出現(xiàn)的異常狀況都會伴隨著完整的 JavaScript 調(diào)用堆棧而出現(xiàn)。你可以展開這些控制臺信息來查看堆棧信息并定位到代碼中的相應位置:
你可能希望下一次 JavaScript 發(fā)生異常的時候能夠暫停 JavaScript 的執(zhí)行并查看它的調(diào)用堆棧、范圍變量以及應用程序的狀態(tài)。Script 面板底部的暫停按鈕()允許你在不同的異常處模式之間切換,且該按鈕具有三種狀態(tài):你可以選擇在所有的異常發(fā)生時都暫停程序運行或者只是在未捕獲的異常發(fā)生時暫停程序運行或者是忽視所有的異常。
在 DevTools 中輸出的日志信息對于理解應用程序的執(zhí)行過程非常有幫助,你可以在日志信息中包括相關聯(lián)的堆棧跟蹤信息來使它更加有用。想要做到這一點有多種方式。
每個 Error 對象都有一個名為 stack 的字符串屬性,該字符串包含了堆棧跟蹤信息:
你可以使用 concole.trace()
方法來輸出當前 JavaScript 調(diào)用堆棧,這種方法可以用于檢測代碼:
將 assertion 加入到你的代碼中也是一種不錯的方法。只要調(diào)用 console.assert()
方法并將錯誤情況作為第一個參數(shù)即可,每當表達式的計算結果為 false 時你就會看到相應的控制臺記錄:
Chrome 支持將一個處理函數(shù)設置為 window.onerror。每當一個 JavaScript 異常在窗口上下文中拋出并且沒有被任何的 try/catch 塊捕獲的時候,該方法就會被調(diào)用。同時,異常信息、拋出異常的文件 URL 以及出現(xiàn)異常的位置在文件中的行號會按照上面的順序作為三個參數(shù)傳給該方法。你可能覺得像這樣設置一個能夠收集未捕獲異常信息并且能將其報告給服務器的錯誤處理器非常方便。
如果你在閱讀以及調(diào)試某些過于簡化的 JavaScript 代碼有麻煩的時候,有一個美化輸出格式的選項可以讓這些過程更輕松。下面是一份簡化過頭的腳本文件在 DevTools 中可能顯示出的樣子:
如果點擊左邊底部的花括號 圖標,該 JavaScript 就會轉(zhuǎn)換為更具可讀性的格式。這種格式對調(diào)試和設置斷點也相當方便。
你是否期望過你的客戶端代碼能夠保持可讀性并且適合調(diào)試,甚至是你在合并以及縮小代碼之后也能這樣嗎?那么,現(xiàn)在你可以感受源映射的魔力了。
一個基于 JSON 格式的源映射創(chuàng)建了一種縮小后的代碼和源代碼之間的關系。
下面一種簡單的源映射的示例:
{
version : 3,
file: "out.min.js",
sourceRoot : "",
sources: ["foo.js", "bar.js"],
names: ["src", "maps", "are", "fun"],
mappings: "AAgBC,SAAQ,CAAEA"
}
源映射是指,當你為了構建產(chǎn)品而縮小及合并 JavaScript 文件的時候,產(chǎn)生擁有源文件信息的一種映射。源映射會讓 DevTools 去加載你的源文件,而不是縮小后的文件。于是你可以使用源文件來設置斷點以及調(diào)試代碼。同時,Chrome 實際運行的是縮小后的代碼。這就讓你感覺像是在運行源文件一般。
你需要使用能夠創(chuàng)建源映射的縮小器來縮小你的代碼。Closure 編譯器以及 UglifyJS 2.0 就是兩款這樣的工具,當然,也有其他的很多支持 CoffeeScript, SASS 等源映射的工具。具體可以參考維基百科的頁面 Source maps: languages, tools and other info。
默認情況下,資源映射(Sourcemap)是啟用的(Chrome 39 就是這樣),如果你想仔細檢查或者單獨啟用它,先打開 DevTools 然后點擊設置圖標 。在 Sources 選項下,查看 Enable javaScript source maps。你也可以檢查 Enable CSS source maps,不過在這個例子中你并不需要這么做。
如果要讓 DevTools 知道某個源映射是可用的,請驗證縮小后的文件最后一行的代碼是不是下面這樣。
//# sourceMappingURL=/path/to/file.js.map
這一行通常是由生成映射的工具添加的,并且能夠讓 DevTools 建立縮小后的文件和源文件之間的聯(lián)系。在 CSS 中,這一行可能是這樣的: /# sourceMappingURL=style.css.map /.
如果你不希望文件中有額外的注釋,你可以使用 JavaScript 文件中的 HTTP 頭來告訴 DevTools 源文件在哪里。這需要設置或者自定義 web 服務器,并且該內(nèi)容超出了本篇教程的目標。
X-SourceMap: /path/to/file.js.map
和注釋類似,該代碼同樣告訴 DevTools 到哪里去尋找源文件并和相應 JavaScript 文件建立關聯(lián)。這個頭部信息也用于解決引用源映射的語言并不支持單行注釋的問題。
你也應該檢查你的 web 服務器是否設置好了對資源映射的支持。有些服務器,需要對每種文件都做出明確的配置,比如 Google App Engine。在這種情況下,你的源映射應該設置將 MIME 類型設置為 application/json
,不過 Chrome 瀏覽器會接受任何類型的類容聲明,比如 application/octet-stream
。
請看一下 Chrome 中特別構建的 font dragr tool,當源映射啟用的時候,你將會注意到 JavaScript 文件并沒有被編譯,并且你可以看到所有被引用的 JavaScript 文件。這使用了源映射,但是后臺實際運行的是編譯后的代碼。任何的錯誤、日志以及斷點都會映射到開發(fā)代碼中,這使得調(diào)試變得更為容易。實際上你的感覺就像是你在運行開發(fā)中的代碼一樣。
源映射聲明的下列部分,并不會令你在使用 evals 函數(shù)來開發(fā)時有多輕松。
這個幫助器(@sourceURL)看起來類似于 //# sourceMappingURL 屬性,并且實際上是在源映射 V3 規(guī)范中提及的。在你的代碼中包含下面這些特殊的注釋,你可以為 eval 函數(shù)及內(nèi)嵌的腳本和樣式命名,這樣他們在你的開發(fā)工具中顯示的時候就可以擁有邏輯名稱。
//# sourceURL=source.coffee
更多建議: