天天看點

chrome調試 JavaScript 腳本

随着 javascript 應用的複雜性逐漸提高,開發者需要有力的調試工具來幫助他們快速發現問題的原因,并且能高效地修複它。chrome devtools 提供了一系列實用的工具使得調試 javascript 應用不再是一件痛苦的事。

在這個部分,我們會通過調試 ​​google closure hovercard demo​​ 以及其他的動态示例來讓你了解怎麼去使用這些工具。

注意:如果你是 web 開發者并且希望獲得最新版的 devtools,你應該使用 ​​chrome canary​​

源面闆允許你調試 javascript 代碼。它提供了 ​​v8​​ 調試器的圖形化接口。請通過以下步驟來使用源面闆:

打開一個站點,比如 ​​google closure hovercard demo page​​ 或者 ​​todomvc​​ 的應用程式。

打開 devtools 視窗。

如果沒有選中 sources,則手動選中。

chrome調試 JavaScript 腳本

源面闆允許你檢視正在浏覽的頁面上所有的腳本。面闆底部的圖示按鈕分别提供了标準的暫停、恢複以及逐條語句運作等操作。視窗底部還有一個按鈕,在出現異常時可以強制暫停。在不同頁籤中,sources 都是可見的,而且隻要點選 

chrome調試 JavaScript 腳本

 就可以打開檔案定位并且顯示全部腳本。

執行控制相關的按鈕就在側面闆的頂端,它們使得你能夠單步執行代碼。可用的按鈕有:

chrome調試 JavaScript 腳本

 continue:繼續執行代碼,直至遇到另一個斷點。

chrome調試 JavaScript 腳本

 step over(逐語句):逐行執行,以了解每一行如何操作目前的變量。當你的代碼調用另一個函數的時候,調試器不會跳到那個函數的代碼中去,其焦點還是目前的函數,而 step into 則相反。

chrome調試 JavaScript 腳本

 step into(逐過程):和逐語句類似,但是點選逐過程會在函數調用時,令調試器将執行轉到所調用的函數聲明中去。

chrome調試 JavaScript 腳本

 step out:當使用逐過程進入某個函數内部後,點選該按鈕會跳過該函數聲明的剩餘部分,調試器會将執行過程移動到其父函數中。

chrome調試 JavaScript 腳本

 toggle breakpoints:切換斷點啟用、禁用狀态,同時保證各自的啟用狀态不會受到影響。

在源面闆中,有許多相關的快捷鍵可用:

continue:在mac上使用 ​<code>​f8​</code>​ 或者 ​<code>​command​</code>​ + ​<code>​\​</code>​,其他平台上為 ​<code>​ctrl​</code>​+ ​<code>​\​</code>​。

step over:在mac上為 ​<code>​f10​</code>​ 或者 ​<code>​command​</code>​ + ​<code>​'​</code>​,在其他平台上為 ​<code>​ctrl​</code>​ + ​<code>​'​</code>​。

step into:在mac上為 ​<code>​f11​</code>​ 或者 ​<code>​command​</code>​ + ​<code>​;​</code>​,在其他平台上為 ​<code>​ctrl​</code>​ + ​<code>​;​</code>​。

step out:在mac上為 ​<code>​shift​</code>​ + ​<code>​f11​</code>​ 或者 ​<code>​shift​</code>​ + ​<code>​command​</code>​ + ​<code>​;​</code>​,在其他平台上為 ​<code>​shift​</code>​+ ​<code>​ctrl​</code>​ + ​<code>​;​</code>​。

next call frame:​<code>​ctrl​</code>​ + ​<code>​.​</code>​。(适用于全平台)

previous call frame: ​<code>​ctrl​</code>​ + ​<code>​,​</code>​。(适用于全平台)

如果想要檢視其他支援的快捷鍵,請參考 ​​shortcuts​​。

斷點是在腳本中處于某種目的而停止或者暫停代碼運作的地方。在 devtools 中使用斷點可以調試 javascript 代碼, dom 更新以及網絡調用。

在源面闆中,打開一份 javascript 檔案用于調試。在下面的例子中,我們調試了來自 ​​angularjs version of todomvc​​ 中的 todoctrl.js 檔案。

chrome調試 JavaScript 腳本

點選行号前的空格來在那一行設定斷點。之後一個藍色的标記将會出現,這說明斷點已經被設定好了:

chrome調試 JavaScript 腳本

你可以添加多個斷點。點選其他行行号前的空格就可以繼續設定斷點,你所設定的全部斷點都會在右邊的側欄下 breakpoints 選項中顯示出來。

斷點前的複選框可以選擇是否啟用斷點,如果斷點被禁用了,那麼藍色的标簽會變色。

點選斷點的入口可以跳轉到源檔案中的對應行:

chrome調試 JavaScript 腳本

點選藍色的标簽可以删除斷點。

右擊藍色标簽會打開一個菜單,其中包括:continue to here,remove breakpoint,edit breakpoint 以及 disable breakpoint。

chrome調試 JavaScript 腳本

想要設定條件斷點,選擇 edit breakpoint ,或者,右鍵點選行号前的空白然後選擇 add conditional breakpoint。在輸入域中,可以輸入任何能夠傳回 true 或者 false 的表達式。當條件傳回 true 的時候,斷點會中斷代碼的執行。

chrome調試 JavaScript 腳本

在你想要分析循環或者經常觸發的回調事件的代碼時,條件斷點是非常有用的。

注意:有時候你可能不需要從 devtools 接口來設定斷點。此時你希望從代碼中來啟動調試器,那麼你可以使用 debugger 關鍵字來實作這一操作。

當你設定了一個或多個斷點的時候,傳回到浏覽器視窗并且與頁面進行互動。在下面的例子中,我們在 removetodo() 方法中加入了斷點。現在任何想要在 todomvc 應用中删除 todo 選項的行為都将觸發斷點:

chrome調試 JavaScript 腳本

要恢複代碼的運作,在 devtools 視窗中點選 continue 

chrome調試 JavaScript 腳本

 按鈕或者使用 ​<code>​f8​</code>​ 鍵盤快捷鍵。

當腳本暫停運作的時候,你可以使用右邊側欄中的 watch expressinos, call stack 以及 scope variables 面闆。

調用棧面闆展示了代碼到暫停處的完整執行路徑,這讓我們能夠深入代碼去找出導緻錯誤的原因。

chrome調試 JavaScript 腳本

如果要檢視包括計時器和 xhr 事件在内的異步 javascript 回調函數的執行路徑,請點選 async 複選框。

chrome調試 JavaScript 腳本

更多關于異步調用棧的資訊和示例請參考 html5rocks.com 網頁上的 ​​debuggin asynchtonous javascript with chrome devtools​​

當你把一個 javascript 源檔案放到黑盒中時,你在調試代碼的時候無法跳轉到那個檔案中了。你可以在你感興趣的代碼嘗試一下。

chrome調試 JavaScript 腳本

你可以使用設定面闆來将腳本檔案放入黑盒,或者右鍵點選 sources 面闆中的檔案然後選擇 blackbox script。

chrome調試 JavaScript 腳本

更多關于黑盒的資訊請參考 ​​blackboxing javascript file​​

devtools 中的 consle drawer 允許你在調試器目前暫停的位置附近進行試驗。點選 esc 鍵在視圖中打開控制台,再次按 esc 鍵就會關閉該控制台。

chrome調試 JavaScript 腳本

load dynamic script

在 sources 面闆中腳本的下拉選項中找到 "dynamicscript.js" 然後在第二行設定斷點。

call function from dynamic script

此時程式應該在斷點處暫停

在 devtools 視窗中點選 continue 

chrome調試 JavaScript 腳本

 或者按 ​<code>​f8​</code>​ 來繼續執行

chrome調試 JavaScript 腳本
提示:注意 dynamicscript.js 檔案結尾處的 "//# sourceurl=dynamicscript.js" 這一行。這種方式可以給由 eval 函數建立的腳本命名,更多的資訊會在 ​​source maps​​ 這一節中說明。隻有當使用者為動态的 javascript 檔案提供了名稱時才能為其設定斷點。

點選 pause 

chrome調試 JavaScript 腳本

 按鈕

将你的滑鼠移動到下圖中的區域

你的滑鼠應該停在 onmouseover 函數上

點選 continue 

chrome調試 JavaScript 腳本

 按鈕或者按 f8** 來繼續執行

chrome調試 JavaScript 腳本

點選視窗底部的 pause on exceptions 

chrome調試 JavaScript 腳本

 按鈕來切換到在異常處暫停模式

勾選 pause on caught exceptinos 複選框

raise exception!

程式應該在 raiseandcatchexception 函數中停止

chrome調試 JavaScript 腳本

 按鈕或者按 f8 來繼續執行

chrome調試 JavaScript 腳本

點選 pause on exceptions 

chrome調試 JavaScript 腳本

取消勾選 pause on caught exceptions 複選框

此時若捕獲了異常,程式應該不會在 raiseandcatchexcep 函數處停止

raise uncaught exception!

此時應該在 raiseexception 函數處停止

chrome調試 JavaScript 腳本
chrome調試 JavaScript 腳本

右鍵點選下面的 "parent element" 并且從文本菜單中選擇 inspect element(審查元素)

parent element

右鍵點選 elements 面闆元素然後選擇 break on subtree modifications

append child!

此時應該會在 ​<code>​appendchild​</code>​ 函數調用處停止

chrome調試 JavaScript 腳本
chrome調試 JavaScript 腳本

點選 sources面闆右側的 xhr breakpoints 邊欄上的 add 

chrome調試 JavaScript 腳本

在文本輸入去輸入 "data.txt" 然後單擊回車

retrieve data.txt by xhr

此時應該在​<code>​send​</code>​ 函數調用處停止

右鍵點選新建立的斷點然後選擇 remove breakpoint

點選devtools 視窗中的 continue 

chrome調試 JavaScript 腳本
chrome調試 JavaScript 腳本

提示:要編輯 url 過濾器,輕按兩下 xhr breakpoints 邊欄的 xbr 斷點,具有空的 url 過濾器的 xhr 斷點會比對任何 xhr。

打開右邊 scripts 面闆的 event listener breakpoints 邊欄

展開 mouse 選項

選中 mouseout 前的複選框可以設定 mouseout 事件監聽器斷點

chrome調試 JavaScript 腳本

将你的滑鼠移動到下面的的盒子中

hover me!

此時應該在 ​<code>​mouseout​</code>​ 事件處理器處停止

chrome調試 JavaScript 腳本
chrome調試 JavaScript 腳本
提示:下列事件是支援的  keyboard:松開按鍵,按下按鍵,輸入文字  mouse:點選,輕按兩下,滑鼠鍵按下,滑鼠鍵松開,滑鼠懸浮,滑鼠移動,滑鼠從元素上離開。  control:重新設定大小,滾動,縮放,焦點,失焦,選擇,變化,重置  clipboard:複制,剪切,粘貼,beforecopy,beforecut,beforepaste  load:加載,解除安裝,廢除,出錯。  dom mutation:domactivate,domfocusin,domattrmodified,domcharacterdatamodified,domnodeinserted,domnodeinsertedintodocument,domnoderemoved,domnoderemovedfromdocument,domsubtreemodified,domcontentloaded  device:面向裝置,裝置運動。

當暫停的時候,點選并且不放開恢複按鈕可以讓 ”所有的暫停都阻塞 500 毫秒後恢複“。這會讓所有的斷點在半秒内都無法使用,可以使用該方法進入到下一個循環中,這樣就可以避免為了退出循環而不斷讓斷點繼續執行。

專業建議:當使用 devtools 啟動“重新整理”的時候(焦點在 devtools 的時候使用 ctrl + r),全部暫停都會被禁用,直到新的頁面開始加載(或者作為備用方案,直到使用者按下 “pause” 按鈕)。然而,如果你從浏覽器的按鈕來啟動重新整理操作的時候(或者當焦點在 devtools 之外的時候使用 ctrl + r),将會命中所有剩餘的斷點。這實際上可對那些對頁面解除安裝過程感興趣的人非常有用。

chrome調試 JavaScript 腳本

在創作和工作流章節中,我們讨論了怎麼通過 source 面闆來對腳本進行修改。在斷點處,同樣也可以通過點選主編輯面闆來做出修改,并且能夠實時修改腳本檔案。

定位到 google closure hovercard demo

在源面闆中,打開 “mouse.js” 然後使用 ctrl/cmd + shift + o 來定位到 onmouseout() 函數

chrome調試 JavaScript 腳本

點選暫停按鈕來暫停調試

修改函數,在末尾加入 console.log('moused out')

使用 cmd + s 或者 ctrl + s 快捷鍵可以儲存更改,記得确認是否儲存

點選 pause/resume 按鈕來恢複執行

當你的滑鼠離開相關位置的時候,控制台會輸出資訊

chrome調試 JavaScript 腳本

這允許你在不退出浏覽器的情況下通過使用 devtools 來儲存修改的内容。

讓我們現在來看一下怎麼處理異常以及如何利用 chrome 的 devtools 使用堆棧追蹤。 異常處理是對于出現的異常的響應 - 除了有些需要特定處理過程的情況 - 并且一般會改變 javascript 代碼執行的正常流程。

注意:如果是 web 開發者并且希望獲得最新版的 devtools,你需要使用 ​​chrome canary​​

當程式出現異常的時候,你可以打開 devtools 控制台(ctrl + shift + j/cmd + option + j),然後你會發現有許多 javascript 出錯資訊。每條資訊都指出了相應的檔案名以及行号,你可以通過這些資訊來定位到源代碼中的相關位置。

chrome調試 JavaScript 腳本

導緻出錯的執行路徑可能會有多條,并且究竟是哪一條出現了錯誤并不明顯。隻要 devtools 視窗是打開的,控制台中出現的異常狀況都會伴随着完整的 javascript 調用堆棧而出現。你可以展開這些控制台資訊來檢視堆棧資訊并定位到代碼中的相應位置:

chrome調試 JavaScript 腳本

你可能希望下一次 javascript 發生異常的時候能夠暫停 javascript 的執行并檢視它的調用堆棧、範圍變量以及應用程式的狀态。script 面闆底部的暫停按鈕(

chrome調試 JavaScript 腳本

)允許你在不同的異常處模式之間切換,且該按鈕具有三種狀态:你可以選擇在所有的異常發生時都暫停程式運作或者隻是在未捕獲的異常發生時暫停程式運作或者是忽視所有的異常。

chrome調試 JavaScript 腳本

在 devtools 中輸出的日志資訊對于了解應用程式的執行過程非常有幫助,你可以在日志資訊中包括相關聯的堆棧跟蹤資訊來使它更加有用。想要做到這一點有多種方式。

每個 error 對象都有一個名為 stack 的字元串屬性,該字元串包含了堆棧跟蹤資訊:

chrome調試 JavaScript 腳本

你可以使用 ​<code>​concole.trace()​</code>​ 方法來輸出目前 javascript 調用堆棧,這種方法可以用于檢測代碼:

chrome調試 JavaScript 腳本

将 assertion 加入到你的代碼中也是一種不錯的方法。隻要調用 ​<code>​console.assert()​</code>​ 方法并将錯誤情況作為第一個參數即可,每當表達式的計算結果為 false 時你就會看到相應的控制台記錄:

chrome調試 JavaScript 腳本

chrome 支援将一個處理函數設定為 window.onerror。每當一個 javascript 異常在視窗上下文中抛出并且沒有被任何的 try/catch 塊捕獲的時候,該方法就會被調用。同時,異常資訊、抛出異常的檔案 url 以及出現異常的位置在檔案中的行号會按照上面的順序作為三個參數傳給該方法。你可能覺得像這樣設定一個能夠收集未捕獲異常資訊并且能将其報告給伺服器的錯誤處理器非常友善。

chrome調試 JavaScript 腳本

如果你在閱讀以及調試某些過于簡化的 javascript 代碼有麻煩的時候,有一個美化輸出格式的選項可以讓這些過程更輕松。下面是一份簡化過頭的腳本檔案在 devtools 中可能顯示出的樣子:

chrome調試 JavaScript 腳本

如果點選左邊底部的花括号 

chrome調試 JavaScript 腳本

 圖示,該 javascript 就會轉換為更具可讀性的格式。這種格式對調試和設定斷點也相當友善。

chrome調試 JavaScript 腳本

你是否期望過你的用戶端代碼能夠保持可讀性并且适合調試,甚至是你在合并以及縮小代碼之後也能這樣嗎?那麼,現在你可以感受源映射的魔力了。

一個基于 json 格式的源映射建立了一種縮小後的代碼和源代碼之間的關系。

下面一種簡單的源映射的示例:

源映射是指,當你為了建構産品而縮小及合并 javascript 檔案的時候,産生擁有源檔案資訊的一種映射。源映射會讓 devtools 去加載你的源檔案,而不是縮小後的檔案。于是你可以使用源檔案來設定斷點以及調試代碼。同時,chrome 實際運作的是縮小後的代碼。這就讓你感覺像是在運作源檔案一般。

你需要使用能夠建立源映射的縮小器來縮小你的代碼。closure 編譯器以及 uglifyjs 2.0 就是兩款這樣的工具,當然,也有其他的很多支援 coffeescript, sass 等源映射的工具。具體可以參考維基百科的頁面 ​​source maps: languages, tools and other info​​。

預設情況下,資源映射(sourcemap)是啟用的(chrome 39 就是這樣),如果你想仔細檢查或者單獨啟用它,先打開 devtools 然後點選設定圖示 

chrome調試 JavaScript 腳本

。在 sources 選項下,檢視 enable javascript source maps。你也可以檢查 enable css source maps,不過在這個例子中你并不需要這麼做。

chrome調試 JavaScript 腳本

如果要讓 devtools 知道某個源映射是可用的,請驗證縮小後的檔案最後一行的代碼是不是下面這樣。

這一行通常是由生成映射的工具添加的,并且能夠讓 devtools 建立縮小後的檔案和源檔案之間的聯系。在 css 中,這一行可能是這樣的:​<code>​ /# sourcemappingurl=style.css.map /.​</code>​

如果你不希望檔案中有額外的注釋,你可以使用 javascript 檔案中的 http 頭來告訴 devtools 源檔案在哪裡。這需要設定或者自定義 web 伺服器,并且該内容超出了本篇教程的目标。

和注釋類似,該代碼同樣告訴 devtools 到哪裡去尋找源檔案并和相應 javascript 檔案建立關聯。這個頭部資訊也用于解決引用源映射的語言并不支援單行注釋的問題。

你也應該檢查你的 web 伺服器是否設定好了對資源映射的支援。有些伺服器,需要對每種檔案都做出明确的配置,比如 google app engine。在這種情況下,你的源映射應該設定将 mime 類型設定為 ​<code>​application/json​</code>​,不過 chrome 浏覽器會​​接受任何類型的類容聲明​​,比如 ​<code>​application/octet-stream​</code>​。

請看一下 chrome 中特别建構的 ​​font dragr tool​​,當源映射啟用的時候,你将會注意到 javascript 檔案并沒有被編譯,并且你可以看到所有被引用的 javascript 檔案。這使用了源映射,但是背景實際運作的是編譯後的代碼。任何的錯誤、日志以及斷點都會映射到開發代碼中,這使得調試變得更為容易。實際上你的感覺就像是你在運作開發中的代碼一樣。

源映射聲明的下列部分,并不會令你在使用 evals 函數來開發時有多輕松。

這個幫助器(@sourceurl)看起來類似于 //# sourcemappingurl 屬性,并且實際上是在源映射 v3 規範中提及的。在你的代碼中包含下面這些特殊的注釋,你可以為 eval 函數及内嵌的腳本和樣式命名,這樣他們在你的開發工具中顯示的時候就可以擁有邏輯名稱。

定位到 ​​demo​​

打開 devtools 并找到 sources 面闆

輸入一個名稱來為你的代碼命名

點選 compile 按鈕

coffeescript 源檔案會計算總值并且通過警告來輸出

如果你打開 sources 的子面闆,你将會看到一個擁有你之前輸入的檔案名的新檔案。如果你輕按兩下該檔案來檢視詳細内容,會發現該檔案中含有初始源檔案編譯後的 javascript。在最後一行會有 // @sourceurl 注釋,該注釋表明了源檔案是什麼。這在通過語言抽象來調試時具有很大的幫助。

chrome調試 JavaScript 腳本

繼續閱讀