了解如何使用瀏覽器DevTools調試器調試JavaScript
調試是程序員活動的核心技能之一。
有時我們會盡力而為,但是程序無法正常運行,例如,它崩潰了,速度很慢或正在打印錯誤的信息。
當您編寫的程序表現不理想時,您會怎麼做?
您開始調試它。
找出錯誤可能在哪裡
第一步始終是查看正在發生的事情,並嘗試確定問題的根源。在環境中有問題嗎?您提供給程序的輸入是否有問題?是否由於內存使用過多而導致一次崩潰?還是每次您運行它時都會發生?
這些都是解決問題時開始朝正確方向發展的關鍵信息。
一旦知道了錯誤的來源,就可以開始檢查代碼的特定部分。
閱讀代碼
至少在工具方面,最簡單的調試方法是閱讀您編寫的代碼。大聲從我們自己的聲音中聽到的聲音有些不可思議的事情,而您在靜默地閱讀時卻不會發生。
我經常以這種方式發現問題。
使用控制台
如果閱讀該代碼對您沒有任何幫助,那麼下一個邏輯步驟是開始向您的代碼中添加幾行代碼,以使您有所了解。
在JavaScript前端代碼中,您經常要做的是使用alert()
和console.log
(及其酷友)。
考慮這一行:
const a = calculateA()
const b = calculateB()
const result = a + b
不知何故無法正確計算結果,因此您可以先添加alert(a)
和alert(b)
在計算結果之前,瀏覽器在執行代碼時將打開兩個警報面板。
const a = calculateA()
const b = calculateB()
alert(a)
alert(b)
const result = a + b
如果您要傳遞給它,這會很好alert()
是字符串或數字。一旦有了數組或對象,事情就變得太複雜了alert()
,您可以使用控制台API。從...開始console.log()
:
const a = calculateA()
const b = calculateB()
console.log(a)
console.log(b)
const result = a + b
該值顯示在瀏覽器開發人員工具的JavaScript控制台中。為了方便起見,我在此處解釋如何在Chrome DevTools中進行調試,但是一般概念適用於所有瀏覽器,但在支持的功能方面有所不同。
Chrome開發工具
結果console.log()
調用將打印到JavaScript控制台。這是每個瀏覽器或多或少通用的工具:
該工具非常強大,可讓您打印複雜的對像或數組,並可以檢查它們的每個屬性。
在裡面控制台API發布後,您將看到使用它的所有選項和詳細信息,因此在此我不解釋所有詳細信息。
調試器
調試器是瀏覽器開發人員工具中功能最強大的工具,可以在資料來源控制板:
屏幕的頂部顯示文件導航器。
您可以選擇任何文件並在右側檢查它。這對於設置斷點非常重要,我們將在後面看到。
底部是實際的調試器。
斷點
當瀏覽器加載頁面時,將執行JavaScript代碼,直到遇到斷點為止。
此時,執行被暫停,您可以檢查所有有關正在運行的程序。
您可以檢查變量值,然後一次只恢復一行程序的執行。
但是首先,什麼是斷點?簡單來說,斷點就是breakpoint
指令放在您的代碼中。當瀏覽器遇到它時,它停止。
在開發時,這是一個不錯的選擇。另一個選項是在“源”面板中打開文件,然後單擊要添加斷點的行上的數字:
再次單擊斷點將其刪除。
添加斷點後,您可以重新加載頁面,並且代碼在找到斷點時將在該執行點停止。
添加斷點時,您可以在斷點面板form.js
在線的7
有斷點。您可以在那裡查看所有斷點,並暫時禁用它們。
還有其他類型的斷點:
- XHR /獲取斷點:在發送任何網絡請求時觸發
- DOM斷點:在DOM元素更改時觸發
- 事件偵聽器斷點:在發生某些事件(如鼠標單擊)時觸發
範圍
在此示例中,我在事件監聽器中設置了一個斷點,因此我必須提交一個表單來觸發它:
現在,將打印範圍內的所有變量及其各自的值。您可以通過雙擊來編輯這些變量。
觀察變量和表達式
權利範圍面板上有手錶控制板。
它有一個+
您可以用來添加任何表達式的按鈕。例如添加name
將打印name
在示例中為可變值Flavio
。你可以加name.toUpperCase()
它會打印FLAVIO
:
恢復執行
現在,自斷點停止執行以來,所有腳本均已暫停。
在“在斷點處暫停”標語上方有一組按鈕,可讓您更改此狀態。
第一個是藍色。單擊它可恢復正常腳本執行。
第二個按鈕是跨過,它將繼續執行直到下一行,然後再次停止。
下一個按鈕執行步入操作:進入正在執行的功能,讓您了解其詳細信息。
走出去相反:返回到調用此函數的外部函數。
這些是調試期間控制流的主要方法。
編輯腳本
在此devtools屏幕上,您可以編輯任何腳本,也可以在腳本停止執行時進行編輯。只需編輯文件,然後在Mac上按cmd-S或在Windows / Linux上按ctrl-S。
當然,除非您在本地工作並在devtools(一個更高級的主題)中設置工作區,否則所做的更改不會持久保存到磁盤上。
檢查調用堆棧
這調用堆棧很高興看到您深入到JavaScript代碼中有多少個功能級別。通過單擊每個函數名稱,它也可以使您在堆棧中向上移動:
黑盒腳本
例如,通常您在不想“涉足”的庫中工作時,您會信任它們,並且不想在調用堆棧中看到它們的代碼。就像上面的情況一樣validator.min.js
,用於電子郵件驗證。
我相信它做得很好,所以我可以在調用堆棧中右鍵單擊它,然後按黑盒腳本。從那時起,就不可能進入此腳本代碼,而您可以快樂地處理自己的應用程序代碼。
使用瀏覽器devtools調試Node.js
由於Node.js基於Chrome的同一引擎構建,v8,您可以鏈接2並使用Chrome DevTools來檢查Node.js應用程序的執行情況。
打開你的終端並運行
node --inspect
然後在Chrome中輸入以下網址:about://inspect
。
單擊“節點”目標旁邊的“打開用於節點的專用DevTools”鏈接,您將可以在瀏覽器DevTools中訪問Node.js:
確保單擊該按鈕,而不單擊下面的檢查鏈接,因為它在我們重新啟動時會自動重新連接到Node.js實例-非常方便!
免費下載我的JavaScript初學者手冊
更多js教程:
- JavaScript中應避免的事情(不良部分)
- JavaScript中的延遲和承諾(+ Ember.js示例)
- 如何使用JavaScript將文件上傳到服務器
- JavaScript編碼風格
- JavaScript數組簡介
- JavaScript編程語言簡介
- 完整的ECMAScript 2015-2019指南
- 了解JavaScript承諾
- JavaScript的詞彙結構
- JavaScript類型
- JavaScript變數
- 示例Web應用程序提示列表
- JavaScript函數式編程簡介
- 具有Async和Await的現代異步JavaScript
- JavaScript循環和範圍
- Map JavaScript數據結構
- 設置JavaScript數據結構
- JavaScript模板文字指南
- 學習JavaScript的路線圖
- JavaScript表達式
- 發現JavaScript計時器
- JavaScript事件說明
- JavaScript循環
- 使用map,filter,reduce和find編寫JavaScript循環
- JavaScript事件循環
- JavaScript函數
- JavaScript詞彙表
- JavaScript閉包說明
- JavaScript Arrow函數教程
- JavaScript正則表達式指南
- 如何在JavaScript中檢查字符串是否包含子字符串
- 如何從JavaScript中的數組中刪除項目
- 如何深度克隆JavaScript對象
- Introduction to Unicode and UTF-8
- JavaScript中的Unicode
- 如何在JavaScript中大寫字符串的第一個字母
- 如何在JavaScript中將數字格式化為貨幣值
- 如何在JavaScript中將字符串轉換為數字
- 這在JavaScript中
- 如何在JavaScript中獲取當前時間戳
- JavaScript嚴格模式
- JavaScript立即調用函數表達式(IIFE)
- 如何使用JavaScript重定向到另一個網頁
- 如何從JavaScript對像中刪除屬性
- 如何在JavaScript中將項目追加到數組
- 如何檢查JavaScript對象屬性是否未定義
- ES模塊簡介
- CommonJS簡介
- JavaScript異步編程和回調
- 如何替換JavaScript中所有出現的字符串
- 現代JavaScript語法快速參考指南
- 如何在JavaScript中修剪數字中的前導零
- 如何檢查JavaScript對象
- 關於JavaScript日期的權威指南
- Moment.js教程
- JavaScript中的分號
- JavaScript算術運算符
- JavaScript Math對象
- 在JavaScript中生成隨機且唯一的字符串
- 如何使您的JavaScript函數進入睡眠狀態
- JavaScript原型繼承
- JavaScript例外
- 如何使用JavaScript類
- JavaScript食譜
- JavaScript中的引號
- 如何在JavaScript中驗證電子郵件地址
- 如何獲取JavaScript數組中一組對象的唯一屬性
- 如何在JavaScript中檢查字符串是否以另一個字符串開頭
- 如何在JavaScript中創建多行字符串
- ES6指南
- 如何在JavaScript中獲取當前URL
- ES2016指南
- 如何使用JavaScript中的值初始化新數組
- ES2017指南
- ES2018指南
- 如何在Array.prototype.map()中使用Async和Await
- 異步與同步代碼
- 如何在JavaScript中生成兩個數字之間的隨機數
- HTML Canvas API教程
- 如何在JavaScript中的for-of循環中獲取迭代的索引
- 什麼是單頁應用程序?
- WebAssembly簡介
- JSON簡介
- JSONP指南
- Should you use or learn jQuery in 2020?
- 如何使用純JavaScript隱藏DOM元素
- 如何在JavaScript中合併兩個對象
- 如何清空JavaScript數組
- 如何使用JavaScript編碼URL
- 如何在JavaScript中設置默認參數值
- 如何在JavaScript中按屬性值對對像數組進行排序
- 如何計算JavaScript對像中的屬性數量
- JavaScript中的call()和apply()
- WebRTC庫PeerJS簡介
- 使用Rest和Spread處理對象和數組
- 用JavaScript分解對象和數組
- 調試JavaScript的權威指南
- TypeScript指南
- 在JavaScript中動態選擇對象的方法
- 將undefined傳遞給JavaScript立即調用的函數表達式
- 鬆散類型與強類型語言
- 如何使用JavaScript設置DOM元素的樣式
- 用JavaScript投放
- JavaScript生成器教程
- node_modules文件夾的大小不是問題。這是一種特權
- 在JavaScript中導入模塊時如何解決意外的標識符錯誤
- 如何在JavaScript中列出對象的所有方法
- 字符串replace()方法
- 字符串search()方法
- 我如何運行一些JavaScript代碼段
- ES2019指南
- 字符串charAt()方法
- 字符串charCodeAt()方法
- 字符串codePointAt()方法
- 字符串concat()方法
- 字符串endsWith()方法
- 字符串include()方法
- 字符串indexOf()方法
- 字符串lastIndexOf()方法
- 字符串localeCompare()方法
- 字符串match()方法
- 字符串normalize()方法
- 字符串padEnd()方法
- 字符串padStart()方法
- 字符串repeat()方法
- 字符串slice()方法
- 字符串split()方法
- 字符串startsWith()方法
- String substring()方法
- 字符串toLocaleLowerCase()方法
- 字符串toLocaleUpperCase()方法
- String toLowerCase()方法
- 字符串toString()方法
- String toUpperCase()方法
- 字符串trim()方法
- String trimEnd()方法
- String trimStart()方法
- JavaScript的記憶化
- 字符串valueOf()方法
- JavaScript參考:字符串
- Number isInteger()方法
- Number isNaN()方法
- Number isSafeInteger()方法
- Number parseFloat()方法
- Number parseInt()方法
- Number toString()方法
- Number valueOf()方法
- Number toPrecision()方法
- Number toExponential()方法
- Number toLocaleString()方法
- Number toFixed()方法
- Number isFinite()方法
- JavaScript參考:編號
- JavaScript屬性描述符
- 對象的assign()方法
- 對象的create()方法
- Object defineProperties()方法
- Object defineProperty()方法
- 對象entry()方法
- 對象Frozen()方法
- Object getOwnPropertyDescriptor()方法
- Object getOwnPropertyDescriptors()方法
- Object getOwnPropertyNames()方法
- Object getOwnPropertySymbols()方法
- Object getPrototypeOf()方法
- Object is()方法
- Object isExtensible()方法
- Object isFrozen()方法
- Object isSealed()方法
- 對象keys()方法
- 對象的preventExtensions()方法
- 對象seal()方法
- Object setPrototypeOf()方法
- Object values()方法
- 對象的hasOwnProperty()方法
- Object isPrototypeOf()方法
- 對象的propertyIsEnumerable()方法
- Object toLocaleString()方法
- Object toString()方法
- Object valueOf()方法
- JavaScript參考:對象
- JavaScript賦值運算符
- JavaScript國際化
- JavaScript typeof運算子
- JavaScript新運算符
- JavaScript比較運算符
- JavaScript運算符優先級規則
- JavaScript instanceof運算符
- JavaScript陳述式
- JavaScript範圍
- JavaScript類型轉換(廣播)
- JavaScript相等運算符
- JavaScript if / else條件
- JavaScript切換條件
- JavaScript刪除運算符
- JavaScript函數參數
- JavaScript Spread運算符
- JavaScript返回值
- JavaScript邏輯運算符
- JavaScript三元運算符
- JavaScript遞歸
- JavaScript對象屬性
- JavaScript錯誤對象
- JavaScript全局對象
- JavaScript filter()函數
- JavaScript map()函數
- JavaScript reduce()函數
- JavaScript`in`運算子
- JavaScript運算子
- 如何在JavaScript中獲取CSS屬性的值
- 如何將事件偵聽器添加到JavaScript中的多個元素
- JavaScript私有類字段
- 如何在JavaScript中按日期值對數組排序
- JavaScript公共類字段
- JavaScript符號
- 如何使用JavaScript bcrypt庫
- 使用對象解構時如何重命名字段
- 如何在不使用TypeScript的情況下檢查JavaScript中的類型
- 如何檢查JavaScript數組是否包含特定值
- 雙重否定運算符是什麼!用JavaScript做嗎?
- JavaScript比較中應使用哪個等號運算符? == vs ===
- JavaScript仍然值得學習嗎?
- 如何在JavaScript中返回異步函數的結果
- 如何在JavaScript中檢查對像是否為空
- 如何突破JavaScript中的for循環
- 如何在JavaScript中的特定索引處將項目添加到數組
- 為什麼不應該修改JavaScript對象原型
- 在JavaScript中使用let和var有什麼區別?
- 用於激活JavaScript功能的鏈接
- 如何在JavaScript中連接兩個字符串
- 如何在JavaScript中連接兩個數組
- 如何檢查JavaScript值是否為數組?
- 如何在JavaScript中獲取數組的最後一個元素?
- 如何使用Axios發送urlencoded數據
- 如何使用JavaScript獲取明天的日期
- 如何使用JavaScript獲取昨天的日期
- 如何從JavaScript日期獲取月份名稱
- 如何檢查兩個日期是否在JavaScript中是同一天
- 如何在JavaScript中檢查日期是否指向過去的一天
- 標有JavaScript的語句
- 如何等待2個或更多的Promise在JavaScript中解析
- 如何在JavaScript中獲取兩個日期之間的日期
- 如何使用提取上傳文件
- 如何在JavaScript中格式化日期
- 如何遍歷JavaScript中的對象屬性
- 如何在JavaScript中計算兩個日期之間的天數
- 如何在ES模塊中使用頂級等待
- JavaScript動態導入
- JavaScript可選鏈接
- 如何在JavaScript中替換字符串內的空格
- JavaScript空合併
- 如何在JavaScript中展平數組
- JavaScript的十年
- 如何使用Axios發送授權標頭
- JavaScript中的關鍵字和保留字列表
- 如何在JavaScript中將數組轉換為字符串
- 如何刪除所有的node_modules文件夾內容
- 如何從JavaScript數組中刪除重複項
- 在JavaScript中讓vs const
- 各種JavaScript庫中的相同POST API調用
- 如何在JS中獲取數組中的前n個項目
- 如何在JS中將數組劃分為多個相等的部分
- 如何減慢JavaScript中的循環
- 如何在HTML畫布中加載圖像
- 如何在JavaScript中將字符串切成單詞
- 如何在JavaScript中將數組分成兩半
- 如何將文本寫入HTML畫布
- 如何在JavaScript中刪除字符串的最後一個字符
- 如何在JavaScript中刪除字符串的第一個字符
- 如何修復TypeError:無法分配為只讀對象“#< Object>”的屬性“ exports”錯誤
- 如何創建退出意圖彈出窗口
- 如何檢查一個元素是否是另一個元素的後代
- 如何對每個Axios請求強制使用憑據
- 如何解決JavaScript中的“不是函數”錯誤
- 蓋茨比,如何更改圖標
- 使用Gatsby加載外部JS文件
- 如何使用JavaScript檢測暗模式
- 包裹,如何修復“ regeneratorRuntime未定義”錯誤
- 如何檢測Adblocker是否與JavaScript一起使用
- 使用TypeScript中的類型進行對象分解
- Deno手冊:Deno的簡要介紹🦕
- 如何使用JavaScript獲取路徑或URL的最後一段
- 如何隨機播放JavaScript數組中的元素
- 如何檢查JavaScript對像中是否存在密鑰
- 事件冒泡和事件捕獲
- event.stopPropagation與event.preventDefault()與在DOM事件中返回false
- JavaScript中的原始類型與對象
- 在JavaScript中,如何判斷值的類型?
- 如何從JavaScript中的函數返回多個值
- JavaScript中的箭頭函數與常規函數
- 我們可以通過哪些方式訪問對象屬性的值?
- JavaScript中的null和undefined有什麼區別?
- 方法和函數有什麼區別?
- 我們可以通過哪些方法擺脫JavaScript循環?
- JavaScript for..of循環
- 什麼是JavaScript中的對象解構?
- JavaScript吊起了什麼?
- 如何使用JavaScript將逗號更改為點
- 使用DOM時計時的重要性
- 如何反轉JavaScript數組
- 如何在JavaScript中檢查值是否為數字
- 如何在JavaScript函數中接受無限的參數
- JavaScript代理對象
- 使用香草JavaScript在瀏覽器中進行事件委託
- JavaScript super關鍵字
- XState簡介
- 值是通過引用傳遞還是通過JavaScript中的值傳遞?
- JavaScript中的自定義事件
- JavaScript中的自定義錯誤
- JavaScript中的命名空間
- JavaScript中逗號的奇怪用法
- JavaScript中的鏈接方法調用
- 如何處理承諾拒絕
- 如何在JavaScript中交換兩個數組元素
- 如何在使用Gitbook時解決“ cb.apply不是函數”錯誤
- 如何在JavaScript中的數組開頭添加項目
- Gatsby,修復“找不到模塊gatsby-cli / lib / reporter”錯誤
- 如何獲取JavaScript數組中項目的索引
- 如何在JavaScript中測試空對象
- 如何將對象解構為JavaScript中的現有變量
- 數組JavaScript數據結構
- 堆棧JavaScript數據結構
- JavaScript數據結構:隊列
- JavaScript數據結構:集
- JavaScript數據結構:字典
- JavaScript數據結構:鏈接列表
- JavaScript,如何導出函數
- JavaScript,如何導出多個功能
- JavaScript,如何退出功能
- JavaScript,如何在字符串中查找字符
- JavaScript,如何過濾數組
- JavaScript,如何擴展類
- JavaScript,如何在數組中查找重複項
- JavaScript,如何替換數組的項
- JavaScript算法:線性搜索
- JavaScript算法:二進制搜索
- JavaScript算法:選擇排序
- JavaScript算法:Quicksort
- JavaScript算法:合併排序
- JavaScript算法:冒泡排序