相信絕大多數同學使用 console.log 偵錯的,把想看的變數值列印在控制檯。【相關教學推薦:、】
這樣能滿足需求,但是遇到物件的列印就不行了。
比如我想看 webpack 原始碼裡的 compilation 物件的值,我列印了一下:
但你會發現物件的值也是物件的時候不會展開,而是列印一個 [Object] [Array] 這種字串。
更致命的是列印的太長會超過緩衝區的大小,terminal 裡會顯示不全:
而你用 debugger 來跑,在這裡打個斷點來看就沒這些問題了:
有的同學可能會說,那列印一個簡單的值的時候用 console.log 還是很方便呀。
比如這樣:
真的麼?
那還不如用 logpoint:
程式碼執行到這裡就會列印:
而且沒有汙染程式碼,用 console.log 的話偵錯完之後這個 console 不也得刪掉麼?
但是 logpoint 不用,它就是個斷點的設定,不在程式碼裡。
當然,最重要的是 Debugger 偵錯是可以看到呼叫棧和作用域的!
首先是呼叫棧,它就是程式碼的執行路線。
比如這個 App 的函陣列件,你可以看到渲染這個函陣列件會經歷 workLoop、beginWork、renderWithHooks 這些流程:
你可以點開呼叫棧的每一幀看下都執行了啥邏輯,用到啥資料。比如可以看到這個函陣列件的 fiber 節點:
再就是作用域,點選每一個棧幀就可以看到每個函數的作用域中的變數:
用 Debugger 可以看到程式碼的執行路徑,每一步的作用域資訊。而你用 console.log 呢?
只能看到那個變數值而已。
拿到的資訊量的差距不是一點半點,偵錯時間長了,別人會對程式碼的執行流程越來越清晰,而你用 console.log 呢?還是老樣子,因為你看不到程式碼執行路徑。
所以,不管是偵錯庫的原始碼還是業務程式碼,不管是偵錯 Node.js 還是網頁,都推薦用 Debugger 打斷點,別再用 console.log 了,就算想列印紀錄檔,也可以用 LogPoint。
而且在排查問題的時候,用 Debugger 的話可以加一個異常斷點,程式碼跑到拋異常的地方就會斷住:
可以看到呼叫棧來理清出錯前都走了哪些程式碼,可以通過作用域來看到每一個變數的值。
有了這些東西,排查錯誤不就很輕鬆了麼!
而你用 console.log 呢?
啥也沒,只能自己猜。
前面說 Debugger 偵錯可以看到一條程式碼的執行路徑,但是程式碼的執行路徑往往比較曲折。
比如那個 React 會對每個 fiber 節點做處理,每個節點都會呼叫 beginWork。處理完之後又會處理下一個節點,再次呼叫 beginWork:
就像你走了一條小路,然後回到大路之後又走了另一條小路,用 Debugger 只能看到當前這條小路的執行路徑,看不到其他小路的路徑:
這時候就可以結合 Performance 工具了,用 Performance 工具看到程式碼執行的全貌,然後用 Debugger 來深入每一條程式碼執行路徑的細節。
sourcemap 很重要,因為我們執行過的都是編譯打包後的程式碼,基本是不可讀的,偵錯這種程式碼也沒啥意義,而 sourcemap 就可以讓我們直接偵錯最初的原始碼。
比如 vue,關聯了 sourcemap 之後,我們能直接偵錯 ts 原始碼:
nest.js 也是:
不用 sourcemap 的話,想搞懂原始碼,但你偵錯的是編譯後的程式碼,怎麼讀懂呢?
前面說的 Debugger、Performance、SourceMap 只是偵錯程式碼的工具,那會了偵錯工具,依然讀不懂程式碼怎麼辦呢?
我覺得這是不可能的。
為什麼這麼說呢?
就拿 react 原始碼來說:
switch case 能讀懂吧。三目運運算元能讀懂吧。函數呼叫能讀懂吧。
每一行程式碼都能讀懂,而全部的程式碼不就是由這一行行程式碼組成的麼?
加上我們可以單步執行來知道程式碼執行路徑。
為啥每行程式碼都能讀懂,連起來就讀不懂了呢?
那應該是程式碼太多了,而你花的時間不夠而已。
先要讀懂一行,一個函數,讀懂一個小功能的實現流程,慢慢積累,之後瞭解的越來越多之後,你能讀懂的程式碼就會越多。
這篇文章講了為什麼要用偵錯工具,如何讀懂複雜程式碼。
console.log 的弊端太多了,大物件列印不全,會超過 terminal 緩衝區,物件屬性不能展開等等,不建議大家用。就算要列印也可以用 LogPoint。
用 Debugger 可以看到呼叫棧,也就是程式碼的執行路徑,每個棧幀的作用域,可以知道程式碼從開始執行到現在都經歷了什麼,而 console.log 只能知道某個變數的值。
此外,報錯的時候也可以通過異常斷點來梳理程式碼執行路徑來排查報錯原因。
但 Debugger 只能看到一條執行路徑,可以用 Performance 錄製程式碼執行的全流程,然後再結合 Debugger 來深入其中一條路徑的執行細節。
此外,只有偵錯最初的原始碼才有意義,不然偵錯編譯後的程式碼會少很多資訊。可以通過 SourceMap 來關聯到原始碼,不管是 Vue、React 的原始碼還是 Nest.js、Babel 等的原始碼。
會了偵錯之後,就能偵錯各種程式碼了,不存在看不懂的原始碼,因為每一行程式碼都是基礎的語法,都是能看懂的,如果看不懂,只可能是程式碼太多了,你需要更多的耐心去讀一行行程式碼、一個個函數、理清一個個功能的實現,慢慢積累就好了。
掌握基於 Debugger、Performance、SourceMap 等偵錯程式碼之後,各種網頁和 Node.js 程式碼都能偵錯,各種原始碼都能讀懂!【推薦學習:】
以上就是為什麼要用debugger來偵錯程式碼?這樣你能讀懂各種原始碼!的詳細內容,更多請關注TW511.COM其它相關文章!