高级JavaScript调试技巧

在JavaScript调试的领域中,有许多技巧可以帮助开发者更快地定位和解决问题。本文将介绍一些高级调试技巧,这些技巧在Chrome浏览器中特别有用。这些技巧包括条件断点、事件监听断点以及观察对象属性的变化。这些技巧对于处理第三方库或者难以直接调试的代码尤其有效。

条件断点

在前几篇文章中,介绍了如何使用debugger语句设置静态断点。这种方法在可以直接修改测试代码的情况下效果很好。然而,如果需要调试第三方库,那么就需要使用浏览器断点。

第三方库通常包含大量的代码重用。调试时可能会在代码的热点部分设置断点。如果断点被频繁触发,那么误报可能会淹没真正的问题。条件断点可以帮助缓解这个问题。

假设有一个控制器如下:

this.application.on('SOME_EVENT', this.onSomeEvent, this);

期望其他代码会执行:

this.application.fireEvent('SOME_EVENT');

如果回调函数没有被触发,可以在fireEvent方法上设置断点。但这并不是最佳解决方案,因为它可能会被其他代码调用。

首先,右键点击行号,然后选择编辑断点:

// 当表达式返回true时,它将评估为一个正常的断点。如果返回false,则会跳过它。

使用的一种技巧是将数据记录到控制台,这样就可以看到表达式是如何被评估的。在上面的例子中,只是记录了看到的事件。还有其他时候,设置的条件断点在循环中,表达式需要在特定的索引处返回true。如果输出索引和一些数据,就可以看到循环在bug发生时的索引。

另一种技巧是使用全局标志。曾经遇到过这样的情况,希望表达式在第二次返回true,而不是第一次。如果在表达式上添加一个&&,可以通过检查标志来实现它:

eventName === 'SOME_EVENT' && (window.ZG = true);

eventNameSOME_EVENT时,检查全局标志是否已经设置。如果已经设置,那么知道在第二次,需要评估为true。如果没有,那么需要设置它并忽略这个调用。这就是为什么在赋值后面添加了一个&& flag。JavaScript将(window.ZG = true)评估为true。如果不附加false,那么将在第一次得到一个断点。

同样的原理可以应用于开发者有能力修改的代码的条件断点。全局标志需要被容易识别为临时变量。大多数开发者使用他们的首字母来使其突出,这就是为什么选择了ZG作为。根据情况,它们也可以是整数。

事件监听断点(Chrome)

在自下而上的调试中,有些情况下放置调试器很困难。代码可能属于第三方,或者放置调试器的位置可能不明显。大多数这样的情况都围绕着某种用户输入。所有的JavaScript库都有自己的方式来处理用户输入,所以通过阅读代码来找出放置它的位置几乎没有什么洞察力。

Chrome的开发工具在处理用户交互方面提供了一些帮助。事件监听断点面板允许开发者看到哪些代码响应不同的浏览器事件。

要查看面板,请打开Dev Tools,转到Source,然后在右侧展开事件监听断点:

如果程序员看到用户点击时出现bug,他们可以展开Mouse部分,并监听mouseup和click。大多数JavaScript框架会监听这些事件中的一个,并在触发时触发回调。如果bug发生在按下键之后,keyup是最常监听的事件。

有些情况下使用这些断点非常困难。如果在一个框架期望mousedown然后mouseup在一定时间框架内设置断点,那么观察bug的努力就让它没有出现。条件断点可以通过允许开发者切换这些事件来确保bug仍然可以重现。

JavaScript中的成员变量和方法本质上是public的。JavaScript没有protected或private变量或方法的概念。这可能导致一些难以追踪的bug,因为可能没有使用getter和setter。这通常发生在一个类意外地更新了另一个类的private成员变量而没有通过setter时。

要观察对象属性何时变化,可以为对象显式定义getter和setter:

constructor: function() { this.myObject = { someInt: 1 }; var someInt = this.myObject.someInt; this.myObject.__defineSetter__('someInt', function(sI) { debugger; someInt = si; return someInt; }); this.myObject.__defineGetter__('someInt', function() { return someInt; }); }

this.myObject.someInt被改变时,debugger语句可以在调用栈中显示哪个类正在更新该值。这是一个快速隔离忽略private/protected文档的违规类的方法。

如果违规类将this.myObject设置为一个新对象,那么setter将不会被调用。在这种情况下,可以在this上设置一个getter/setter来观察myObject键的变化。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485