编写代码只是成为开发人员的一小部分。为了在工作中高效且有能力,我们还必须擅长调试。当我花时间学习新的调试技能时,我经常发现自己可以更快地行动,并为我所在的团队带来更多价值。我有一些自己非常依赖的技巧和窍门,并且发现我在研讨会中一遍又一遍地给出相同的建议,因此这里整理了一些技巧,以及来自社区的一些技巧。我们将从一些核心原则开始,然后深入探讨更具体的示例。
主要概念
隔离问题
隔离可能是所有调试中最强大的核心原则。我们的代码库可能很庞大,包含不同的库、框架,并且可能包括许多贡献者,甚至包括不再从事该项目的人员。隔离问题有助于我们慢慢剔除问题中不重要的部分,以便我们可以专注于解决方案。
隔离的一些好处包括,但不限于:
- 弄清楚它是否真的是我们认为的根本原因,还是某种冲突
- 对于基于时间的任务,了解是否存在竞争条件
- 认真研究我们的代码是否可以简化,这有助于编写和维护代码
- 解开它,看看它是一个问题还是更多问题
使问题可重现非常重要。如果没有办法以可以重现的方式准确地确定问题是什么,就很难解决它。这还允许您将其与类似的工作模型进行比较,以便您查看发生了哪些变化或两个模型之间有什么不同。
我在实践中有很多不同的隔离方法。一种是在本地实例、私有 CodePen 或 JSBin 上创建一个简化的测试用例。另一种是在代码中创建断点,以便我可以逐段查看代码的执行情况。有几种方法可以定义断点。
您可以在代码中内联编写 debugger;
。您可以看到如何一次触发一小部分代码。
您可以在 Chrome DevTools 中更进一步,甚至逐步执行下一个触发的事件或选择特定的事件监听器。

传统的 console.log
是一种隔离形式。(或者 PHP 中的 echo
,或 python 中的 print
等等)。您正在获取一小部分执行代码,并测试您的假设,或者检查是否有内容被更改。这可能是最经得起时间考验的调试形式,无论您变得多么先进,它仍然有其用途。ES6 中的箭头函数也允许我们在控制台调试方面更上一层楼,因为现在在控制台中编写有用的单行代码变得容易多了。
console.table
函数也是我最喜欢的工具之一,它特别适合于需要表示大量数据的场景,例如大型数组、大型对象等。console.dir
函数也是一个不错的替代方案。它将记录对象的属性的交互式列表。

要有条理
当我教授研讨会并帮助我的课堂学生时,我发现他们试图调试问题时最大的障碍是缺乏条理性。这真是一个龟兔赛跑的故事。他们可以理解地想要快速行动,所以他们一次更改了很多东西,然后当某些东西停止工作时,他们不知道他们更改了哪一项内容导致了错误。然后,为了调试,他们一次更改很多东西,并且在试图弄清楚什么有效什么无效时迷失了方向。
我们都在一定程度上这样做。当我们对某个工具越来越熟练时,我们可以编写越来越多的代码而无需测试假设。但是,如果您不熟悉某种语法或技术,那么慢一点、小心一点对您有利。您更有可能撤销自己可能无意中为自己创建的问题。实际上,一旦您创建了一个问题,一次调试一个问题可能看起来更慢,但这确实会暴露发生了哪些变化以及错误到底在哪里,而看似更快的速度则不允许这样做。我说看似,是因为这种方式并没有真正节省时间。
您还记得您小时候,父母说“如果您迷路了,就待在那里”吗? 我的父母至少是这么说的。这是因为如果他们在四处走动寻找我,而我也在四处走动寻找他们,那么我们就更不可能相遇。代码的工作方式相同。活动部件越少越好;您返回一致结果的次数越多,跟踪问题就越容易。因此,在调试时,尽量不要安装任何东西,或者添加新的依赖项。如果您每次都看到不同的错误,而您应该返回静态结果,那么这是一个很大的红色警告信号,您应该带着您的侦探帽直接奔向它。
选择合适的工具
有无数种工具可以解决各种问题。我将介绍一些我认为最有用的工具,然后我们会链接到大量资源。
语法高亮
当然,选择语法高亮主题的最新颜色和口味非常有趣,但是花一些时间考虑这里的清晰度很重要。我经常选择深色主题,其中语法跳跃会使我的所有代码变成更浅的颜色,我发现错误非常容易立即看到。我倾向于喜欢 Oceanic Next 或 Panda,但实际上,每个人都有自己的喜好。重要的是要记住,在寻找好的语法高亮显示器时,外观很棒很好,但最重要的是能够突出显示错误,两者兼得是完全可以做到的。
代码风格检查
代码风格检查有助于标记可疑代码并指出我们可能忽略的错误。代码风格检查非常重要,但是您选择哪个代码风格检查器与您正在使用的语言/框架有很大关系,最重要的是,您的代码风格协议是什么。
不同的公司有不同的代码风格和规则。就我个人而言,我喜欢 AirBnB 的,但要小心,不要随意使用任何代码风格检查器。您的代码风格检查器会强制执行某些模式,如果您自己不想强制执行这些模式,可能会阻止您的构建过程。我曾经使用过一个 CSS 代码风格检查器,它会在每次我编写浏览器 hack 时抱怨,最后我不得不绕过它很多次,以至于它不再有用。但是,好的代码风格检查器可以突出显示您可能错过的潜伏的小错误。
这里有一些资源:
- 我最近发现了 这个响应式图片代码风格检查器,它会告诉您可能有哪些机会可以使用 picture、srcset 或 sizes。
- 这是一个 相当不错的 JS 代码风格检查器分解
浏览器扩展
扩展非常棒,因为它们可以很容易地启用和禁用,并且可以满足非常具体的需要。如果您使用的是特定库或框架,那么很有可能启用它们在 DevTools 的扩展程序将为您提供无法从其他地方找到的清晰度。但要小心:扩展程序不仅会拖慢浏览器速度,而且它们还拥有执行脚本的权限,因此请对扩展程序的作者、评级和背景做一些功课。综上所述,以下是我最喜欢的扩展程序:
- 无障碍扩展 来自 Dequeue Systems
- React DevTools 我认为,如果您正在使用 React,这确实是必不可少的,因为它可以让您看到它们的虚拟 DOM
- Vue DevTools 与上面的建议相同。
- Codopen:将您从编辑器模式弹出到 CodePen 的调试窗口。完全公开:我的丈夫给我做了这个作为礼物,因为他受不了看我手动打开调试窗口(有史以来最好的礼物!)。
- Pageruler:获取像素尺寸并测量页面上的任何内容。我喜欢这个,因为我对我的布局非常非常认真。这有助于我满足这种需求。
DevTools
这可能是最明显的调试工具,您可以用它们做很多事情。它们可能包含许多很容易被忽略的功能,因此在下一节中,我们将深入研究一些我最喜欢的功能。
Umar Hansa 有很好的学习 DevTools 功能的资料。他有一个 每周的新闻简报和 GIF,在最后一节中链接了一个新的课程,以及 我们网站上的一篇文章。
我最喜欢的一个最近的例子是这个 CSS Tracker 增强功能,经 Umar 许可后在此显示。这会显示所有未使用的 CSS,以便您可以了解性能影响。

其他工具
- What input 是一个用于跟踪当前输入方法(鼠标、键盘或触摸)以及当前意图的全局实用程序——这对于跟踪无障碍漏洞非常有用(感谢无障碍专家 Marcy Sutton 的提示)。
- Ghostlabapp 是一个非常漂亮的工具,如果您正在进行响应式开发或检查跨大量设备部署的任何内容。它提供同步的 Web 开发、测试和检查。
- Eruda 是一个很棒的工具,可以帮助在移动设备上进行调试。我真的很喜欢它,因为它将模拟器更进一步,提供了一个控制台和真正的 DevTools 来帮助您理解。

具体技巧
我一直对其他人如何进行调试很感兴趣,因此我通过 CSS-Tricks 帐户和我的个人帐户询问了社区他们最喜欢的调试方法。此列表是我喜欢的技巧和社区技巧的汇总。
无障碍
$('body').on('focusin', function() {
console.log(document.activeElement);
});
这会记录当前聚焦的元素,因为打开 Devtools 会使 activeElement 失焦,这很有用
调试 CSS
我们收到了很多回复,说人们在元素上添加红色边框以查看它们的行为。
https://twitter.com/malchata/status/842029469246324736
我也这样做,我甚至有一个小的 CSS 文件,它会添加一些我可以轻松访问的不同颜色的类。
检查 React 中的状态
@sarah_edo <pre>{JSON.stringify(this.state, null, 2)}</pre>
— MICHAEL JACKSON (@mjackson) 2017 年 3 月 15 日
感谢迈克尔,这是我所知道的、最有用的调试工具之一。这段代码会将您正在处理的组件的状态“漂亮地打印”到组件上,以便您可以看到正在发生的事情。您可以验证状态是否按预期工作,它还有助于跟踪状态和使用方法之间的任何错误。
动画
我们收到了很多回复,说他们将动画速度降低了很多。
@sarah_edo @Real_CSS_Tricks * { animation-duration: 10s !important; }
— Thomas Fuchs (@thomasfuchs) 2017 年 3 月 15 日
我在 CSS Tricks 上关于 调试 CSS Keyframe 动画 的一篇文章中提到了这一点,还有更多技巧,例如如何进行硬件加速或使用不同百分比的多重变换。
我也会在 JavaScript 中降低动画速度——在 GreenSock 中,它看起来像:timeline.timeScale(0.5)
(您可以降低整个时间线的速度,而不仅仅是一次降低一个东西的速度,这非常有用),在 mo.js 中,它看起来像 {speed: 0.5}
。
Val Head 有一个很棒的视频,介绍了 Chrome 和 Firefox DevTools 在动画方面的功能。
如果您想使用 Chrome DevTools 时间轴进行性能审核,值得一提的是,绘制是最昂贵的任务,因此在所有条件相同的情况下,请更多地关注绿色部分的百分比。
检查不同的连接速度和负载
我倾向于在快速连接上工作,因此我会限制我的连接速度,以检查人们在没有我的互联网速度的情况下性能会如何。

这在与强制刷新或清空缓存一起使用时也很有用。
@sarah_edo 不是很秘密的技巧。但很多人还不知道。您需要打开 DevTools,然后右键单击刷新按钮。pic.twitter.com/FdAfF9Xtxm
— David Corbacho (@dcorbacho) 2017 年 3 月 15 日
设置计时调试器
这个来自 Chris。我们在这里有一篇关于它的文章 就在这里
setTimeout(function() {
debugger;
}, 3000);
它类似于我之前提到的调试工具,只是您可以将其放在 setTimeout 函数中,并获得更精细的信息。
模拟器
@Real_CSS_Tricks 只是为了确保任何 Mac 用户都知道这一点,iOS 模拟器 + Safari 很棒。pic.twitter.com/Uz4XO3e6uD
— Chris Coyier (@chriscoyier) 2017 年 3 月 15 日
我之前提到了 Eruda 的模拟器。iOS 用户也有一个非常棒的模拟器。我本来要告诉您,您必须先安装 XCode,但这篇推文展示了另一种方法。
@chriscoyier @Real_CSS_Tricks 或者,如果您不想费心安装 XCode,您可以使用这种方法:https://#/WtAnZNo718
— Chris Harrison (@cdharrison) 2017 年 3 月 15 日
Chrome 也有一个设备切换,这很有帮助。
远程调试器
@chriscoyier @Real_CSS_Tricks https://#/q3OfWKNlUo 是一个好工具。
— Gilles 💾⚽ (@gfra54) 2017 年 3 月 15 日
我实际上直到看到这条推文才知道这个工具。非常有用!
CSS 网格调试
Rachel Andrew 在 Smashing 上做了一个演讲,并提到了一个在 Firefox 中可以点击的小华夫饼形状的东西,它会照亮网格中的间隙。她的视频 非常清晰地解释了它。

数组调试
Wes Bos 提供了一个非常有用的技巧,用于在一个数组中搜索单个项目
如果你只是在寻找一个单一的数组项目,那么 array.find() 很棒 https://#/AuRtyFwnq7
— Wes Bos (@wesbos) 2017 年 3 月 15 日
更多调试资源
Jon Kuperman 有一个 Frontend Masters 课程 可以帮助你掌握开发者工具,它与 这个应用 相关。
Code School 上有一个关于 发现开发者工具 的小型课程。
Umar Hansa 推出了一个新的在线课程,叫做 现代开发者工具。
Julia Evans 写了一篇很棒的文章 关于调试的文章,感谢 Jamison Dance 向我展示了它。
如果你和我一样超级极客,想深入研究时间轴,那么 Paul Irish 做了一些 使用开发者工具的高级性能审核。
最后,我会放一个苦乐参半的资源。我的朋友 James Golick 是一位优秀的程序员,也是一位更优秀的人,多年前他做了这个关于调试任何事物的精彩会议演讲。不幸的是,James 已经离开了,但我们仍然可以纪念他的记忆,并从他那里学习。
对于调试 CSS,我之前找到过这个扩展。发现它非常有用。Chrome 的 Pesticide。在元素上添加彩色边框,这样你就能看到它们都在哪里。
https://chrome.google.com/webstore/detail/pesticide-for-chrome/bblbgcheenepgnnajgfpiicnbbdmmooh
嗨 Keith,不错的扩展。
我的一位同事写了这个:https://github.com/srambach/classbxr
它不是一个扩展,但它做同样的事情,而且它还显示类名。
你在文章中提到了一个 React 调试器,所以我想我也会抛出一个用于 Angular 的调试器——Augury。这是一个 Chrome 扩展,可以帮助调试 Angular 应用程序。它唯一的缺点是它仅限于 Chrome。
很棒的文章 Sarah!我发现开发者会忽略开发者工具的力量。当然,它已经走了很长一段路,但我发现它是调试的第一个步骤,检测烟雾——在火灾之前。而且所有人都在使用实际的浏览器,但不知何故,从未选择过 opt-cmd i. ;)
添加了在将 Android 手机与 Chrome 开发者工具连接时进行远程调试的想法,以查看实际的移动问题,这仅仅是在台式机上进行节流和设备工具栏操作之外的一步。
使用真正的边框进行 CSS 调试可能是一个问题,因为边框有宽度,因此可能会影响布局。
基本上,我使用一个假的边框,要么使用轮廓,要么使用盒子阴影。它们的好处是它们不会影响其他布局,只是给目标元素一个高亮。
你可以使用盒模型来解决这个问题
这些技巧对我有很大帮助,感谢分享!
谢谢 Sarah!
很多有见地的想法。
向社区寻求帮助的想法非常棒。
调试任何类似 C 的语言(如 JavaScript)的最强大工具之一是使用断言。事实上,Eiffel 语言的开发在很大程度上是为了使断言(在 Eiffel 中称为契约)成为语言的核心功能。
一个好的、简单的断言函数示例 在这里 给出。典型的用法是(如果没有使用 TypeScript)检查传递给函数的参数类型。通过检查你的假设是否有效,你可以发现假设无效的情况,而不是等到问题变得可见。
这难道不只是单元测试吗?
cu,w0lf。
附录:或者可能是经典的 A/B 测试?
cu,w0lf。
单元测试只是一个通用的术语,用于测试模块以确保其正常工作,通常在编码完成后进行。断言是在代码中编写的,以预测可能的故障点,并确保故障不会发生,或者如果发生,则在早期捕获它。通常,断言代码被编写为在生产中不执行任何操作,并且仅在测试环境中执行。因此,断言代码始终保留在适当的位置。这意味着,如果将来的某些修改破坏了假设,则会捕获错误。
人们使用开发者工具的最大问题是他们不知道如何获得想要的结果。是的,你可以设置断点,但这如何使修复 bug 变得更容易?
我设置了一个断点并重新加载了页面。现在呢?哪个按钮可以使事情发生?所有这些信息如何帮助我修复 bug?人们知道一些工具的存在,但它们太复杂了,所以大多数人使用 console.log 调试代替。
如果你不知道它们是如何协同工作的,就很难应用不同的功能。我写了一些关于如何使用开发者工具逐步解决一些真实的 bug 的示例,展示了所有这些是如何协同工作的,希望这能让大家更容易理解如何使用它来解决自己的问题。
https://codeutopia.net/blog/2015/11/01/how-to-fix-javascript-errors-more-easily-with-chromes-debugger/
Jani,这是一篇很棒的开发者工具入门文章,我希望几年前我就读过它!;)
对于 CSS,我过去一直使用边框,但越来越多地使用轮廓来代替它,因为它不会在盒模型中添加像素。不过,它也有一个小问题,那就是它并不总是显示在所有边缘,具体取决于显示类型和其他玄学,就我所知。
另一个读者可能觉得有用的资源。大约一年前,我写下了我的 CSS 调试方法。https://benfrain.com/debugging-css/
分享了很多相同的想法,特别是在隔离和复制方面。
那里也有指向俄语和中文版本的链接。:)
必备工具… http://www.sprymedia.co.uk/article/visual+event+2
在测试https://crossbrowsertesting.com/的网页应用程序(对于某些浏览器-设备组合)时,有一个调试按钮可以打开开发者工具 ️
完全没有提到源映射吗?
我们生活在一个代码被各种预处理器和编译器多次编译/合并/压缩/混淆的时代。 不使用源映射来访问原始源代码/行号,将使隔离任何问题变得非常困难。 即使使用这里提到的所有工具。
例如,Webpack 有一个
devtool
选项来启用源映射。https://webpack.js.cn/configuration/devtool/
单独的加载程序也有选项,可以在代码被它们处理后创建源映射。
https://github.com/postcss/postcss-loader#sourcemaps
https://github.com/webpack-contrib/sass-loader#source-maps
另一个提示,对于生产代码,我们使用像Sentry这样的错误跟踪服务。 这些服务记录并通知您用户捕获到的任何问题。 以及错误详细信息,例如堆栈跟踪、浏览器版本、页面 URL 等。
另一个选择是TrackJS。 也很有用。 这些东西就像错误的 Google Analytics。