友情提示:文中涉及較多Gif演示動畫,移動端請盡量在Wifi環(huán)境中閱讀 前言:調(diào)試技巧,,在任何一項技術(shù)研發(fā)中都可謂是必不可少的技能。掌握各種調(diào)試技巧,必定能在工作中起到事半功倍的效果,。譬如,,快速定位問題、降低故障概率,、幫助分析邏輯錯誤等等,。而在互聯(lián)網(wǎng)前端開發(fā)越來越重要的今天,如何在前端開發(fā)中降低開發(fā)成本,,提升工作效率,,掌握前端開發(fā)調(diào)試技巧尤為重要。 本文將一一講解各種前端JS調(diào)試技巧,,也許你已經(jīng)熟練掌握,,那讓我們一起來溫習(xí),,也許有你沒見過的方法,不妨一起來學(xué)習(xí),,也許你尚不知如何調(diào)試,,趕緊趁此機會填補空白。 骨灰級調(diào)試大師Alert 那還是互聯(lián)網(wǎng)剛剛起步的時代,,網(wǎng)頁前端還主要以內(nèi)容展示為主,,瀏覽器腳本還只能為頁面提供非常簡單的輔助功能的時候。那個時候,,網(wǎng)頁主要運行在以IE6為主的瀏覽器中,,JS的調(diào)試功能還非常弱,只能通過內(nèi)置于Window對象中的alert方法來調(diào)試,,那時候看起來應(yīng)該是這個樣子: 需要說明一點,,這里看到的效果,并非當年的IE瀏覽器中看到的效果,,而是在高版本IE中的效果,。此外,當年貌似還沒有這么高級的控制臺,,而alert的使用也是在真實的頁面JS代碼中,。雖然,alert的調(diào)試方式很原始,,但當時確實有它不可磨滅的價值,,甚至到今天,已然有其用武之地,。 新一代調(diào)試王者Console 隨著JS在Web前端中能做的事情越來越多,,責任越來越大,而地位也越來越重要,。傳統(tǒng)的alert調(diào)試方式已經(jīng)漸漸不能滿足前端開發(fā)的種種場景,。而且alert調(diào)試方式彈出的調(diào)試信息,那個窗口著實不太美觀,,而且會遮擋部分頁面內(nèi)容,,著實有些不太友好。 另一方面,,alert的調(diào)試信息,,必須在程序邏輯中添加類似”alert(xxxxx)”這樣的語句,才能正常工作,,并且alert會阻礙頁面的繼續(xù)渲染,。這就意味著開發(fā)人員調(diào)試完成后,必須手動清除這些調(diào)試代碼,,實在有些麻煩,。 所以,,新一代的瀏覽器Firefox、Chrome,,包括IE,,都相繼推出了JS調(diào)試控制臺,支持使用類似”console.log(xxxx)”的形式,,在控制臺打印調(diào)試信息,,而不直接影響頁面顯示。以IE為例,,它看起來像這樣: 好吧,,再見丑陋的alert彈出框。而以Chrome瀏覽器為首的后起之秀,,為Console擴展了更豐富的功能: 你以為這樣就滿足了,?Chrome開發(fā)團隊的想象力實在不得不讓人佩服: 好了,稍微多說了一點點題外話,??傊刂婆_以及瀏覽器內(nèi)置Console對象的出現(xiàn),,給前端開發(fā)調(diào)試帶來了極大的便利,。 有人會問,這樣的調(diào)試代碼不一樣需要在調(diào)試完成后進行清理嗎,? 關(guān)于這個問題,,如果在使用console對象之前先進性存在性驗證,其實不刪除也不會對業(yè)務(wù)邏輯造成破壞,。當然,為了代碼整潔,,在調(diào)試完成后,,還是應(yīng)盡可能刪除這些與業(yè)務(wù)邏輯無關(guān)的調(diào)試代碼。 JS斷點調(diào)試
JS斷點調(diào)試,,即是在瀏覽器開發(fā)者工具中為JS代碼添加斷點,,讓JS執(zhí)行到某一特定位置停住,方便開發(fā)者對該處代碼段的分析與邏輯處理,。為了能夠觀察到斷點調(diào)試的效果,,我們預(yù)先隨意準備一段JS代碼: 代碼很簡單,就是定義一個函數(shù),,傳入兩個數(shù),,分別加上一個亂七八糟的隨機整數(shù)后,再返回兩個數(shù)的總和,。以Chrome開發(fā)者工具為例,,我們來看一下JS斷點調(diào)試的基本方法。 Sources斷點 首先,,測試代碼中我們通過上圖console的輸出結(jié)果可以看出代碼應(yīng)該是正常運行了,,但是為什么是應(yīng)該呢?因為函數(shù)中加了一個隨機數(shù),,而最終結(jié)果是否真的是正確的呢,?這是毫無意義的猜想,但是假設(shè)我現(xiàn)在就是要驗證一下:函數(shù)傳入的兩個數(shù),、被加的隨機數(shù),,以及最終的總和。那么該怎么操作呢,? 方法一,,前面講過最普通的,無論使用alert還是console,,我們可以這么來驗證: 從上圖發(fā)現(xiàn),,我們在代碼中新增了三行console代碼,用以打印我們關(guān)心的數(shù)據(jù)變量,,而最終我們從控制臺(Console面板)中的輸出結(jié)果,,可以很清楚的驗證整個計算過程是否正常,進而達到我們題設(shè)的驗證要求,。 方法二,,方法一的驗證過程存在很明顯的弊端就是,添加了很多冗余代碼,,接下來我們看一下使用斷點進行驗證,,是否更加方便,先看一個如何加斷點,,以及斷點后是什么效果: 如圖,,給一段代碼添加斷點的流程是“F12(Ctrl + Shift + I)打開開發(fā)工具”——“點擊Sources菜單”——“左側(cè)樹中找到相應(yīng)文件”——“點擊行號列”即完成在當前行添加/刪除斷點操作。當斷點添加完畢后,,刷新頁面JS執(zhí)行到斷點位置停住,,在Sources界面會看到當前作用域中所有變量和值,,只需對每個值進行驗證即可完成我們題設(shè)驗證要求。 那問題來了,,仔細的朋友會發(fā)現(xiàn)當我的代碼執(zhí)行到斷點的時候,,顯示的變量a和b的值是已經(jīng)進行過加法運算后的,我們看不到調(diào)用sum函數(shù)時初始傳入的10和20,。那么該怎么辦呢,?這就要回過頭來先學(xué)習(xí)一下斷點調(diào)試的一些基礎(chǔ)知識了。我們打開Sources面板后其實會在界面中看到如下內(nèi)容,,我們跟著鼠標軌跡逐一看看都是什么意思: 從左到右,,各個圖標表示的功能分別為:
到此,斷點調(diào)試的功能鍵介紹得差不多了,,接下來我們就可以一行一行去看我們的程序代碼,,查看每一行執(zhí)行完畢之后,我們各個變量的變化情況了,,如下圖所示: 如上,,我們可以看到a、b變量從最初值,,到中間加上隨機值,,再到最后計算總和并輸出最終結(jié)果的整個過程,完成題設(shè)驗證要求不在話下,。 其余幾個功能鍵,,我們稍微改動一下我們的測試代碼,用一張gif圖來演示他們的使用方法: 這里需要注意一點,,直接在代碼區(qū)打印變量值的功能是在較新版本的Chrome瀏覽器中才新增的功能,,如果你還在使用較老版本的Chrome瀏覽器,,可能無法直接在斷點的情況下查看變量信息,,此時你可以將鼠標移動到變量名上短暫停頓則會出現(xiàn)變量值。也可以用鼠標選中變量名稱,,然后右鍵“Add to watch”在Watch面板查看,,此方法同樣適用于表達式。此外,,你還可以在斷點情況下,,切換到Console面板,,直接在控制臺輸入變量名稱,回車查看變量信息,。該部分比較簡單,,考慮篇幅問題,不在做圖演示,。 Debugger斷點 所謂的Debugger斷點,,其實是我自己給它命名的,專業(yè)術(shù)語我也不知道怎么說,。具體的說就是通過在代碼中添加”debugger;”語句,,當代碼執(zhí)行到該語句的時候就會自動斷點。接下去的操作就跟在Sources面板添加斷點調(diào)試幾乎一模一樣,,唯一的區(qū)別在于調(diào)試完后需要刪除該語句,。 既然除了設(shè)置斷點的方式不一樣,功能和Sources面板添加斷點效果一樣,,那么為什么還會存在這種方式呢,?我想原因應(yīng)該是這樣的:我們在開發(fā)中偶爾會遇到異步加載html片段(包含內(nèi)嵌JS代碼)的情況,而這部分JS代碼在Sources樹種無法找到,,因此無法直接在開發(fā)工具中直接添加斷點,,那么如果想給異步加載的腳本添加斷點,此時”debugger;”就發(fā)揮作用了,。我們直接通過gif圖看看他的效果: DOM斷點調(diào)試 DOM斷點,,顧名思義就是在DOM元素上添加斷點,進而達到調(diào)試的目的,。而在實際使用中斷點的效果最終還是落地到JS邏輯之內(nèi),。我們依次來看一下每一種DOM斷點的具體效果。 當節(jié)點內(nèi)部子節(jié)點變化時斷點(Break on subtree modifications) 在前端開發(fā)越來越復(fù)雜的今天,,前端JS代碼越來越多,,邏輯越來越復(fù)雜,一個看似簡單的Web頁面,,通常伴隨著大段大段的JS代碼,,涉及諸多DOM節(jié)點增、刪,、改的操作,。難免遇到直接通過JS代碼很難定位代碼段的情況,而我們卻可以通過開發(fā)者工具的Elements面板,,快速定位到相關(guān)DOM節(jié)點,,這時候通過DOM斷點定位腳本就顯得尤其重要了。具體我們還是通過gif演示來看一下吧: 上圖演示了對ul子節(jié)點(li)的增加、刪除以及交換順序操作觸發(fā)斷點的效果,。但需要注意的是,,對子節(jié)點進行屬性修改和內(nèi)容修改并不會觸發(fā)斷點。 當節(jié)點屬性發(fā)生變化時斷點(Break on attributes modifications) 另一方面,,由于前端處理的業(yè)務(wù)邏輯越來越復(fù)雜,,對一些數(shù)據(jù)的存儲依賴越來越強烈,而將臨時數(shù)據(jù)存儲于DOM節(jié)點的(自定義)屬性中,,是很多情況下開發(fā)者優(yōu)先選擇的方式,。特別是在HTML5標準增強自定義屬性支持(例:dataset、data-*之類)之后,,屬性設(shè)置應(yīng)用越來越多,,因此Chrome開發(fā)者工具也提供了屬性變化斷點支持,其效果大致如下: 此方式同樣需要注意,,對子節(jié)點的屬性進行任何操作也不會觸發(fā)節(jié)點本身的斷點,。 當節(jié)點被移除時斷點(Break on node removal) 這個DOM斷點設(shè)置很簡單,觸發(fā)方式很明確——當節(jié)點被刪除時,。所以通常情況應(yīng)該是在執(zhí)行”parentNode.removeChild(childNode)”語句的時候使用此方式,。此方式使用不多。 前面介紹到的基本上是我們在日常開發(fā)中經(jīng)常用到的調(diào)試手段,,運用得當它們也幾乎能應(yīng)對我們?nèi)粘i_發(fā)中的幾乎所有問題,。但是,開發(fā)者工具還考慮到了更多的情況,,提供更多的斷點方式,,如圖: XHR Breakpoints 這幾年前端開發(fā)發(fā)生了翻天覆地的變化,從當初的名不見經(jīng)傳到如今的盛極一時,,Ajax驅(qū)動Web富應(yīng)用,,移動WebApp單頁應(yīng)用風生水起。這一切都離不開XMLHttpRequest對象,,而“XHR Breakpoints”正是專為異步而生的斷點調(diào)試功能,。 我們可以通過“XHR Breakpoints”右側(cè)的“+”號為異步斷點添加斷點條件,當異步請求觸發(fā)時的URL滿足此條件,,JS邏輯則會自動產(chǎn)生斷點,。演示動畫中并沒有演示到斷點位置,這是因為,,演示使用的是jQuery封裝好的ajax方法,,代碼已經(jīng)過壓縮,看不到什么效果,,而事實上XHR斷點的產(chǎn)生位置是”xhr.send()”語句,。 XHR斷點的強大之處是可以自定義斷點規(guī)則,,這就意味著我們可以針對某一批,、某一個,乃至所有異步請求進行斷點設(shè)置,,非常強大,。但是,似乎這個功能在日常開發(fā)中用得并不多,,至少我用得不多,。想想原因大概有兩點:其一,這類型的斷點調(diào)試需求在日常業(yè)務(wù)中本身涉及不多,;其二,,現(xiàn)階段的前端開發(fā)大多基于JS框架進行,最基本的jQuery也已經(jīng)對Ajax進行了良好封裝,,極少有人自己封裝Ajax方法,,而項目為了減少代碼體積,通常選擇壓縮后的代碼庫,,使得XHR斷點跟蹤相對不那么容易了,。 Event Listener Breakpoints 事件監(jiān)聽器斷點,即根據(jù)事件名稱進行斷點設(shè)置,。當事件被觸發(fā)時,,斷點到事件綁定的位置。事件監(jiān)聽器斷點,,列出了所有頁面及腳本事件,,包括:鼠標、鍵盤,、動畫,、定時器、XHR等等,。極大的降低了事件方面業(yè)務(wù)邏輯的調(diào)試難度,。 演示實例演示了當click事件被觸發(fā)時和當setTimeout被設(shè)置時的斷點效果。實例顯示,,當選中click事件斷點之后,,兩個按鈕的被點擊時都觸發(fā)了斷點,而當setTimeout被設(shè)置時,,“Set Timer”斷點被觸發(fā),。 調(diào)試,是在項目開發(fā)中非常重要的環(huán)節(jié),,不僅可以幫助我們快速定位問題,,還能節(jié)省我們的開發(fā)時間。熟練掌握各種調(diào)試手段,定當為你的職業(yè)發(fā)展帶來諸多利益,,但是,,在如此多的調(diào)試手段中,如何選擇一個適合自己當前應(yīng)用場景的,,這需要經(jīng)驗,,需要不斷嘗試積累。 |
|
來自: 昵稱總是重復(fù) > 《Java》