67个你可能不知道的神奇的浏览器调试技巧
一系列有用的、不明显的技巧,可帮助您充分利用浏览器的调试器。假设对开发人员工具有中级或更高的了解。
Advanced Conditional Breakpoints 高级条件断点
通过在您意想不到的地方使用具有副作用的表达式,我们可以从条件断点等基本功能中挤出更多功能。
Logpoints / Tracepoints 日志点/跟踪点
例如,我们可以在断点中 console.log
。日志点是记录到控制台而不暂停执行的断点 。虽然 Microsoft Edge 内置日志点已经有一段时间了,Chrome 也只是在 v73 中添加了它们,但 Firefox 却没有。但是,我们可以使用条件断点在任何浏览器中模拟它们。
如果您还想获得该行执行次数的运行计数,请使用 console.count
而不是 console.log
。 更新(2020 年 5 月):所有主要浏览器现在都直接支持日志点/跟踪点(Chrome Logpoints, Edge Tracepoints, Firefox Logpoints)
Watch Pane
您还可以在watch pane中使用 console.log
。例如,要在每次应用程序在调试器中暂停时转储 localStorage
的快照,您可以创建一个 console.table(localStorage)
监视:
或者要在 DOM 突变后执行表达式,请设置 DOM 突变断点(在元素检查器中):
然后添加您的watch表达式,例如记录 DOM 的快照: (window.doms = window.doms || []).push(document.documentElement.outerHTML)
。现在,在修改任何 DOM 子树之后,调试器将暂停执行,新的 DOM 快照将位于 window.doms
数组的末尾。 (无法创建不暂停执行的 DOM 突变断点。)
Tracing Callstacks 跟踪调用堆栈
假设您有一个 show spinner的函数和一个hide 它的函数,但在代码中的某个位置您调用了 show 方法,而没有匹配的 hide 调用。如何找到未配对的show 调用的来源?在 show 方法的条件断点中使用 console.trace
,运行代码,找到 show 方法的最后一个堆栈跟踪,然后单击调用者转到代码:
Changing Program Behavior 改变程序行为
通过使用对程序行为有副作用的表达式,我们可以在浏览器中即时更改程序行为。
例如,您可以将参数重写为 getPerson
函数 id
。由于 id=1
的计算结果为 true,因此该条件断点将暂停调试器。为了防止这种情况,请将 , false
附加到表达式中。
Quick and Dirty Performance Profiling
您不应该将性能分析与条件断点评估时间之类的内容混为一谈,但如果您想要快速准确地测量某项运行所需的时间,则可以在条件断点中使用控制台计时 API。在起点设置一个具有条件 console.time('label')
的断点,并在终点设置一个具有条件 console.timeEnd('label')
的断点。每次您正在测量的东西运行时,浏览器都会将其花费的时间记录到控制台。
Using Function Arity 使用函数参数
Break on Number of Arguments 参数个数中断
仅在使用 3 个参数调用当前函数时暂停: arguments.callee.length === 3
当您有一个带有可选参数的重载函数时很有用。
Break on Function Arity Mismatch 函数参数数量不匹配时中断
仅当使用错误数量的参数调用当前函数时才暂停: (arguments.callee.length) != arguments.length
在查找函数调用点中的错误时很有用。
Using Time
Skip Page Load 跳过页面加载
页面加载后 5 秒才暂停: performance.now() > 5000
当您想要设置断点但您只想在初始页面加载后暂停执行时很有用。
Skip N Seconds 跳过 N 秒
如果在接下来的 5 秒内命中断点,则不暂停执行,但在以下时间后随时暂停: window.baseline = window.baseline || Date.now(), (Date.now() - window.baseline) > 5000
您可以随时从控制台重置计数器: window.baseline = Date.now()
Using CSS 使用CSS
根据计算出的 CSS 值暂停,例如仅当文档正文具有红色背景色时暂停执行: window.getComputedStyle(document.body).backgroundColor === "rgb(255,0,0)"
Even Calls Only
仅在执行该行时每隔一段时间暂停一次: window.counter = window.counter || 0, window.counter % 2 === 0
Break on Sample
仅在该行执行的随机样本上中断,例如该行每执行 10 次,只中断 1 次: Math.random() < 0.1
Never Pause Here
当您右键单击装订线并选择"永不在此暂停"时,Chrome 会创建一个条件断点 false
并且永远不会通过。这使得调试器永远不会在此行暂停。
当您想要从 XHR 断点中免除一行、忽略正在抛出的异常等时很有用。
Automatic Instance IDs 自动实例 ID
通过在构造函数中设置条件断点,自动为类的每个实例分配唯一的 ID: (window.instances = window.instances || []).push(this)
然后检索唯一 ID: window.instances.indexOf(instance)
(例如,在类方法中时为 window.instances.indexOf(this)
)
Programmatically Toggle 以编程方式切换
使用全局布尔值来控制一个或多个条件断点:
然后以编程方式切换布尔值,例如
-
手动,从控制台
javascript1 window.enableBreakpoints = true;
-
从其他断点
-
从控制台上的计时器
javascript1 setTimeout(() => (window.enableBreakpoints = true), 5000);
-
其他方式略...
monitor() class Calls Monitor() 类调用
您可以使用 Chrome 的 monitor
命令行方法轻松跟踪对类方法的所有调用。例如。给定一个类 Dog
javascript
1 class Dog {
2 bark(count) {
3 /* ... */
4 }
5}
如果我们想知道对 Dog
的所有实例进行的所有调用,请将其粘贴到命令行中:
javascript
1 var p = Dog.prototype;
2 Object.getOwnPropertyNames(p).forEach((k) => monitor(p[k]));
你将在控制台中得到输出:
sql
> function bark called with arguments: 2
如果您想暂停任何方法调用的执行(而不是仅仅记录到控制台),可以使用 debug
而不是 monitor
。
From a Specific Instance
如果您不知道该类但有一个实例:
javascript
1 var p = instance.constructor.prototype;
2 Object.getOwnPropertyNames(p).forEach((k) => monitor(p[k]));
当您想编写一个对任何类的任何实例执行此操作的函数(而不仅仅是 Dog
)时很有用
Call and Debug a Function
在控制台中调用要调试的函数之前,请调用 debugger
。例如。给定:
javascript
1 function fn() {
2 /* ... */
3}
php
> debugger; fn(1);
然后"Step into next function call"来调试 fn
的实现。
当您不想查找 fn
的定义并手动添加断点,或者如果 fn
动态绑定到函数并且您不知道源在哪里时,这很有用。
在 Chrome 中,您还可以选择在命令行上调用 debug(fn)
,调试器将在每次调用时暂停 fn
内的执行。
Pause Execution on URL Change
URL 更改时暂停执行
要在单页应用程序修改 URL 之前暂停执行(即发生某些路由事件):
javascript
1 const dbg = () => {
2 debugger;
3 };
4 history.pushState = dbg;
5 history.replaceState = dbg;
6 window.onhashchange = dbg;
7 window.onpopstate = dbg;
创建一个暂停执行而不中断导航的 dbg
版本是留给读者的练习。
另请注意,当代码直接调用 window.location.replace/assign
时,这不会处理,因为页面将在分配后立即卸载,因此无需调试。如果您仍然想查看这些重定向的来源(并调试重定向时的状态),在 Chrome 中您可以 debug
相关方法:
javascript
1 debug(window.location.replace);
2 debug(window.location.assign);
Debugging Property Reads
调试属性读取 如果您有一个对象并且想知道何时读取该对象的属性,请使用带有 debugger
调用的对象 getter。例如,将 {configOption: true}
转换为 {get configOption() { debugger; return true; }}
(在原始源代码中或使用条件断点)。
当您将一些配置选项传递给某些东西并且您想了解它们如何使用时很有用。
Use copy()
您可以使用 copy()
控制台 API 将感兴趣的信息从浏览器直接复制到剪贴板,而无需任何字符串截断。您可能想要复制一些有趣的内容:
- 当前 DOM 的快照:
copy(document.documentElement.outerHTML)
- 有关资源的元数据(例如图像):
copy(performance.getEntriesByType("resource"))
- 一个大的 JSON blob,格式为:
copy(JSON.parse(blob))
- 本地存储的转储:
copy(localStorage)
- 其他...
Debugging HTML/CSS 调试 HTML/CSS
JS 控制台在诊断 HTML/CSS 问题时非常有用。
Inspect the DOM with JS Disabled
在禁用 JS 的情况下检查 DOM
在 DOM 检查器中按 ctrl+\ (Chrome/Windows) 可随时暂停 JS 执行。这允许您检查 DOM 的快照,而不必担心 JS 改变 DOM 或事件(例如鼠标悬停)导致 DOM 从您的下方发生变化。
Inspect an Elusive Element
检查难以捉摸的元素
假设您想要检查仅有条件出现的 DOM 元素。检查所述元素需要将鼠标移动到它,但是当你尝试这样做时,它就会消失:
要检查该元素,您可以将其粘贴到控制台中: setTimeout(function() { debugger; }, 5000);
。这给了你 5 秒的时间来触发 UI,然后一旦 5 秒计时器到了,JS 执行就会暂停,并且没有任何东西会让你的元素消失。您可以自由地将鼠标移动到开发工具而不会丢失该元素:
当 JS 执行暂停时,您可以检查元素、编辑其 CSS、在 JS 控制台中执行命令等。
在检查依赖于特定光标位置、焦点等的 DOM 时很有用。
Record Snapshots of the DOM
要获取当前状态下 DOM 的副本:
javascript
1 copy(document.documentElement.outerHTML);
每秒记录一次 DOM 快照:
javascript
1 doms = [];
2 setInterval(() => {
3 const domStr = document.documentElement.outerHTML;
4 doms.push(domStr);
5 }, 1000);
或者将其打印到控制台:
javascript
1 setInterval(() => {
2 const domStr = document.documentElement.outerHTML;
3 console.log("snapshotting DOM: ", domStr);
4}, 1000);
Monitor Focused Element
javascript
1(function () {2 let last = document.activeElement;3 setInterval(() => {4 if (document.activeElement !== last) {5 last = document.activeElement;6 console.log("Focus changed to: ", last);7 }8 }, 100);9})();
Find Bold Elements
javascript
1 const isBold = (e) => {
2 let w = window.getComputedStyle(e).fontWeight;
3 return w === "bold" || w === "700";
4 };
5 Array.from(document.querySelectorAll("*")).filter(isBold);
Just Descendants
或者只是当前在检查器中选择的元素的后代:
javascript
1 Array.from($0.querySelectorAll("*")).filter(isBold);
Reference Currently Selected Element
控制台中的 $0
是对元素检查器中当前选定元素的自动引用。
Previous Elements
在 Chrome 和 Edge 中,您可以使用 $1
访问上次检查的元素,使用 $2
访问之前的元素,等等。
Get Event Listeners 获取事件监听器
在 Chrome 中,您可以检查当前所选元素的事件侦听器: getEventListeners($0)
,例如
Monitor Events for Element
调试所选元素的所有事件: monitorEvents($0)
调试所选元素的特定事件: monitorEvents($0, ["control", "key"])
- Chrome、Firefox 和 Edge 均支持提示,除非浏览器徽标另有说明:
原文:67 Weird Debugging Tricks Your Browser Doesn't Want You to Know | Alan Norbauer