您的位置:首页 > Web前端 > JavaScript

js调试学习总结2

2016-07-25 18:28 399 查看

js调试系列 断点与动态调试[基础篇]

http://www.jb51.net/article/51233.htm

上几篇文章已经为大家介绍了js调试系列的一些基础知识,支持乱码兄弟为大家带来了js断点与动态调

试方法,需要的朋友可以参考下

上几篇文章已经为大家介绍了js调试系列的一些基础知识,这次乱码兄弟为大家带来了js断点与动态调

试方法,需要的朋友可以参考下

昨天留的课后练习 1. 分析 votePost 函数是如何实现 推荐 的。

其实我们已经看到了源码,只要读下源码即可知道他是怎么实现的了。

function votePost(n, t, i) { 

 i || (i = !1); 

 var r = { 

  blogApp: currentBlogApp, 

  postId: n, 

  voteType: t, 

  isAbandoned: i 

 }; 

 $("#digg_tips").css("color", "red").html("提交中..."); 

 $.ajax({ 

  url: "/mvc/vote/VoteBlogPost.aspx", 

  type: "post", 

  dataType: "json", 

  contentType: "application/json; charset=utf-8", 

  data: JSON.stringify(r), 

  success: function(n) { 

   if (n.IsSuccess) { 

    var i = $("#" + t.toLowerCase() + "_count"); 

    r.isAbandoned ? $(i).html(parseInt($(i).html()) - 1) : $(i).html(parseInt($(i).html()) 

+ 1) 

   } 

   $("#digg_tips").html(n.Message) 

  }, 

  error: function(n) { 

   n.status > 0 && (n.status == 500 ? $("#digg_tips").html("抱歉!发生了错误!麻烦反馈至

contact@cnblogs.com") : $("#digg_tips").html(n.responseText)) 

  } 

 }); 
}

差不多就这个样子的。

ps: 我用的是 sublime text 格式化的代码,和chrome控制台格式化后的结果有点不同。

也可以试试这个在线格式化工具,效果差不多:Online JavaScript beautifier 

简单读过代码后,可以大致知道,这个函数有 3 个参数,第一个是 postId,就是文章ID,第二个是 推

荐(digg) 或者 反对(bury),

但是第三个一直没用到,而且默认值是 false

往下看,他在 #digg_tips 处显示 "提交中..." 字符串,接着通过 ajax 提交数据给后台。

返回数据后,如果 n.IsSuccess 是 真 就在对应的 喜欢(#digg_count)或反对(#bury_count)的计数id

上 +1,

不过这里看到如果 isAbandoned 的值是 真 的话,就计数 -1。

那我们可以猜测第三个参数是撤销推荐或者反对用的,简单说就是我点了推荐,但是我现在不想推荐了

,可以传递第三个参数 true 实现取消推荐的作用。

我们稍后测试下。

接着是在 #digg_tips 处显示服务器返回的 n.Message 信息。

如果 ajax 发生错误,是 500 错误就提示 "抱歉!发生了错误!麻烦反馈至contact@cnblogs.com" 其

他状态直接提示服务器返回的错误信息。

这就是大致的流程,因为这个函数简单,所以基本上一眼就看出来了。

可能有的新人朋友问了,你怎么知道 currentBlogApp, n, t ,i 是什么值呢?

那我们来进行下一步,动态调试好了。对于编译过的项目,动态调试是非常有用的手段。

先定位到 votePost 源码处,(这个昨天说过了,不太懂的话,再回去看看先。)

so easy,我们就定位到了源码。

接下来我们点下92那个数字,进行下断点操作。

为什么不是在91行下断点呢?

因为91行是函数声明部分,没法下断点,我们在函数要执行的代码处下断点才行。

看到 91 行的行号变成蓝色了,表示这个地方已经下了断点了。同时,我们可以在右侧 Breakpoints 一

栏里看到已下的断点。

Breakpoints 这个一栏是管理所有断点的,可以方便的跳转到对应断点的位置出,以后常常会用到哦。

现在下完断点了,我们回头点下 推荐。。(虽然感觉我在骗推荐,不过我真心没这么想,当初是随便找

了个按钮当练习的。)

当你点 推荐 按钮的时候,神奇的事情发生了,并没有运行推荐功能,而是跳到了控制台 Sources 面板

里我们刚刚下的那个断点处。

现在,你不仅能在右侧 Scope Variables(变量作用域) 一栏处看到当前变量,而且还能把鼠标直接移到

任意变量上,就可以查看该变量的值。

Scope Variables栏目会显示当前作用域以及他的父级作用域,以及闭包。

是不是超方便。。(我初学闭包的时候,Scope Variables帮了我不少呢。)

我们进行下一步,按3次 F10 就可以看到这样的东西。

我们每按一次 F10 会执行一条语句,刚才按了3次,就是执行到了  $("#digg_tips").css("color", 

"red").html("提交中..."); 

所以我们可以在页面上看到 #digg_tips 显示提交中的字样。

可是当我们再次按 F10 的时候,发现他一路执行下去,而没有进入 ajax 内部的回调函数。

这是个纠结的问题,也是我要重点说的。

像这种回调函数,特别是异步的,我们要在回调函数内部再次下一个断点。

所以我们在 96 行再下个断点即可,现在我们再点一下 推荐 依然停在了 92 行,我们直接按 F8 就可

以在 ajax 的回调函数处断下了。

现在,我们就可以调试回调数据了,同时可以发现右侧 Scope Variables 多了一个 Closure 的东西,

这个就是闭包。

如果现在理解不了,那就过,这东西要大篇幅介绍,不是三言两句就能讲明白的,反正控制台很强大就

对了。

在看到闭包的同时,我们也看到 ajax 的返回数据 n,很明显,我的 IsSuccess 属性为 false 没有成

功,因为他返回了一个信息 "不能推荐自己的内容"。

是不是很有意思,动态调试,让寻找BUG变得 so easy。

接下来,我们来实验第三个参数。

我们在控制台输入  votePost(cb_entryId, 'Digg', true);  然后回车。

同样停在了92行的断点处,这个里就不调试了,直接F8进入 ajax 的回调函数出。

在这里我们非常清楚的看到,当第三个参数为 true 的时候,确实是取消推荐了,同时你可以看到推荐

数确实 -1 了,哪怕刷新也一样。

本次我们用到了两个快捷键 F10 和 F8,明天详细介绍,今天先学会基础调试先。

课后练习:(提高下难度)

1. 查看下面评论的 提交评论 按钮,并找到他的事件。(jQuery 绑定的)

2. 动态调试这个 提交评论 事件的执行过程。

如果不会这个练习,推荐看下 《浅谈 jQuery 事件源码定位问题》,有详细分析哦。

本文来自:博客园博主 乱码 的文章。http://www.cnblogs.com/52cik/

========

一探前端开发中的JS调试技巧

http://www.cnblogs.com/miragele/p/5394396.html

前言:调试技巧,在任何一项技术研发中都可谓是必不可少的技能。掌握各种调试技巧,必定能在工作

中起到事半功倍的效果。譬如,快速定位问题、降低故障概率、帮助分析逻辑错误等等。而在互联网前

端开发越来越重要的今天,如何在前端开发中降低开发成本,提升工作效率,掌握前端开发调试技巧尤

为重要。

本文将一一讲解各种前端JS调试技巧,也许你已经熟练掌握,那让我们一起来温习,也许有你没见过的

方法,不妨一起来学习,也许你尚不知如何调试,赶紧趁此机会填补空白。

骨灰级调试大师Alert

那还是互联网刚刚起步的时代,网页前端还主要以内容展示为主,浏览器脚本还只能为页面提供非常简

单的辅助功能的时候。那个时候,网页主要运行在以IE6为主的浏览器中,JS的调试功能还非常弱,只能

通过内置于Window对象中的alert方法来调试,那时候看起来应该是这个样子:

Alert调试效果

需要说明一点,这里看到的效果,并非当年的IE浏览器中看到的效果,而是在高版本IE中的效果。此外

,当年貌似还没有这么高级的控制台,而alert的使用也是在真实的页面JS代码中。虽然,alert的调试

方式很原始,但当时确实有它不可磨灭的价值,甚至到今天,已然有其用武之地。

新一代调试王者Console

随着JS在Web前端中能做的事情越来越多,责任越来越大,而地位也越来越重要。传统的alert调试方式

已经渐渐不能满足前端开发的种种场景。而且alert调试方式弹出的调试信息,那个窗口着实不太美观,

而且会遮挡部分页面内容,着实有些不太友好。

另一方面,alert的调试信息,必须在程序逻辑中添加类似”alert(xxxxx)”这样的语句,才能正常工作

,并且alert会阻碍页面的继续渲染。这就意味着开发人员调试完成后,必须手动清除这些调试代码,实

在有些麻烦。

所以,新一代的浏览器Firefox、Chrome,包括IE,都相继推出了JS调试控制台,支持使用类

似”console.log(xxxx)”的形式,在控制台打印调试信息,而不直接影响页面显示。以IE为例,它看起

来像这样:

Console调试效果

好吧,再见丑陋的alert弹出框。而以Chrome浏览器为首的后起之秀,为Console扩展了更丰富的功能:

更丰富的Console

你以为这样就满足了?Chrome开发团队的想象力实在不得不让人佩服:

花式Console.log

好了,稍微多说了一点点题外话。总之,控制台以及浏览器内置Console对象的出现,给前端开发调试带

来了极大的便利。

有人会问,这样的调试代码不一样需要在调试完成后进行清理吗?

关于这个问题,如果在使用console对象之前先进性存在性验证,其实不删除也不会对业务逻辑造成破坏

。当然,为了代码整洁,在调试完成后,还是应尽可能删除这些与业务逻辑无关的调试代码。

JS断点调试

断点,调试器的功能之一,可以让程序中断在需要的地方,从而方便其分析。也可以在一次调试中设置

断点,下一次只需让程序自动运行到设置断点位置,便可在上次设置断点的位置中断下来,极大的方便

了操作,同时节省了时间。——百度百科

JS断点调试,即是在浏览器开发者工具中为JS代码添加断点,让JS执行到某一特定位置停住,方便开发

者对该处代码段的分析与逻辑处理。为了能够观察到断点调试的效果,我们预先随意准备一段JS代码:

断点调试测试代码

代码很简单,就是定义一个函数,传入两个数,分别加上一个乱七八糟的随机整数后,再返回两个数的

总和。以Chrome开发者工具为例,我们来看一下JS断点调试的基本方法。

Sources断点

首先,测试代码中我们通过上图console的输出结果可以看出代码应该是正常运行了,但是为什么是应该

呢?因为函数中加了一个随机数,而最终结果是否真的是正确的呢?这是毫无意义的猜想,但是假设我

现在就是要验证一下:函数传入的两个数、被加的随机数,以及最终的总和。那么该怎么操作呢?

方法一,前面讲过最普通的,无论使用alert还是console,我们可以这么来验证:

通过console进行上述验证

从上图发现,我们在代码中新增了三行console代码,用以打印我们关心的数据变量,而最终我们从控制

台(Console面板)中的输出结果,可以很清楚的验证整个计算过程是否正常,进而达到我们题设的验证

要求。

方法二,方法一的验证过程存在很明显的弊端就是,添加了很多冗余代码,接下来我们看一下使用断点

进行验证,是否更加方便,先看一个如何加断点,以及断点后是什么效果:

断点调试效果一

如图,给一段代码添加断点的流程是“F12(Ctrl + Shift + I)打开开发工具”——“点击Sources菜

单”——“左侧树中找到相应文件”——“点击行号列”即完成在当前行添加/删除断点操作。当断点添

加完毕后,刷新页面JS执行到断点位置停住,在Sources界面会看到当前作用域中所有变量和值,只需对

每个值进行验证即可完成我们题设验证要求。

那问题来了,仔细的朋友会发现当我的代码执行到断点的时候,显示的变量a和b的值是已经进行过加法

运算后的,我们看不到调用sum函数时初始传入的10和20。那么该怎么办呢?这就要回过头来先学习一下

断点调试的一些基础知识了。我们打开Sources面板后其实会在界面中看到如下内容,我们跟着鼠标轨迹

逐一看看都是什么意思:

断点调试功能选项介绍

从左到右,各个图标表示的功能分别为:

Pause/Resume script execution:暂停/恢复脚本执行(程序执行到下一断点停止)。

Step over next function call:执行到下一步的函数调用(跳到下一行)。

Step into next function call:进入当前函数。

Step out of current function:跳出当前执行函数。

Deactive/Active all breakpoints:关闭/开启所有断点(不会取消)。

Pause on exceptions:异常情况自动断点设置。

到此,断点调试的功能键介绍得差不多了,接下来我们就可以一行一行去看我们的程序代码,查看每一

行执行完毕之后,我们各个变量的变化情况了,如下图所示:

断点调试,逐行验证

如上,我们可以看到a、b变量从最初值,到中间加上随机值,再到最后计算总和并输出最终结果的整个

过程,完成题设验证要求不在话下。

其余几个功能键,我们稍微改动一下我们的测试代码,用一张gif图来演示他们的使用方法:

断点进入、跳出函数演示

这里需要注意一点,直接在代码区打印变量值的功能是在较新版本的Chrome浏览器中才新增的功能,如

果你还在使用较老版本的Chrome浏览器,可能无法直接在断点的情况下查看变量信息,此时你可以将鼠

标移动到变量名上短暂停顿则会出现变量值。也可以用鼠标选中变量名称,然后右键“Add to watch”

在Watch面板查看,此方法同样适用于表达式。此外,你还可以在断点情况下,切换到Console面板,直

接在控制台输入变量名称,回车查看变量信息。该部分比较简单,考虑篇幅问题,不在做图演示。

Debugger断点

所谓的Debugger断点,其实是我自己给它命名的,专业术语我也不知道怎么说。具体的说就是通过在代

码中添加”debugger;”语句,当代码执行到该语句的时候就会自动断点。接下去的操作就跟在Sources

面板添加断点调试几乎一模一样,唯一的区别在于调试完后需要删除该语句。

既然除了设置断点的方式不一样,功能和Sources面板添加断点效果一样,那么为什么还会存在这种方式

呢?我想原因应该是这样的:我们在开发中偶尔会遇到异步加载html片段(包含内嵌JS代码)的情况,

而这部分JS代码在Sources树种无法找到,因此无法直接在开发工具中直接添加断点,那么如果想给异步

加载的脚本添加断点,此时”debugger;”就发挥作用了。我们直接通过gif图看看他的效果:

Debugger断点使用演示

DOM断点调试

DOM断点,顾名思义就是在DOM元素上添加断点,进而达到调试的目的。而在实际使用中断点的效果最终

还是落地到JS逻辑之内。我们依次来看一下每一种DOM断点的具体效果。

当节点内部子节点变化时断点(Break on subtree modifications)

在前端开发越来越复杂的今天,前端JS代码越来越多,逻辑越来越复杂,一个看似简单的Web页面,通常

伴随着大段大段的JS代码,涉及诸多DOM节点增、删、改的操作。难免遇到直接通过JS代码很难定位代码

段的情况,而我们却可以通过开发者工具的Elements面板,快速定位到相关DOM节点,这时候通过DOM断

点定位脚本就显得尤其重要了。具体我们还是通过gif演示来看一下吧:

子节点发生变化时断点

上图演示了对ul子节点(li)的增加、删除以及交换顺序操作触发断点的效果。但需要注意的是,对子

节点进行属性修改和内容修改并不会触发断点。

当节点属性发生变化时断点(Break on attributes modifications)

另一方面,由于前端处理的业务逻辑越来越复杂,对一些数据的存储依赖越来越强烈,而将临时数据存

储于DOM节点的(自定义)属性中,是很多情况下开发者优先选择的方式。特别是在HTML5标准增强自定

义属性支持(例:dataset、data-*之类)之后,属性设置应用越来越多,因此Chrome开发者工具也提供

了属性变化断点支持,其效果大致如下:

节点属性变化时断点演示

此方式同样需要注意,对子节点的属性进行任何操作也不会触发节点本身的断点。

当节点被移除时断点(Break on node removal)

这个DOM断点设置很简单,触发方式很明确——当节点被删除时。所以通常情况应该是在执

行”parentNode.removeChild(childNode)”语句的时候使用此方式。此方式使用不多。

前面介绍到的基本上是我们在日常开发中经常用到的调试手段,运用得当它们也几乎能应对我们日常开

发中的几乎所有问题。但是,开发者工具还考虑到了更多的情况,提供更多的断点方式,如图:

XHR和事件监听断点

XHR Breakpoints

这几年前端开发发生了翻天覆地的变化,从当初的名不见经传到如今的盛极一时,Ajax驱动Web富应用,

移动WebApp单页应用风生水起。这一切都离不开XMLHttpRequest对象,而“XHR Breakpoints”正是专为

异步而生的断点调试功能。

XHR Breakpoints演示

我们可以通过“XHR Breakpoints”右侧的“+”号为异步断点添加断点条件,当异步请求触发时的URL满

足此条件,JS逻辑则会自动产生断点。演示动画中并没有演示到断点位置,这是因为,演示使用的是

jQuery封装好的ajax方法,代码已经过压缩,看不到什么效果,而事实上XHR断点的产生位置

是”xhr.send()”语句。

XHR断点的强大之处是可以自定义断点规则,这就意味着我们可以针对某一批、某一个,乃至所有异步请

求进行断点设置,非常强大。但是,似乎这个功能在日常开发中用得并不多,至少我用得不多。想想原

因大概有两点:其一,这类型的断点调试需求在日常业务中本身涉及不多;其二,现阶段的前端开发大

多基于JS框架进行,最基本的jQuery也已经对Ajax进行了良好封装,极少有人自己封装Ajax方法,而项

目为了减少代码体积,通常选择压缩后的代码库,使得XHR断点跟踪相对不那么容易了。

Event Listener Breakpoints

事件监听器断点,即根据事件名称进行断点设置。当事件被触发时,断点到事件绑定的位置。事件监听

器断点,列出了所有页面及脚本事件,包括:鼠标、键盘、动画、定时器、XHR等等。极大的降低了事件

方面业务逻辑的调试难度。

事件监听器断点演示

演示实例演示了当click事件被触发时和当setTimeout被设置时的断点效果。实例显示,当选中click事

件断点之后,两个按钮的被点击时都触发了断点,而当setTimeout被设置时,“Set Timer”断点被触发



调试,是在项目开发中非常重要的环节,不仅可以帮助我们快速定位问题,还能节省我们的开发时间。

熟练掌握各种调试手段,定当为你的职业发展带来诸多利益,但是,在如此多的调试手段中,如何选择

一个适合自己当前应用场景的,这需要经验,需要不断尝试积累。

========

浅谈 jQuery 事件源码定位问题

http://www.jb51.net/article/51212.htm

在一个不是自己写的页面上,如何快速定位到他绑定的事件代码在哪,下面为大家简单的介绍下,需要的

朋友可以参考下

昨天群里有人问了个事件源码定位的问题,简单描述下是这样的。

在一个不是自己写的页面上,如何快速定位到他绑定的事件代码在哪?(页面用的是jQuery)

这个问题,说难不难,说简单也没那么简单,万一用的是委托之类也会麻烦点。

在 chrome 的控制台里有个 Event Listeners,这里会显示你所选择元素的事件,如果是原生事件,他

会直接显示,

你点击一下事件就会跳到对应代码里了,可是 jQuery 绑定的事件却不是这样的,你点击后只会跳到 

jQuery 源码里,

min后的jQuery源码密密麻麻的,看着都眼花。

关于jQuery对于事件的管理,大牛们也分析的非常透彻了,我就不啰嗦了,因为不是我们今天要说的重

点。

我们要说的重点是怎么定位到事件源码处。因为jQuery版本众多,而且重构过多次,所以要分情况来说

了。

基本上 1.2.6-1.8 和 1.9 两种情况,经过测试,大体上定为下面2个版本

1.2.6-1.8 用  $.data( elem, "events", undefined, true ); 

1.9+ 用  $._data( elem, "events" ); 

PS: 你现在也可以按 F12 打开控制台看看结果,当然也可以复制下面的源码自己测试。

由于谷歌被墙的厉害,所以把cdn换成百度的了。2014-06-07

?

<!doctype html>

<html lang="en">

<head>

  <meta charset="UTF-8">

  <title>test</title>

  <script src="http://libs.baidu.com/jquery/1.4.0/jquery.js"></script>

</head>

 

<body>

  <input type="button" id="testbtn" value="testbtn" />

  <script>

    var version = ["1.2.6", "1.3.0", "1.4.0", "1.5.0", "1.6.0", "1.7.0", "1.8.0", "1.9.0", 

"1.10.0"],

      elem = $("#testbtn")[0], // 待操作的元素

      url, // jquery 地址

      jq = null, // 保存新的jquery句柄

      jqver, // jqury 版本

      fn; // 函数句柄

 

    for (var i = 0; i < version.length; i++) {

      url = "http://libs.baidu.com/jquery/" + version[i] + "/jquery.min.js";

 

      $.getScript(url, function() {

        jq = $.noConflict(true); // 释放控制权

        jqver = jq.fn.jquery; // 当前 jquery 版本

        fn = new Function('ver_' + jqver.replace(/\./g, "_"), ''); // 生成类似 function 

(ver_1_9_0) {} 这样的函数

        jq(elem).click(fn).click(fn).bind("test", fn); // 普通事件和自定义事件

 

        console.log(

          jqver,

          jq.data && jq.data(elem, "events", undefined, true),

          jq._data && jq._data(elem, "events")

        );

      });

    }

  </script>

</body>

</html>

如果不出意外,你可以在控制台看到这样的显示结果

展开后可以看到绑定的函数参数里的版本和当前版本是对应的。

 

可以看到

1.2.6-1.4 只支持  $.data( elem, "events", undefined, true ); 

1.5-1.8 两者都支持

1.9-1.11 只支持  $._data( elem, "events" ); 

那么我们可以写个函数简单的兼容下,然他全兼容即可

?

function lookEvents (elem) {

  return $.data ? $.data( elem, "events", undefined, true ) : $._data( elem, "events" );

}

现在调用 lookEvents 就可以得到对应的 events 对象了。

虽然可以看到了我们绑定的自定义事件,但还是不知道他在哪个文件哪一行啊。

下面我们就来定位他的具体位置,我们就拿 1.7 的试试。

PS: 下面操作都是在控制台完成,我的环境是 chrome 34

?

function lookEvents (elem) {

  return $.data ? $.data( elem, "events", undefined, true ) : $._data( elem, "events" );

}

var event = lookEvents($("#testbtn")[0]); // 获取绑定的事件

event.click[0].handler // 获取click事件的第一个事件源码地址

复制到控制台,按回车运行后,不出意外可以看到下面这个结果。

有没有看到右下角的 1.html:36 这个就是源码所在的文件和对应的行号了。

你可以直接点击 1.html:36 跳到对应的代码处,是不是觉得很给力啊。

上面方法适用于 1.5+ 版本的 jQuery,对于 1.2.6-1.4 的版本,稍微有点不同,不过也非常简单。

function lookEvents (elem) { return $.data ? $.data( elem, "events", undefined, true ) : 

$._data( elem, "events" );}var event = lookEvents($("#testbtn")[0]); // 获取绑定的事件

event.click; // 查看有几个click事件,如果要查看其他事件直接输入 event 然后回车即可

上面看到的编码就是对应事件句柄了,比如我这的 1,2 事件(如下图显示), 这个编号不是按顺序的,

这个要注意。

 event.click[1] // 获取click事件的 id是1 的事件源码地址 

不出意外可以看到下面这个结果。

从操作来说,不管是 1.2.6-1.4 还是 1.5+ 版本 都差不多,只是 1.5+ 利用数组模式管理函数句柄了

,比较方便。

好了,该说的都说完了,小伙伴们各种测试起来吧。

========

JSFiddle:在线JS代码调试工具

http://www.egouz.com/topics/7865.html

英文网址:http://jsfiddle.net/英文网址

JSFiddle:在线JS代码调试工具是一个老牌的支持javascript、css、html代码可视化在线调试工具,支

持多种应用多种主流框架,用起来非常方便,而且还可以将调试好的结果以非常简洁的页面直接嵌入在

其他网页里。

JSFiddle:在线JS代码调试工具

对于网页设计师来说需要写演示用的JavaScript实例代码的时候,就完全可以在jsFiddle里面直接完成

编写后调试,再将结果直接嵌入Blog正文里即可了,真的是很方便的选择。

除了可以调试代码外,还可以方便的发布到社区,论坛或者社交媒体上与朋友们分享或者提问。整合了

很多的不同的类库供大家选择。 类似的工具还有jsbin.com,也非常不错。

========

http://runjs.cn/

RunJS - 在线编辑、展示、分享、交流你的 JavaScript 代码

========
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript 调试