调试技巧和窍门

Avatar of Sarah Drasner
Sarah Drasner

DigitalOcean 为您的旅程的每个阶段提供云产品。立即开始使用 $200 的免费积分!

编写代码只是成为开发人员的一小部分。为了在工作中高效且有能力,我们还必须擅长调试。当我花时间学习新的调试技能时,我经常发现自己可以更快地行动,并为我所在的团队带来更多价值。我有一些自己非常依赖的技巧和窍门,并且发现我在研讨会中一遍又一遍地给出相同的建议,因此这里整理了一些技巧,以及来自社区的一些技巧。我们将从一些核心原则开始,然后深入探讨更具体的示例。

主要概念

隔离问题

隔离可能是所有调试中最强大的核心原则。我们的代码库可能很庞大,包含不同的库、框架,并且可能包括许多贡献者,甚至包括不再从事该项目的人员。隔离问题有助于我们慢慢剔除问题中不重要的部分,以便我们可以专注于解决方案。

隔离的一些好处包括,但不限于:

  • 弄清楚它是否真的是我们认为的根本原因,还是某种冲突
  • 对于基于时间的任务,了解是否存在竞争条件
  • 认真研究我们的代码是否可以简化,这有助于编写和维护代码
  • 解开它,看看它是一个问题还是更多问题

使问题可重现非常重要。如果没有办法以可以重现的方式准确地确定问题是什么,就很难解决它。这还允许您将其与类似的工作模型进行比较,以便您查看发生了哪些变化或两个模型之间有什么不同。

我在实践中有很多不同的隔离方法。一种是在本地实例、私有 CodePen 或 JSBin 上创建一个简化的测试用例。另一种是在代码中创建断点,以便我可以逐段查看代码的执行情况。有几种方法可以定义断点。

您可以在代码中内联编写 debugger;。您可以看到如何一次触发一小部分代码。

您可以在 Chrome DevTools 中更进一步,甚至逐步执行下一个触发的事件或选择特定的事件监听器。

Step into the next function call

传统的 console.log 是一种隔离形式。(或者 PHP 中的 echo,或 python 中的 print 等等)。您正在获取一小部分执行代码,并测试您的假设,或者检查是否有内容被更改。这可能是最经得起时间考验的调试形式,无论您变得多么先进,它仍然有其用途。ES6 中的箭头函数也允许我们在控制台调试方面更上一层楼,因为现在在控制台中编写有用的单行代码变得容易多了。

console.table 函数也是我最喜欢的工具之一,它特别适合于需要表示大量数据的场景,例如大型数组、大型对象等。console.dir 函数也是一个不错的替代方案。它将记录对象的属性的交互式列表。

console.dir 提供交互式列表

要有条理

当我教授研讨会并帮助我的课堂学生时,我发现他们试图调试问题时最大的障碍是缺乏条理性。这真是一个龟兔赛跑的故事。他们可以理解地想要快速行动,所以他们一次更改了很多东西,然后当某些东西停止工作时,他们不知道他们更改了哪一项内容导致了错误。然后,为了调试,他们一次更改很多东西,并且在试图弄清楚什么有效什么无效时迷失了方向。

我们都在一定程度上这样做。当我们对某个工具越来越熟练时,我们可以编写越来越多的代码而无需测试假设。但是,如果您不熟悉某种语法或技术,那么慢一点、小心一点对您有利。您更有可能撤销自己可能无意中为自己创建的问题。实际上,一旦您创建了一个问题,一次调试一个问题可能看起来更慢,但这确实会暴露发生了哪些变化以及错误到底在哪里,而看似更快的速度则不允许这样做。我说看似,是因为这种方式并没有真正节省时间。

您还记得您小时候,父母说“如果您迷路了,就待在那里”吗? 我的父母至少是这么说的。这是因为如果他们在四处走动寻找我,而我也在四处走动寻找他们,那么我们就更不可能相遇。代码的工作方式相同。活动部件越少越好;您返回一致结果的次数越多,跟踪问题就越容易。因此,在调试时,尽量不要安装任何东西,或者添加新的依赖项。如果您每次都看到不同的错误,而您应该返回静态结果,那么这是一个很大的红色警告信号,您应该带着您的侦探帽直接奔向它。

选择合适的工具

有无数种工具可以解决各种问题。我将介绍一些我认为最有用的工具,然后我们会链接到大量资源。

语法高亮

当然,选择语法高亮主题的最新颜色和口味非常有趣,但是花一些时间考虑这里的清晰度很重要。我经常选择深色主题,其中语法跳跃会使我的所有代码变成更浅的颜色,我发现错误非常容易立即看到。我倾向于喜欢 Oceanic Next 或 Panda,但实际上,每个人都有自己的喜好。重要的是要记住,在寻找好的语法高亮显示器时,外观很棒很好,但最重要的是能够突出显示错误,两者兼得是完全可以做到的。

代码风格检查

代码风格检查有助于标记可疑代码并指出我们可能忽略的错误。代码风格检查非常重要,但是您选择哪个代码风格检查器与您正在使用的语言/框架有很大关系,最重要的是,您的代码风格协议是什么。

不同的公司有不同的代码风格和规则。就我个人而言,我喜欢 AirBnB 的,但要小心,不要随意使用任何代码风格检查器。您的代码风格检查器会强制执行某些模式,如果您自己不想强制执行这些模式,可能会阻止您的构建过程。我曾经使用过一个 CSS 代码风格检查器,它会在每次我编写浏览器 hack 时抱怨,最后我不得不绕过它很多次,以至于它不再有用。但是,好的代码风格检查器可以突出显示您可能错过的潜伏的小错误。
这里有一些资源:

浏览器扩展

扩展非常棒,因为它们可以很容易地启用和禁用,并且可以满足非常具体的需要。如果您使用的是特定库或框架,那么很有可能启用它们在 DevTools 的扩展程序将为您提供无法从其他地方找到的清晰度。但要小心:扩展程序不仅会拖慢浏览器速度,而且它们还拥有执行脚本的权限,因此请对扩展程序的作者、评级和背景做一些功课。综上所述,以下是我最喜欢的扩展程序:

  • 无障碍扩展 来自 Dequeue Systems
  • React DevTools 我认为,如果您正在使用 React,这确实是必不可少的,因为它可以让您看到它们的虚拟 DOM
  • Vue DevTools 与上面的建议相同。
  • Codopen:将您从编辑器模式弹出到 CodePen 的调试窗口。完全公开:我的丈夫给我做了这个作为礼物,因为他受不了看我手动打开调试窗口(有史以来最好的礼物!)。
  • Pageruler:获取像素尺寸并测量页面上的任何内容。我喜欢这个,因为我对我的布局非常非常认真。这有助于我满足这种需求。

DevTools

这可能是最明显的调试工具,您可以用它们做很多事情。它们可能包含许多很容易被忽略的功能,因此在下一节中,我们将深入研究一些我最喜欢的功能。

Umar Hansa 有很好的学习 DevTools 功能的资料。他有一个 每周的新闻简报和 GIF,在最后一节中链接了一个新的课程,以及 我们网站上的一篇文章

我最喜欢的一个最近的例子是这个 CSS Tracker 增强功能,经 Umar 许可后在此显示。这会显示所有未使用的 CSS,以便您可以了解性能影响。

CSS Tracker 显示了用于和未使用集的彩色编码规则。

其他工具

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

具体技巧

我一直对其他人如何进行调试很感兴趣,因此我通过 CSS-Tricks 帐户和我的个人帐户询问了社区他们最喜欢的调试方法。此列表是我喜欢的技巧和社区技巧的汇总。

无障碍

$('body').on('focusin', function() {
  console.log(document.activeElement);
});

这会记录当前聚焦的元素,因为打开 Devtools 会使 activeElement 失焦,这很有用

Marcy Sutton

调试 CSS

我们收到了很多回复,说人们在元素上添加红色边框以查看它们的行为。
https://twitter.com/malchata/status/842029469246324736
我也这样做,我甚至有一个小的 CSS 文件,它会添加一些我可以轻松访问的不同颜色的类。

检查 React 中的状态

感谢迈克尔,这是我所知道的、最有用的调试工具之一。这段代码会将您正在处理的组件的状态“漂亮地打印”到组件上,以便您可以看到正在发生的事情。您可以验证状态是否按预期工作,它还有助于跟踪状态和使用方法之间的任何错误。

动画

我们收到了很多回复,说他们将动画速度降低了很多。

我在 CSS Tricks 上关于 调试 CSS Keyframe 动画 的一篇文章中提到了这一点,还有更多技巧,例如如何进行硬件加速或使用不同百分比的多重变换。

我也会在 JavaScript 中降低动画速度——在 GreenSock 中,它看起来像:timeline.timeScale(0.5)(您可以降低整个时间线的速度,而不仅仅是一次降低一个东西的速度,这非常有用),在 mo.js 中,它看起来像 {speed: 0.5}

Val Head 有一个很棒的视频,介绍了 Chrome 和 Firefox DevTools 在动画方面的功能。

如果您想使用 Chrome DevTools 时间轴进行性能审核,值得一提的是,绘制是最昂贵的任务,因此在所有条件相同的情况下,请更多地关注绿色部分的百分比。

检查不同的连接速度和负载

我倾向于在快速连接上工作,因此我会限制我的连接速度,以检查人们在没有我的互联网速度的情况下性能会如何。

throttle connection in devtools

这在与强制刷新或清空缓存一起使用时也很有用。

设置计时调试器

这个来自 Chris。我们在这里有一篇关于它的文章 就在这里

setTimeout(function() {
  debugger;
}, 3000);

它类似于我之前提到的调试工具,只是您可以将其放在 setTimeout 函数中,并获得更精细的信息。

模拟器

我之前提到了 Eruda 的模拟器。iOS 用户也有一个非常棒的模拟器。我本来要告诉您,您必须先安装 XCode,但这篇推文展示了另一种方法。

Chrome 也有一个设备切换,这很有帮助。

远程调试器

我实际上直到看到这条推文才知道这个工具。非常有用!

CSS 网格调试

Rachel Andrew 在 Smashing 上做了一个演讲,并提到了一个在 Firefox 中可以点击的小华夫饼形状的东西,它会照亮网格中的间隙。她的视频 非常清晰地解释了它。

Rachel Andrew 展示了如何在 Firefox 开发工具中突出显示间隙。

数组调试

Wes Bos 提供了一个非常有用的技巧,用于在一个数组中搜索单个项目

更多调试资源

Jon Kuperman 有一个 Frontend Masters 课程 可以帮助你掌握开发者工具,它与 这个应用 相关。

Code School 上有一个关于 发现开发者工具 的小型课程。

Umar Hansa 推出了一个新的在线课程,叫做 现代开发者工具

Julia Evans 写了一篇很棒的文章 关于调试的文章,感谢 Jamison Dance 向我展示了它。

如果你和我一样超级极客,想深入研究时间轴,那么 Paul Irish 做了一些 使用开发者工具的高级性能审核

最后,我会放一个苦乐参半的资源。我的朋友 James Golick 是一位优秀的程序员,也是一位更优秀的人,多年前他做了这个关于调试任何事物的精彩会议演讲。不幸的是,James 已经离开了,但我们仍然可以纪念他的记忆,并从他那里学习。