前端 debug 的奇技淫巧
為什么要寫這個文章呢?其實(shí)發(fā)現(xiàn)很多同學(xué)對一些很簡單又有效的 debug 手段都不太了解,找 bug 的方式都不是很高效,導(dǎo)致最終 bug 找不到或者走了很多彎路。
Devtools
作為前端開發(fā),chrome 的 devtools 一定不陌生,下面講一講 devtools 里面 debug 的一些思路。
breakpoint
其中斷點(diǎn)是最最經(jīng)常用到的,但很多同學(xué)都只用過默認(rèn)的 breakpoint,其實(shí)還有其他兩種。
breakpoint
當(dāng)代碼執(zhí)行到該行代碼時暫停
conditional breakpoint
條件斷點(diǎn),當(dāng)表達(dá)式為 true 時才會暫停,下圖是當(dāng)變量a === 1時才暫停。經(jīng)典應(yīng)用場景是當(dāng) bug 是偶現(xiàn)時,你需要知道入?yún)⑹裁吹恼徽?,你可以打一個你認(rèn)為不正常的條件斷點(diǎn),看看是誰調(diào)用的。PS:值得注意的是,如果你的表達(dá)式報錯,那這個斷點(diǎn)就會不生效,需要甄別到底是報錯引起的斷點(diǎn)沒進(jìn)入還是真的沒進(jìn)入。
logpoint
日志斷點(diǎn),當(dāng)代碼執(zhí)行到這里時,會在控制臺輸出你的表達(dá)式,不會暫停代碼執(zhí)行,下圖是將 a 輸出到控制臺的例子。
值得注意的是,當(dāng)你在調(diào)試帶有 sroucemap 的壓縮后的代碼,可能會產(chǎn)生你看到的變量名和實(shí)際運(yùn)行時拿到的變量名不一樣,此時可以在右側(cè) scope 找到你想要的真實(shí)變量名或者在 source 面板 disable 掉 js 的 sourcemap 后再打斷點(diǎn)。
Performance
當(dāng)你做了一些操作,不確定到底執(zhí)行了什么代碼時,可以利用 performance 來捕獲到底什么樣的代碼被執(zhí)行了,結(jié)合你的具體情況,有時候也會找到線索,有意想不到的收獲。
是誰動了我的代碼
經(jīng)典面試題,如何找到是誰阻止了冒泡,直接在控制臺輸入下面的代碼即可。經(jīng)常用于尋找我綁定的事件為什么沒有被觸發(fā)。
var tmpStopPropagation = MouseEvent.prototype.stopPropagation;
MouseEvent.prototype.stopPropagation = function(...args) {
console.trace('stopPropagation');
tmpStopPropagation.call(this, ...args);
};
下面這個例子是找到到底是誰對容器進(jìn)行了滾動,比如我們遇到一些頁面跳動或者抖動的場景,尋找到底是誰滾動了容器,當(dāng)然滾動還有其他方法會觸發(fā),比如scrollIntoView,但思路都是一樣的,代理這個方法即可。
var tmpScrollTop = element.scrollTop;
Object.defineProperty(element, 'scrollTop', {
get: function() {
return tmpScrollTop;
},
set: function(newVal) {
console.trace('scrollTop');
tmpScrollTop = newVal;
}
})
setTimeout
如果我們在想要打斷點(diǎn)的時候依賴鼠標(biāo)或者鍵盤操作,如果你去 source 面板去點(diǎn)擊暫定,那我的現(xiàn)場就沒有了,那下面的代碼會幫你解決問題。
setTimeout(() => {debugger;}, 4000);
還有這樣一種 case,比如我期望在我鼠標(biāo)移動時看看某個變量值是多少,此時不要再傻傻的在代碼里面添加 console.log,直接運(yùn)行下面的代碼,可以實(shí)時看到你想要的變量。這個方法比較像logpoint,不過不需要找源碼去打斷點(diǎn),各有各的應(yīng)用場景。
setTimeout(() => {console.log(yourInstance.getSomeValue());}, 100);
SSR
當(dāng)你想要 debug 某個頁面上 SSR 渲染的樣式時,可以禁用掉 js 的執(zhí)行,具體操作是打開 devtools 的 source 面板,然后 cmd+p,輸入「>disable javascript」,按回車,然后刷新頁面,你的頁面就是純 SSR 狀態(tài)了。
二分法
這個是終極 debug 方法,很少會用到,但也很通俗易懂,有一定應(yīng)用場景。當(dāng)你發(fā)現(xiàn)在某個版本之后你的代碼出了問題,但又各種找不到思路,我只知道在 A 版本沒問題,B 版本就有問題了,或者代碼突然出了問題,又不知道是依賴了誰出的問題,就可以用這種方法。總的思路就是「控制變量」,你可以在代碼中批量注釋一些代碼,然后驗(yàn)證問題還有沒有,如果還就的話就繼續(xù)注釋,沒有的話問題就出在被注釋的代碼里,比較像算法中的二分法。
總結(jié)
如何 debug 還有更多的技巧,我這里寫的也只是一部分,如果有其他更好的思路歡迎留言。
點(diǎn)個『在看』支持下 
