【Debug】 你所不知道的各种前端Debug技巧系列 Sources - JavaScript Debugging---第14天

使用JavaScript Debugger 的精髓除了断点、逐步执行外,还有各种列表显示JavaScript 目前的执行状态,以及一些关于Debugger 的设定。

阅读本篇文章时建议搭配Demo页面Sources - JavaScript Debugging,效果更佳。

状态列表

Watch

执行程式码的过程中,若需要不断查看某个变数的值,可以在Watch 列表中新增一条Expression。

加入后每次暂停或逐步执行都会重新执行Watch中的Expression,另外也可以手动按下右方的Refresh watch expressions图示来刷新Expression。

需要注意的就是Expression可能会触发副作用,关于Watch的副作用在Console - Run JavaScript中的Live expression也有提及,当Expression为Function时有副作用较易察觉,但若是藏在物件的Getter中就很可能被忽略了。

Scope

Scope 列表中会显示目前各个Scope 可取得的变数值,JavaScript Debugger 中的Scope 可以简单归类为以下几种:

Local – 目前所在Function scope 宣告的变数
Block – 同一个Block scope(大括弧)宣告的变数
Closure – 目前所在Function 可见的外部Function scope 变数
Script – Global scope宣告的变数(const、let)
Global –可透过window.x取得的属性(var)
以下列程式码为例子,假设目前停在console.log,试着猜猜看a、b、c、d、e在Scope列表中会分别被归类于哪一种Scope:

var a = 'a';
const b = 'b';
function outer() {
  const c = 'c';
  function inner() {
    const d = 'd';
    if (true) {
      const e = 'e';
      console.log(a, b, c, d, e); // 斷點
    }
  }
  inner();
}
outer();

答案在下方,可以在Demo页面看看实际的执行结果,是否和自己的想法一致呢?注意function、var的宣告是属于Function scope,更详细的说明可以参考MDN关于Functions和Block的文件。
在这里插入图片描述
注意变数可能同时属于多种Scope,在Sources面板的Scope列表中会自动归类到其中一种。
答案是Global, Script, Closure, Local, Block

修改变数

双击变数可以修改变数值,比较特别的是Function执行到最后一行的时候Local scope会出现Return value,可以修改Return value的值,甚至Function本身的程式码也可以修改。

另外右键点击Scope列表内的Function会多一个Show function definition选项,可以跳至该Function宣告的位置。
在这里插入图片描述

Call stack

每多执行一层Function,Call stack就会加入一层Function,以下方程式码为例,若在C行加入断点,执行outer后会看到Call stack里面出现hello、world:

function hello() {
  let message = 'Hello'; // A
  function world() {
    message = message + ' World'; // C 斷點
    console.log(message);
  }
  inner(); // B
}

在这里插入图片描述

切换

Call stack内的蓝色箭头会指向显示目前正在观察的Function,点击其他Function如hello可以看到进入world前的状态:
在这里插入图片描述
重新执行
右键点击任意一层可以看到Restart frame选项,点击后会跳至该Function的第一行,以下方程式码为例子,假设目前停在C行,点击Step执行C行后,再点击Restart Frame就会跳至C行之前。
在这里插入图片描述
在Hello后面加了两次World

Console

暂停时可以在Console内执行任意JavaScript,例如修改变数、Console.log等等,可以存取当下Scope内的任意变数。
在这里插入图片描述

Settings

在DevTools的设定中,可以找到Blackboxing和Enable JavScript source maps。

Blackboxing能够blackbox符合特定Pattern的档案,另外勾选Blackbox content scripts则可以Blackbox所有Extension的Content script,不过想要完全避免Extension的干扰,还是开启无痕模式会比较保险。

Preferences > Sources 内可以开关JavaScript 的Source map,预设为开启,也就是自动读取Source map 档案。
在这里插入图片描述

Blackbox script

Debug 时可以把某些程式码加入Blackbox,也就是黑箱作业,当一个档案被Blackbox 后,逐步执行系列就不会跳入该程式码,不过还是有可能经由断点暂停在Blackbox 的程式码中。

Debug 时可以把有把握的档案Blackbox 掉,例如写过完整测试或皆为Pure function 的程式码、第三方套件、Extension 的Content scripts 等等来减少干扰。

在程式码中点击右键就会看到Blackbox script的选项,也可以透过再次点击Stop blackboxing解除。
在这里插入图片描述

Source map

目前越来越多网页的程式码都会经过处理,实际使用时和开发时看到的并不同,而处理过的程式码通常会被压缩,几乎不能用来Debug,因此使用Sources面板进行Debug时常常会需要Source map来映射目前执行的程式码到原始码上,关于Source map更多的介绍可以参考Sources - Files。

Sources面板中也有提供format的功能,点击程式码面板的左下角的Pretty print xxx.js图示会开启另一份经过排版的程式码,名称为xxx.js:formatted,当程式码的格式太过混乱或是想要对别人的程式码做坏事时能大大提升可读性。

也是因此编辑来自Formatted 或Source map 的档案都是无效的,只有修改原始档案并存档才能立即覆写当前程式码的行为。

小结

善用Sources面板的JavaScript Debugging功能可以提升Debug的效率,虽然console.log真的很诱人,也常常是个好方法,但尝试一下Sources面板或许能够改变未来的Debug方式哦。

猜你喜欢

转载自blog.csdn.net/wlcs_6305/article/details/115209376