譯者按: 不少時候,你們可能只是依靠console.log來調試JavaScript代碼,這樣作的侷限性不言而喻,這篇博客將教你幾招實用的調試技巧。javascript
爲了保證可讀性,本文采用意譯而非直譯。另外,本文版權歸原做者全部,翻譯僅用於學習。css
掌握工具的使用方法能夠極大提升解決問題的效率。儘管JavaScript以難以Debug著稱,若是你知道一些技巧可讓你更快地搞定它。本文我總結了14個Debug小技巧,也許會對你有用!java
大多數技巧都是針對Chrome檢查器(Inspector)和Firefox,儘管有不少人使用其餘檢查器。node
debugger;
除了console.log
以外,debugger;
是我最喜歡的快速debug的工具。一旦在代碼中加入了這行語句,Chrome在執行的時候會自動在該行停下來。你甚至能夠和條件語句配合使用,僅僅在你須要它的時候開啓。chrome
if(thisThing){
debugger;
}
|
有時候,你須要查看一個複雜的對象元素。一般,咱們都會使用console.log
將其打印出來而後查看。其實,你還可使用console.table
,讓對象更加美觀地呈現出來。瀏覽器
var animals = [
{
animal: 'Horse', name: 'Henry', age: 43 },
{
animal: 'Dog', name: 'Fred', age: 13 },
{
animal: 'Cat', name: 'Frodo', age: 18 }
];
console.table(animals);
|
輸出樣式:cookie
若是你擁有各類型號的手機那麼測試會相對簡單,可是現實可不會這樣。其實,你能夠直接在瀏覽器大家改變viewport的大小來查看效果。谷歌瀏覽器提供了很是強大的功能。在谷歌開發者面板,點擊toogle device mode
按鈕,就能夠選擇不一樣的設備大小了。網絡
構造一個DOM元素,而後在控制檯(Console)下面使用。谷歌瀏覽器調試器(Chrome Inspector)保留了最後5個DOM元素的歷史。最後一個標記爲$0,倒數第二個$1, 以此類推。框架
若是你按照item-4
,item-3
,item-2
,item-1
,item-0
的順序點擊這些元素,那麼你能夠在控制檯下使用$x
來訪問它們。dom
瞭解代碼的執行時間是很是有用的,特別是調試耗時的for循環。你能夠經過定義不一樣的名字來設置多個timer。咱們來演示一下如何操做:
console.time('Timer1');
var items = [];
for(var i = 0; i < 100000; i++){
items.push({
index: i});
}
console.timeEnd('Timer1');
|
你也許知道很多JavaScript框架,它們能夠一鍵快速生成大量代碼。代碼裏面包含各類view和事件觸發器,最終你會想要搞明白某些函數是如何被調用的。
由於JavaScript並非一個很結構化的語言,全部有時候要搞清楚什麼時候如何發生的仍是比較困難的。在這個時候,咱們可使用console.trace
來debug JavaScript。
好比,若是你想看到一個Car實例下,funcZ
的整個堆棧詳情:
var car;
var func1 = function() {
func2();
}
var func2 = function() {
func4();
}
var func3 = function() {
}
var func4 = function() {
car =
new Car();
car.funcX();
}
var Car = function() {
this.brand = ‘volvo’;
this.color = ‘red’;
this.funcX = function() {
this.funcY();
}
this.funcY = function() {
this.funcZ();
}
this.funcZ = function() {
console.trace(‘trace car’)
}
}
func1();
var car;
var func1 = function() {
func2();
}
var func2 = function() {
func4();
}
var func3 = function() {
}
var func4 = function() {
car =
new Car();
car.funcX();
}
var Car = function() {
this.brand = ‘volvo’;
this.color = ‘red’;
this.funcX = function() {
this.funcY();
}
this.funcY = function() {
this.funcZ();
}
this.funcZ = function() {
console.trace(‘trace car’)
}
}
func1();
|
使用console.trace
,輸出結果以下:
咱們能夠清晰地看到func1調用func2,func2調用func4,func4
建立了一個Car
的實例,而後調用了car.funcX,等等。
有時候,儘管你認爲對本身的代碼很是清楚,使用console.trace
依然能夠幫你快速定位函數。好比,你想要改進代碼,那麼經過trace能夠獲取到全部相關的函數,並且每個均可以點擊直接跳轉,就像一個快捷菜單同樣。
廣告: 若是你須要監控線上JavaScript代碼的錯誤的話,歡迎無償使用Fundebug!
有時候,生產環境的代碼出現問題,然而source map並無和壓縮的代碼綁定在一塊兒,全部沒法看到還原的代碼。不用擔憂,谷歌瀏覽器能夠將JavaScript代碼還原到一個可讀的樣式。儘管仍是比不上真實的代碼,可是能夠很好的幫助你去分析問題了。點擊{}
來結構化代碼:
設想咱們想要在函數中設置一個斷點,最多見的兩種方式是:
不管哪一種方法,你都須要在全部的代碼文件中首先找到須要debug的那一行。
還有一個不經常使用的方式是使用控制檯(console),使用debug(funcName)
,腳本會在那行函數處暫停。使用這個方法能夠很快定位函數,可是對於私有和匿名函數不適用。(注意:debug和console.debug不是同一個事情!)
var func1 = function() {
func2();
};
var Car = function() {
this.funcX = function() {
this.funcY();
}
this.funcY = function() {
this.funcZ();
}
}
var car = new Car();
|
在控制檯輸入debug(car.funcY)
,腳本會在函數調用car.funcY
處進入debug模式。
咱們的代碼中都會引入很多庫函數和框架。大多數都是通過測試,幾乎沒有什麼bug的。可是debugger會一不當心跳進去。所以,咱們能夠選擇將這些腳本屏蔽。能夠查看谷歌瀏覽器屏蔽文件的設置和火狐瀏覽器屏蔽文件的設置。
在一些很複雜的Debug中,咱們須要輸出不少行的日誌,使用Console.log
,console.debug
,console.warn
,console.info
和console.error
。你可使用過濾器來查看特定的消息,可是有時候你會發現這樣並不夠。咱們可使用更加富有創造力的方法,使用CSS來個性化定義Console.log打印的消息:
console.todo = function(msg) {
console.log(‘ % c % s % s % s‘, ‘color: yellow; background - color: black;’, ‘–‘, msg, ‘–‘);
}
console.important = function(msg) {
console.log(‘ % c % s % s % s’, ‘color: brown; font - weight: bold; text - decoration: underline;’, ‘–‘, msg, ‘–‘);
}
console.todo(「This is something that’ s need to be fixed」);
console.important(‘This is an important message’);
|
輸出的結果以下:
你能夠用%s來輸出字符串,%i來輸出數字,%c來自定義格式。若是你使用單頁面框架,對於視圖(view)的console消息使用一種格式,模型(model)、集合,控制器各自使用不一樣的格式。甚至,你可能想要更短的名字,相似於wlog, clog和mlog。
在谷歌瀏覽器控制檯,你能夠一直觀察某個函數。每次它被調用,都會打印傳入的參數值。
var func1 = function(x, y, z) {
//....
};
|
使用monitor
函數能夠獲取到函數運行時傳入的參數值。可是,有一個不足在於並無指明該函數的形參個數。因此func1
其實是須要三個參數的,可是隻傳入了兩個。若是忽略了這種狀況,那麼可能會致使bug出現。
在控制檯使用查詢選擇器(querySelector)很方便, 使用$('css-selector')
就能夠返回第一個匹配的元素,$$('css-selector')
會返回全部匹配的元素。若是你會屢次使用某個元素,甚至能夠將其保存到變量中。
不少開發者使用Postman來發送Ajax請求。Postman很是好用,可是打開一個新的窗口,而且配置請求對象仍是有點繁瑣。
若是你不須要擔憂使用cookie認證,那麼你能夠在Firefox中編輯和重發請求。
打開檢查器,跳轉到網絡(network)標籤。右鍵點擊選中的請求,選擇編輯和重發選項。
下圖是我將同一個GET請求的屬性編輯後再次發送出去的狀況:
有時候DOM莫名其妙變化了,然而你並不知道爲啥。好在谷歌瀏覽器提供了一個功能能夠在DOM元素變化的時候暫停執行。在谷歌檢查器下,右鍵選中的元素,而後選定要監控的變化類型:Subtree Modifications, Attributes Modifications, Node Removal。