45

一、设置断点

断点类型 使用场景
debugger 在js文件中,手动输入代码debugger;,当js文件运行时,会在此处暂停
行断点 知道代码执行的区域,手动在某一行代码处设置断点
满足条件的行断点 知道代码执行的区域,手动在某一行代码处设置断点,但是只在满足某些条件下才会暂停
DOM断点 改变、删除一个DOM节点,或者删除这个DOM节点的子元素时设置断点
XHR断点 XHR URL包含某一字符串时设置断点
事件监听器断点 触发某些事件时设置断点
抛出异常断点 抛出异常时设置断点

debugger

开发环境下:在js源文件中,想在某个地方设置断点以查看后续代码的执行情况,手动在此处输入代码debugger;,js文件运行的时候会在此处暂停。

行断点

当开发者知道要在代码的哪个地方打断点时,设置行断点调试。DevTools总是在这行代码执行之前暂停。
行断点设置的方法:

  1. 切换到Sources面板

  2. 打开想要调试的js文件

  3. 找到代码所在的行

  4. 这行代码的左侧有一个数字,这个数字代表着这行代码在js文件中所在的行数。点击这个数字,会出现一个蓝色的图标,表示断点已经设置好。

clipboard.png

满足条件的行断点

和行断点一样,但是只有在某一条件为真时,DevTools才会在这行代码之前暂停。
设置方法:

  1. 切换到Sources面板

  2. 打开想要调试的js文件

  3. 找到代码所在的行

  4. 这行代码的左侧有一个数字,这个数字代表着这行代码在js文件中所在的行数,右击这个数字

  5. 选择 Add conditional breakpoint,出现一个输入框

  6. 在输入框中输入条件表达式

  7. Enter键激活此断点,当条件表达式为真时,DevTools会在这行代码执行之前暂停(条件性行断点的颜色为橙色)

clipboard.png

管理行断点

设置的很多行断点可以在Breakpoints小窗口做统一管理。

  • 不勾选某一复选框,使对应断点处于“失效”状态,反之亦然

  • 右键可以删除当前断点、删除所有断点、停用断点等,或者全部(不)勾选复选框使所有的断点(不)“生效”

  • 停用断点(Deactivate breakpoints)的意思是:告知DevTools忽略所有的行断点,但是同时保持那些断点的状态,当激活断点(Activate breakpoints)时,这些断点可以继续起作用

clipboard.png

DOM断点

当改变一个节点或者其子元素时,可以设置一个DOM断点:

  1. 点击Elements面板

  2. 找到想要设置断点的元素

  3. 在此元素上右键

  4. Break on --> Subtree modifications / Attribute modifications / Node removal

clipboard.png

Subtree modifications(子树修改):当前选中的元素,删除、增加其子代或者改变其子代的内容。修改子元素的属性或者当前选中元素有任何改变都不会触发此类型断点
Attributes modifications(属性修改):当前选中的元素,增加、删除其属性,或者修改某个属性值
Node Removal(节点移除):移除当前选中的元素

XHR断点

当XHR的请求URL包含某一特定的字符串时,可以暂停调试代码。DevTools会在XHR调用send()那行代码的地方暂停。

  1. 点击Sources面板

  2. 展开XHR Breakpoints小窗口

  3. 点击“增加断点(Add breakpoint)”

  4. 输入一个字符串,只要在某个XHR的请求URL中包含此字符串, DevTools会暂停

  5. Enter键确认

图片描述

事件监听器断点

这个断点类型也算是比较常用的一个了,特别是当我们调试别人的代码时,触发某个事件,想找到对应的代码。事件类型可以是很具体的,比如click事件,也可以是某一类别的事件,比如“鼠标事件”。

  1. 点击Sources面板

  2. 展开Event Listener Breakpoints小窗口

  3. 勾选某一类别的事件或者是某一具体的事件

clipboard.png

抛出异常断点

当代码抛出一个捕获的或者未捕获的异常时,可以设置此类型断点在代码抛出异常的地方暂停。

  1. 点击Sources面板

  2. 点击Pause on exceptions按钮,激活时按钮变成蓝色

  3. (可选)勾选Pause On Caught Exceptions表示只在捕获的异常处暂停,未捕获的异常不考虑

clipboard.png

二、JS Debugging

设置断点暂停代码

设置一个断点使代码在执行的过程中暂停,以便进一步地调试代码。

调试代码

跳过某个函数(Step over)

当在某行代码暂停时,且此行代码包含某个函数,这个函数与我们调试的bug又没有关系,此时可以点击Step over图标直接进入下一行代码(函数正常执行,但DevTools不会进入到函数中去逐行调试代码)。

clipboard.png

举例,假设正在调试以下代码:

function updateHeader() {  
  var day = new Date().getDay();  
  var name = getName(); // A  
  updateName(name); // D
}
function getName() {
  var name = app.first + ' ' + app.last; // B
  return name; // C
}

当在A处暂停时,点击Step over图标,DevTools会执行getName函数里面的所有代码,即B和C(但不在B、C处暂停),然后会在下一行代码D处暂停。

按照代码实际执行的顺序调试(Step into)

当在某行代码暂停时,且此行代码包含某个函数,这个函数与我们调试的bug又有关系,此时可以按Step into图标进入到这个函数中做进一步的调试。

clipboard.png

还以下面的代码举例:

function updateHeader() {  
  var day = new Date().getDay();  
  var name = getName(); // A  
  updateName(name); // D
}
function getName() {
  var name = app.first + ' ' + app.last; // B
  return name; // C
}

当在A处暂停时,点击Step into按钮,DevTools会执行这行代码,然后在B处暂停。

跳出某个函数(Step out)

当在某个函数内部暂停时,如果确认函数剩余的代码与bug无关时,可以按Step out图标让DevTools执行函数剩下的代码,然后跳出函数。
clipboard.png

以下面的代码举例:

function updateHeader() {  
  var day = new Date().getDay();  
  var name = getName();  
  updateName(name); // C
}
function getName() {
  var name = app.first + ' ' + app.last; // A
  return name; // B
}

当在A处暂停时,点击Step out图标,DevTools会执行函数getName()剩余的代码即B,然后在C处暂停。

继续执行脚本

代码暂停之后,点击Resume Script Execution图标可以让代码继续执行。DevTools会继续执行代码直到碰到下一个断点处暂停,如果后面没有断点,脚本就一直执行到结束。

clipboard.png

如果想忽略后面所有的断点,强制代码一直执行,可以点击Resume Script Execution图标不松直到出现Force script execution图标,然后把鼠标移动到这个图标上即可。

clipboard.png

重新执行调用栈的top函数

当在某行代码暂停时,在调用栈窗口(Call Stack)的任意地方右键选择Restart Frame,DevTools会在调用栈top函数的第一行代码处暂停。top函数就是指最后一个被调用的函数,在调用栈中位于最上面,所以叫top函数。

clipboard.png

以下面的代码举例:

function factorial(n) {
  var product = 0; // B
  for (var i = 1; i <= n; i++) {
    product += i;
  }
  return product; // A
}

当在A处暂停时,点击Restart Frame之后,代码会在B暂停,即使没有在B处设置断点。

查看、编辑

当代码暂停时,可以在Scope窗口查看、编辑某些属性值和变量值,这些属性和变量按照作用域又分属在不同的地方,如局部作用域内、闭包内或者全局作用域内。双击值即可修改。
clipboard.png

提示: 代码不在暂停状态时,Scope窗口里面是空的

查看当前的调用栈

代码暂停时,可以在Call Stack窗口查看当前的调用栈。如果有异步调用的代码,勾选上Async复选框使异步调用函数也出现在调用栈中。
clipboard.png

以上图为例:
onClick调用inputsAreEmpty inputsAreEmpty调用getNumber1,getNumber1top函数。
DevTools当前高亮的代码属于蓝色箭头指向的inputsAreEmpty函数,而高亮的这一行正是getNumber1函数被调用的位置。
提示: 代码不在暂停状态时,Call Stack窗口里面是空的

忽略某个脚本文件

在调试的过程中,经常会碰到第三方的库(如jQuery)或者框架,通常情况下,我们的bug不是由这些库或者框架的代码引起的,但是调试的过程中又不可避免地会进入到这些代码中,不胜其烦。这时,我们可以使用DevTools的黑盒功能,把这些三方脚本文件放到黑盒中,这样,调试的过程中就不会进入到这些脚本中去了,Call Stack窗口也不会显示和这些脚本相关的调用关系。
把一个js文件放入黑盒有三种方式:

在编辑器窗口

  1. 打开对应的js文件

  2. 在编辑器窗口的任意地方右键

  3. 选择Blackbox script

clipboard.png

在调用栈窗口

  1. 在属于这个脚本的某个函数上右键

  2. 选择Blackbox script
    clipboard.png

在DevTools设置里面

  1. 打开设置

  2. 切换到Blackboxing选项

  3. 点击Add pattern

  4. 输入脚本的文件名或者是文件名的正则表达式

  5. 点击Add

clipboard.png

提示:也可以在这里统一管理黑盒中的所有脚本文件

使用Watch窗口观察表达式值的变化

clipboard.png

  1. 点击Add Expression按钮添加一个新的表达式去观察

  2. 点击Refresh按钮刷新当前所有表达式的值。调试的过程中,这些表达式的值是自动变化的

  3. 把鼠标悬浮在一个表达式上面然后点击Delete watch expression删除一个表达式

  4. Watch窗口右键也可以进行添加、删除表达式操作

改变压缩文件的可读性

点击Format

clipboard.png

编辑脚本文件

修复bug的过程中,我们会经常改变某些代码然后查看效果。对于一些小的改动,没必要去在源文件改然后重新加载页面查看效果,我们可以直接在DevTools中修改。

  1. Sources面板打开对应的文件

  2. 在编辑器窗口直接修改

  3. Command+S(Mac)或者Ctrl+S保存修改,DevTools会重新编译脚本。继续在页面上进行某些操作,比如点击事件,就可以看到修改代码的效果了。


无名小贝勒
5.7k 声望324 粉丝