js调试学习总结2
js調(diào)試系列 斷點(diǎn)與動(dòng)態(tài)調(diào)試[基礎(chǔ)篇]
http://www.jb51.net/article/51233.htm上幾篇文章已經(jīng)為大家介紹了js調(diào)試系列的一些基礎(chǔ)知識(shí),支持亂碼兄弟為大家?guī)?lái)了js斷點(diǎn)與動(dòng)態(tài)調(diào)
試方法,需要的朋友可以參考下
上幾篇文章已經(jīng)為大家介紹了js調(diào)試系列的一些基礎(chǔ)知識(shí),這次亂碼兄弟為大家?guī)?lái)了js斷點(diǎn)與動(dòng)態(tài)調(diào)
試方法,需要的朋友可以參考下
昨天留的課后練習(xí) 1. 分析 votePost 函數(shù)是如何實(shí)現(xiàn) 推薦 的。
其實(shí)我們已經(jīng)看到了源碼,只要讀下源碼即可知道他是怎么實(shí)現(xiàn)的了。
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("抱歉!發(fā)生了錯(cuò)誤!麻煩反饋至
contact@cnblogs.com") : $("#digg_tips").html(n.responseText))?
? }?
?});?
}
ps: 我用的是 sublime text 格式化的代碼,和chrome控制臺(tái)格式化后的結(jié)果有點(diǎn)不同。
也可以試試這個(gè)在線(xiàn)格式化工具,效果差不多:Online JavaScript beautifier?
簡(jiǎn)單讀過(guò)代碼后,可以大致知道,這個(gè)函數(shù)有 3 個(gè)參數(shù),第一個(gè)是 postId,就是文章ID,第二個(gè)是 推
薦(digg) 或者 反對(duì)(bury),
但是第三個(gè)一直沒(méi)用到,而且默認(rèn)值是 false
往下看,他在 #digg_tips 處顯示 "提交中..." 字符串,接著通過(guò) ajax 提交數(shù)據(jù)給后臺(tái)。
返回?cái)?shù)據(jù)后,如果 n.IsSuccess 是 真 就在對(duì)應(yīng)的 喜歡(#digg_count)或反對(duì)(#bury_count)的計(jì)數(shù)id
上 +1,
不過(guò)這里看到如果 isAbandoned 的值是 真 的話(huà),就計(jì)數(shù) -1。
那我們可以猜測(cè)第三個(gè)參數(shù)是撤銷(xiāo)推薦或者反對(duì)用的,簡(jiǎn)單說(shuō)就是我點(diǎn)了推薦,但是我現(xiàn)在不想推薦了
,可以傳遞第三個(gè)參數(shù) true 實(shí)現(xiàn)取消推薦的作用。
我們稍后測(cè)試下。
接著是在 #digg_tips 處顯示服務(wù)器返回的 n.Message 信息。
如果 ajax 發(fā)生錯(cuò)誤,是 500 錯(cuò)誤就提示 "抱歉!發(fā)生了錯(cuò)誤!麻煩反饋至contact@cnblogs.com" 其
他狀態(tài)直接提示服務(wù)器返回的錯(cuò)誤信息。
這就是大致的流程,因?yàn)檫@個(gè)函數(shù)簡(jiǎn)單,所以基本上一眼就看出來(lái)了。
可能有的新人朋友問(wèn)了,你怎么知道 currentBlogApp, n, t ,i 是什么值呢?
那我們來(lái)進(jìn)行下一步,動(dòng)態(tài)調(diào)試好了。對(duì)于編譯過(guò)的項(xiàng)目,動(dòng)態(tài)調(diào)試是非常有用的手段。
先定位到 votePost 源碼處,(這個(gè)昨天說(shuō)過(guò)了,不太懂的話(huà),再回去看看先。)
so easy,我們就定位到了源碼。
接下來(lái)我們點(diǎn)下92那個(gè)數(shù)字,進(jìn)行下斷點(diǎn)操作。
為什么不是在91行下斷點(diǎn)呢?
因?yàn)?1行是函數(shù)聲明部分,沒(méi)法下斷點(diǎn),我們?cè)诤瘮?shù)要執(zhí)行的代碼處下斷點(diǎn)才行。
看到 91 行的行號(hào)變成藍(lán)色了,表示這個(gè)地方已經(jīng)下了斷點(diǎn)了。同時(shí),我們可以在右側(cè) Breakpoints 一
欄里看到已下的斷點(diǎn)。
Breakpoints 這個(gè)一欄是管理所有斷點(diǎn)的,可以方便的跳轉(zhuǎn)到對(duì)應(yīng)斷點(diǎn)的位置出,以后常常會(huì)用到哦。
現(xiàn)在下完斷點(diǎn)了,我們回頭點(diǎn)下 推薦。。(雖然感覺(jué)我在騙推薦,不過(guò)我真心沒(méi)這么想,當(dāng)初是隨便找
了個(gè)按鈕當(dāng)練習(xí)的。)
當(dāng)你點(diǎn) 推薦 按鈕的時(shí)候,神奇的事情發(fā)生了,并沒(méi)有運(yùn)行推薦功能,而是跳到了控制臺(tái) Sources 面板
里我們剛剛下的那個(gè)斷點(diǎn)處。
現(xiàn)在,你不僅能在右側(cè) Scope Variables(變量作用域) 一欄處看到當(dāng)前變量,而且還能把鼠標(biāo)直接移到
任意變量上,就可以查看該變量的值。
Scope Variables欄目會(huì)顯示當(dāng)前作用域以及他的父級(jí)作用域,以及閉包。
是不是超方便。。(我初學(xué)閉包的時(shí)候,Scope Variables幫了我不少呢。)
我們進(jìn)行下一步,按3次 F10 就可以看到這樣的東西。
我們每按一次 F10 會(huì)執(zhí)行一條語(yǔ)句,剛才按了3次,就是執(zhí)行到了 ?$("#digg_tips").css("color",?
"red").html("提交中...");?
所以我們可以在頁(yè)面上看到 #digg_tips 顯示提交中的字樣。
可是當(dāng)我們?cè)俅伟?F10 的時(shí)候,發(fā)現(xiàn)他一路執(zhí)行下去,而沒(méi)有進(jìn)入 ajax 內(nèi)部的回調(diào)函數(shù)。
這是個(gè)糾結(jié)的問(wèn)題,也是我要重點(diǎn)說(shuō)的。
像這種回調(diào)函數(shù),特別是異步的,我們要在回調(diào)函數(shù)內(nèi)部再次下一個(gè)斷點(diǎn)。
所以我們?cè)?96 行再下個(gè)斷點(diǎn)即可,現(xiàn)在我們?cè)冱c(diǎn)一下 推薦 依然停在了 92 行,我們直接按 F8 就可
以在 ajax 的回調(diào)函數(shù)處斷下了。
現(xiàn)在,我們就可以調(diào)試回調(diào)數(shù)據(jù)了,同時(shí)可以發(fā)現(xiàn)右側(cè) Scope Variables 多了一個(gè) Closure 的東西,
這個(gè)就是閉包。
如果現(xiàn)在理解不了,那就過(guò),這東西要大篇幅介紹,不是三言?xún)删渚湍苤v明白的,反正控制臺(tái)很強(qiáng)大就
對(duì)了。
在看到閉包的同時(shí),我們也看到 ajax 的返回?cái)?shù)據(jù) n,很明顯,我的 IsSuccess 屬性為 false 沒(méi)有成
功,因?yàn)樗祷亓艘粋€(gè)信息 "不能推薦自己的內(nèi)容"。
是不是很有意思,動(dòng)態(tài)調(diào)試,讓尋找BUG變得 so easy。
接下來(lái),我們來(lái)實(shí)驗(yàn)第三個(gè)參數(shù)。
我們?cè)诳刂婆_(tái)輸入 ?votePost(cb_entryId, 'Digg', true); ?然后回車(chē)。
同樣停在了92行的斷點(diǎn)處,這個(gè)里就不調(diào)試了,直接F8進(jìn)入 ajax 的回調(diào)函數(shù)出。
在這里我們非常清楚的看到,當(dāng)?shù)谌齻€(gè)參數(shù)為 true 的時(shí)候,確實(shí)是取消推薦了,同時(shí)你可以看到推薦
數(shù)確實(shí) -1 了,哪怕刷新也一樣。
本次我們用到了兩個(gè)快捷鍵 F10 和 F8,明天詳細(xì)介紹,今天先學(xué)會(huì)基礎(chǔ)調(diào)試先。
課后練習(xí):(提高下難度)
1. 查看下面評(píng)論的 提交評(píng)論 按鈕,并找到他的事件。(jQuery 綁定的)
2. 動(dòng)態(tài)調(diào)試這個(gè) 提交評(píng)論 事件的執(zhí)行過(guò)程。
如果不會(huì)這個(gè)練習(xí),推薦看下 《淺談 jQuery 事件源碼定位問(wèn)題》,有詳細(xì)分析哦。
本文來(lái)自:博客園博主 亂碼 的文章。http://www.cnblogs.com/52cik/
========
一探前端開(kāi)發(fā)中的JS調(diào)試技巧
http://www.cnblogs.com/miragele/p/5394396.html前言:調(diào)試技巧,在任何一項(xiàng)技術(shù)研發(fā)中都可謂是必不可少的技能。掌握各種調(diào)試技巧,必定能在工作
中起到事半功倍的效果。譬如,快速定位問(wèn)題、降低故障概率、幫助分析邏輯錯(cuò)誤等等。而在互聯(lián)網(wǎng)前
端開(kāi)發(fā)越來(lái)越重要的今天,如何在前端開(kāi)發(fā)中降低開(kāi)發(fā)成本,提升工作效率,掌握前端開(kāi)發(fā)調(diào)試技巧尤
為重要。
本文將一一講解各種前端JS調(diào)試技巧,也許你已經(jīng)熟練掌握,那讓我們一起來(lái)溫習(xí),也許有你沒(méi)見(jiàn)過(guò)的
方法,不妨一起來(lái)學(xué)習(xí),也許你尚不知如何調(diào)試,趕緊趁此機(jī)會(huì)填補(bǔ)空白。
骨灰級(jí)調(diào)試大師Alert
那還是互聯(lián)網(wǎng)剛剛起步的時(shí)代,網(wǎng)頁(yè)前端還主要以?xún)?nèi)容展示為主,瀏覽器腳本還只能為頁(yè)面提供非常簡(jiǎn)
單的輔助功能的時(shí)候。那個(gè)時(shí)候,網(wǎng)頁(yè)主要運(yùn)行在以IE6為主的瀏覽器中,JS的調(diào)試功能還非常弱,只能
通過(guò)內(nèi)置于Window對(duì)象中的alert方法來(lái)調(diào)試,那時(shí)候看起來(lái)應(yīng)該是這個(gè)樣子:
Alert調(diào)試效果
需要說(shuō)明一點(diǎn),這里看到的效果,并非當(dāng)年的IE瀏覽器中看到的效果,而是在高版本IE中的效果。此外
,當(dāng)年貌似還沒(méi)有這么高級(jí)的控制臺(tái),而alert的使用也是在真實(shí)的頁(yè)面JS代碼中。雖然,alert的調(diào)試
方式很原始,但當(dāng)時(shí)確實(shí)有它不可磨滅的價(jià)值,甚至到今天,已然有其用武之地。
新一代調(diào)試王者Console
隨著JS在Web前端中能做的事情越來(lái)越多,責(zé)任越來(lái)越大,而地位也越來(lái)越重要。傳統(tǒng)的alert調(diào)試方式
已經(jīng)漸漸不能滿(mǎn)足前端開(kāi)發(fā)的種種場(chǎng)景。而且alert調(diào)試方式彈出的調(diào)試信息,那個(gè)窗口著實(shí)不太美觀(guān),
而且會(huì)遮擋部分頁(yè)面內(nèi)容,著實(shí)有些不太友好。
另一方面,alert的調(diào)試信息,必須在程序邏輯中添加類(lèi)似”alert(xxxxx)”這樣的語(yǔ)句,才能正常工作
,并且alert會(huì)阻礙頁(yè)面的繼續(xù)渲染。這就意味著開(kāi)發(fā)人員調(diào)試完成后,必須手動(dòng)清除這些調(diào)試代碼,實(shí)
在有些麻煩。
所以,新一代的瀏覽器Firefox、Chrome,包括IE,都相繼推出了JS調(diào)試控制臺(tái),支持使用類(lèi)
似”console.log(xxxx)”的形式,在控制臺(tái)打印調(diào)試信息,而不直接影響頁(yè)面顯示。以IE為例,它看起
來(lái)像這樣:
Console調(diào)試效果
好吧,再見(jiàn)丑陋的alert彈出框。而以Chrome瀏覽器為首的后起之秀,為Console擴(kuò)展了更豐富的功能:
更豐富的Console
你以為這樣就滿(mǎn)足了?Chrome開(kāi)發(fā)團(tuán)隊(duì)的想象力實(shí)在不得不讓人佩服:
花式Console.log
好了,稍微多說(shuō)了一點(diǎn)點(diǎn)題外話(huà)??傊?#xff0c;控制臺(tái)以及瀏覽器內(nèi)置Console對(duì)象的出現(xiàn),給前端開(kāi)發(fā)調(diào)試帶
來(lái)了極大的便利。
有人會(huì)問(wèn),這樣的調(diào)試代碼不一樣需要在調(diào)試完成后進(jìn)行清理嗎?
關(guān)于這個(gè)問(wèn)題,如果在使用console對(duì)象之前先進(jìn)性存在性驗(yàn)證,其實(shí)不刪除也不會(huì)對(duì)業(yè)務(wù)邏輯造成破壞
。當(dāng)然,為了代碼整潔,在調(diào)試完成后,還是應(yīng)盡可能刪除這些與業(yè)務(wù)邏輯無(wú)關(guān)的調(diào)試代碼。
JS斷點(diǎn)調(diào)試
斷點(diǎn),調(diào)試器的功能之一,可以讓程序中斷在需要的地方,從而方便其分析。也可以在一次調(diào)試中設(shè)置
斷點(diǎn),下一次只需讓程序自動(dòng)運(yùn)行到設(shè)置斷點(diǎn)位置,便可在上次設(shè)置斷點(diǎn)的位置中斷下來(lái),極大的方便
了操作,同時(shí)節(jié)省了時(shí)間。——百度百科
JS斷點(diǎn)調(diào)試,即是在瀏覽器開(kāi)發(fā)者工具中為JS代碼添加斷點(diǎn),讓JS執(zhí)行到某一特定位置停住,方便開(kāi)發(fā)
者對(duì)該處代碼段的分析與邏輯處理。為了能夠觀(guān)察到斷點(diǎn)調(diào)試的效果,我們預(yù)先隨意準(zhǔn)備一段JS代碼:
斷點(diǎn)調(diào)試測(cè)試代碼
代碼很簡(jiǎn)單,就是定義一個(gè)函數(shù),傳入兩個(gè)數(shù),分別加上一個(gè)亂七八糟的隨機(jī)整數(shù)后,再返回兩個(gè)數(shù)的
總和。以Chrome開(kāi)發(fā)者工具為例,我們來(lái)看一下JS斷點(diǎn)調(diào)試的基本方法。
Sources斷點(diǎn)
首先,測(cè)試代碼中我們通過(guò)上圖console的輸出結(jié)果可以看出代碼應(yīng)該是正常運(yùn)行了,但是為什么是應(yīng)該
呢?因?yàn)楹瘮?shù)中加了一個(gè)隨機(jī)數(shù),而最終結(jié)果是否真的是正確的呢?這是毫無(wú)意義的猜想,但是假設(shè)我
現(xiàn)在就是要驗(yàn)證一下:函數(shù)傳入的兩個(gè)數(shù)、被加的隨機(jī)數(shù),以及最終的總和。那么該怎么操作呢?
方法一,前面講過(guò)最普通的,無(wú)論使用alert還是console,我們可以這么來(lái)驗(yàn)證:
通過(guò)console進(jìn)行上述驗(yàn)證
從上圖發(fā)現(xiàn),我們?cè)诖a中新增了三行console代碼,用以打印我們關(guān)心的數(shù)據(jù)變量,而最終我們從控制
臺(tái)(Console面板)中的輸出結(jié)果,可以很清楚的驗(yàn)證整個(gè)計(jì)算過(guò)程是否正常,進(jìn)而達(dá)到我們題設(shè)的驗(yàn)證
要求。
方法二,方法一的驗(yàn)證過(guò)程存在很明顯的弊端就是,添加了很多冗余代碼,接下來(lái)我們看一下使用斷點(diǎn)
進(jìn)行驗(yàn)證,是否更加方便,先看一個(gè)如何加斷點(diǎn),以及斷點(diǎn)后是什么效果:
斷點(diǎn)調(diào)試效果一
如圖,給一段代碼添加斷點(diǎn)的流程是“F12(Ctrl + Shift + I)打開(kāi)開(kāi)發(fā)工具”——“點(diǎn)擊Sources菜
單”——“左側(cè)樹(shù)中找到相應(yīng)文件”——“點(diǎn)擊行號(hào)列”即完成在當(dāng)前行添加/刪除斷點(diǎn)操作。當(dāng)斷點(diǎn)添
加完畢后,刷新頁(yè)面JS執(zhí)行到斷點(diǎn)位置停住,在Sources界面會(huì)看到當(dāng)前作用域中所有變量和值,只需對(duì)
每個(gè)值進(jìn)行驗(yàn)證即可完成我們題設(shè)驗(yàn)證要求。
那問(wèn)題來(lái)了,仔細(xì)的朋友會(huì)發(fā)現(xiàn)當(dāng)我的代碼執(zhí)行到斷點(diǎn)的時(shí)候,顯示的變量a和b的值是已經(jīng)進(jìn)行過(guò)加法
運(yùn)算后的,我們看不到調(diào)用sum函數(shù)時(shí)初始傳入的10和20。那么該怎么辦呢?這就要回過(guò)頭來(lái)先學(xué)習(xí)一下
斷點(diǎn)調(diào)試的一些基礎(chǔ)知識(shí)了。我們打開(kāi)Sources面板后其實(shí)會(huì)在界面中看到如下內(nèi)容,我們跟著鼠標(biāo)軌跡
逐一看看都是什么意思:
斷點(diǎn)調(diào)試功能選項(xiàng)介紹
從左到右,各個(gè)圖標(biāo)表示的功能分別為:
Pause/Resume script execution:暫停/恢復(fù)腳本執(zhí)行(程序執(zhí)行到下一斷點(diǎn)停止)。
Step over next function call:執(zhí)行到下一步的函數(shù)調(diào)用(跳到下一行)。
Step into next function call:進(jìn)入當(dāng)前函數(shù)。
Step out of current function:跳出當(dāng)前執(zhí)行函數(shù)。
Deactive/Active all breakpoints:關(guān)閉/開(kāi)啟所有斷點(diǎn)(不會(huì)取消)。
Pause on exceptions:異常情況自動(dòng)斷點(diǎn)設(shè)置。
到此,斷點(diǎn)調(diào)試的功能鍵介紹得差不多了,接下來(lái)我們就可以一行一行去看我們的程序代碼,查看每一
行執(zhí)行完畢之后,我們各個(gè)變量的變化情況了,如下圖所示:
斷點(diǎn)調(diào)試,逐行驗(yàn)證
如上,我們可以看到a、b變量從最初值,到中間加上隨機(jī)值,再到最后計(jì)算總和并輸出最終結(jié)果的整個(gè)
過(guò)程,完成題設(shè)驗(yàn)證要求不在話(huà)下。
其余幾個(gè)功能鍵,我們稍微改動(dòng)一下我們的測(cè)試代碼,用一張gif圖來(lái)演示他們的使用方法:
斷點(diǎn)進(jìn)入、跳出函數(shù)演示
這里需要注意一點(diǎn),直接在代碼區(qū)打印變量值的功能是在較新版本的Chrome瀏覽器中才新增的功能,如
果你還在使用較老版本的Chrome瀏覽器,可能無(wú)法直接在斷點(diǎn)的情況下查看變量信息,此時(shí)你可以將鼠
標(biāo)移動(dòng)到變量名上短暫停頓則會(huì)出現(xiàn)變量值。也可以用鼠標(biāo)選中變量名稱(chēng),然后右鍵“Add to watch”
在Watch面板查看,此方法同樣適用于表達(dá)式。此外,你還可以在斷點(diǎn)情況下,切換到Console面板,直
接在控制臺(tái)輸入變量名稱(chēng),回車(chē)查看變量信息。該部分比較簡(jiǎn)單,考慮篇幅問(wèn)題,不在做圖演示。
Debugger斷點(diǎn)
所謂的Debugger斷點(diǎn),其實(shí)是我自己給它命名的,專(zhuān)業(yè)術(shù)語(yǔ)我也不知道怎么說(shuō)。具體的說(shuō)就是通過(guò)在代
碼中添加”debugger;”語(yǔ)句,當(dāng)代碼執(zhí)行到該語(yǔ)句的時(shí)候就會(huì)自動(dòng)斷點(diǎn)。接下去的操作就跟在Sources
面板添加斷點(diǎn)調(diào)試幾乎一模一樣,唯一的區(qū)別在于調(diào)試完后需要?jiǎng)h除該語(yǔ)句。
既然除了設(shè)置斷點(diǎn)的方式不一樣,功能和Sources面板添加斷點(diǎn)效果一樣,那么為什么還會(huì)存在這種方式
呢?我想原因應(yīng)該是這樣的:我們?cè)陂_(kāi)發(fā)中偶爾會(huì)遇到異步加載html片段(包含內(nèi)嵌JS代碼)的情況,
而這部分JS代碼在Sources樹(shù)種無(wú)法找到,因此無(wú)法直接在開(kāi)發(fā)工具中直接添加斷點(diǎn),那么如果想給異步
加載的腳本添加斷點(diǎn),此時(shí)”debugger;”就發(fā)揮作用了。我們直接通過(guò)gif圖看看他的效果:
Debugger斷點(diǎn)使用演示
DOM斷點(diǎn)調(diào)試
DOM斷點(diǎn),顧名思義就是在DOM元素上添加斷點(diǎn),進(jìn)而達(dá)到調(diào)試的目的。而在實(shí)際使用中斷點(diǎn)的效果最終
還是落地到JS邏輯之內(nèi)。我們依次來(lái)看一下每一種DOM斷點(diǎn)的具體效果。
當(dāng)節(jié)點(diǎn)內(nèi)部子節(jié)點(diǎn)變化時(shí)斷點(diǎn)(Break on subtree modifications)
在前端開(kāi)發(fā)越來(lái)越復(fù)雜的今天,前端JS代碼越來(lái)越多,邏輯越來(lái)越復(fù)雜,一個(gè)看似簡(jiǎn)單的Web頁(yè)面,通常
伴隨著大段大段的JS代碼,涉及諸多DOM節(jié)點(diǎn)增、刪、改的操作。難免遇到直接通過(guò)JS代碼很難定位代碼
段的情況,而我們卻可以通過(guò)開(kāi)發(fā)者工具的Elements面板,快速定位到相關(guān)DOM節(jié)點(diǎn),這時(shí)候通過(guò)DOM斷
點(diǎn)定位腳本就顯得尤其重要了。具體我們還是通過(guò)gif演示來(lái)看一下吧:
子節(jié)點(diǎn)發(fā)生變化時(shí)斷點(diǎn)
上圖演示了對(duì)ul子節(jié)點(diǎn)(li)的增加、刪除以及交換順序操作觸發(fā)斷點(diǎn)的效果。但需要注意的是,對(duì)子
節(jié)點(diǎn)進(jìn)行屬性修改和內(nèi)容修改并不會(huì)觸發(fā)斷點(diǎn)。
當(dāng)節(jié)點(diǎn)屬性發(fā)生變化時(shí)斷點(diǎn)(Break on attributes modifications)
另一方面,由于前端處理的業(yè)務(wù)邏輯越來(lái)越復(fù)雜,對(duì)一些數(shù)據(jù)的存儲(chǔ)依賴(lài)越來(lái)越強(qiáng)烈,而將臨時(shí)數(shù)據(jù)存
儲(chǔ)于DOM節(jié)點(diǎn)的(自定義)屬性中,是很多情況下開(kāi)發(fā)者優(yōu)先選擇的方式。特別是在HTML5標(biāo)準(zhǔn)增強(qiáng)自定
義屬性支持(例:dataset、data-*之類(lèi))之后,屬性設(shè)置應(yīng)用越來(lái)越多,因此Chrome開(kāi)發(fā)者工具也提供
了屬性變化斷點(diǎn)支持,其效果大致如下:
節(jié)點(diǎn)屬性變化時(shí)斷點(diǎn)演示
此方式同樣需要注意,對(duì)子節(jié)點(diǎn)的屬性進(jìn)行任何操作也不會(huì)觸發(fā)節(jié)點(diǎn)本身的斷點(diǎn)。
當(dāng)節(jié)點(diǎn)被移除時(shí)斷點(diǎn)(Break on node removal)
這個(gè)DOM斷點(diǎn)設(shè)置很簡(jiǎn)單,觸發(fā)方式很明確——當(dāng)節(jié)點(diǎn)被刪除時(shí)。所以通常情況應(yīng)該是在執(zhí)
行”parentNode.removeChild(childNode)”語(yǔ)句的時(shí)候使用此方式。此方式使用不多。
前面介紹到的基本上是我們?cè)谌粘i_(kāi)發(fā)中經(jīng)常用到的調(diào)試手段,運(yùn)用得當(dāng)它們也幾乎能應(yīng)對(duì)我們?nèi)粘i_(kāi)
發(fā)中的幾乎所有問(wèn)題。但是,開(kāi)發(fā)者工具還考慮到了更多的情況,提供更多的斷點(diǎn)方式,如圖:
XHR和事件監(jiān)聽(tīng)斷點(diǎn)
XHR Breakpoints
這幾年前端開(kāi)發(fā)發(fā)生了翻天覆地的變化,從當(dāng)初的名不見(jiàn)經(jīng)傳到如今的盛極一時(shí),Ajax驅(qū)動(dòng)Web富應(yīng)用,
移動(dòng)WebApp單頁(yè)應(yīng)用風(fēng)生水起。這一切都離不開(kāi)XMLHttpRequest對(duì)象,而“XHR Breakpoints”正是專(zhuān)為
異步而生的斷點(diǎn)調(diào)試功能。
XHR Breakpoints演示
我們可以通過(guò)“XHR Breakpoints”右側(cè)的“+”號(hào)為異步斷點(diǎn)添加斷點(diǎn)條件,當(dāng)異步請(qǐng)求觸發(fā)時(shí)的URL滿(mǎn)
足此條件,JS邏輯則會(huì)自動(dòng)產(chǎn)生斷點(diǎn)。演示動(dòng)畫(huà)中并沒(méi)有演示到斷點(diǎn)位置,這是因?yàn)?#xff0c;演示使用的是
jQuery封裝好的ajax方法,代碼已經(jīng)過(guò)壓縮,看不到什么效果,而事實(shí)上XHR斷點(diǎn)的產(chǎn)生位置
是”xhr.send()”語(yǔ)句。
XHR斷點(diǎn)的強(qiáng)大之處是可以自定義斷點(diǎn)規(guī)則,這就意味著我們可以針對(duì)某一批、某一個(gè),乃至所有異步請(qǐng)
求進(jìn)行斷點(diǎn)設(shè)置,非常強(qiáng)大。但是,似乎這個(gè)功能在日常開(kāi)發(fā)中用得并不多,至少我用得不多。想想原
因大概有兩點(diǎn):其一,這類(lèi)型的斷點(diǎn)調(diào)試需求在日常業(yè)務(wù)中本身涉及不多;其二,現(xiàn)階段的前端開(kāi)發(fā)大
多基于JS框架進(jìn)行,最基本的jQuery也已經(jīng)對(duì)Ajax進(jìn)行了良好封裝,極少有人自己封裝Ajax方法,而項(xiàng)
目為了減少代碼體積,通常選擇壓縮后的代碼庫(kù),使得XHR斷點(diǎn)跟蹤相對(duì)不那么容易了。
Event Listener Breakpoints
事件監(jiān)聽(tīng)器斷點(diǎn),即根據(jù)事件名稱(chēng)進(jìn)行斷點(diǎn)設(shè)置。當(dāng)事件被觸發(fā)時(shí),斷點(diǎn)到事件綁定的位置。事件監(jiān)聽(tīng)
器斷點(diǎn),列出了所有頁(yè)面及腳本事件,包括:鼠標(biāo)、鍵盤(pán)、動(dòng)畫(huà)、定時(shí)器、XHR等等。極大的降低了事件
方面業(yè)務(wù)邏輯的調(diào)試難度。
事件監(jiān)聽(tīng)器斷點(diǎn)演示
演示實(shí)例演示了當(dāng)click事件被觸發(fā)時(shí)和當(dāng)setTimeout被設(shè)置時(shí)的斷點(diǎn)效果。實(shí)例顯示,當(dāng)選中click事
件斷點(diǎn)之后,兩個(gè)按鈕的被點(diǎn)擊時(shí)都觸發(fā)了斷點(diǎn),而當(dāng)setTimeout被設(shè)置時(shí),“Set Timer”斷點(diǎn)被觸發(fā)
。
調(diào)試,是在項(xiàng)目開(kāi)發(fā)中非常重要的環(huán)節(jié),不僅可以幫助我們快速定位問(wèn)題,還能節(jié)省我們的開(kāi)發(fā)時(shí)間。
熟練掌握各種調(diào)試手段,定當(dāng)為你的職業(yè)發(fā)展帶來(lái)諸多利益,但是,在如此多的調(diào)試手段中,如何選擇
一個(gè)適合自己當(dāng)前應(yīng)用場(chǎng)景的,這需要經(jīng)驗(yàn),需要不斷嘗試積累。
========
淺談 jQuery 事件源碼定位問(wèn)題
http://www.jb51.net/article/51212.htm在一個(gè)不是自己寫(xiě)的頁(yè)面上,如何快速定位到他綁定的事件代碼在哪,下面為大家簡(jiǎn)單的介紹下,需要的
朋友可以參考下
昨天群里有人問(wèn)了個(gè)事件源碼定位的問(wèn)題,簡(jiǎn)單描述下是這樣的。
在一個(gè)不是自己寫(xiě)的頁(yè)面上,如何快速定位到他綁定的事件代碼在哪?(頁(yè)面用的是jQuery)
這個(gè)問(wèn)題,說(shuō)難不難,說(shuō)簡(jiǎn)單也沒(méi)那么簡(jiǎn)單,萬(wàn)一用的是委托之類(lèi)也會(huì)麻煩點(diǎn)。
在 chrome 的控制臺(tái)里有個(gè) Event Listeners,這里會(huì)顯示你所選擇元素的事件,如果是原生事件,他
會(huì)直接顯示,
你點(diǎn)擊一下事件就會(huì)跳到對(duì)應(yīng)代碼里了,可是 jQuery 綁定的事件卻不是這樣的,你點(diǎn)擊后只會(huì)跳到?
jQuery 源碼里,
min后的jQuery源碼密密麻麻的,看著都眼花。
關(guān)于jQuery對(duì)于事件的管理,大牛們也分析的非常透徹了,我就不啰嗦了,因?yàn)椴皇俏覀兘裉煲f(shuō)的重
點(diǎn)。
我們要說(shuō)的重點(diǎn)是怎么定位到事件源碼處。因?yàn)閖Query版本眾多,而且重構(gòu)過(guò)多次,所以要分情況來(lái)說(shuō)
了。
基本上 1.2.6-1.8 和 1.9 兩種情況,經(jīng)過(guò)測(cè)試,大體上定為下面2個(gè)版本
1.2.6-1.8 用 ?$.data( elem, "events", undefined, true );?
1.9+ 用 ?$._data( elem, "events" );?
PS: 你現(xiàn)在也可以按 F12 打開(kāi)控制臺(tái)看看結(jié)果,當(dāng)然也可以復(fù)制下面的源碼自己測(cè)試。
由于谷歌被墻的厲害,所以把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; // 函數(shù)句柄
?
? ? 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); // 釋放控制權(quán)
? ? ? ? jqver = jq.fn.jquery; // 當(dāng)前 jquery 版本
? ? ? ? fn = new Function('ver_' + jqver.replace(/\./g, "_"), ''); // 生成類(lèi)似 function?
(ver_1_9_0) {} 這樣的函數(shù)
? ? ? ? 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>
如果不出意外,你可以在控制臺(tái)看到這樣的顯示結(jié)果
展開(kāi)后可以看到綁定的函數(shù)參數(shù)里的版本和當(dāng)前版本是對(duì)應(yīng)的。
?
可以看到
1.2.6-1.4 只支持 ?$.data( elem, "events", undefined, true );?
1.5-1.8 兩者都支持
1.9-1.11 只支持 ?$._data( elem, "events" );?
那么我們可以寫(xiě)個(gè)函數(shù)簡(jiǎn)單的兼容下,然他全兼容即可
?
function lookEvents (elem) {
? return $.data ? $.data( elem, "events", undefined, true ) : $._data( elem, "events" );
}
現(xiàn)在調(diào)用 lookEvents 就可以得到對(duì)應(yīng)的 events 對(duì)象了。
雖然可以看到了我們綁定的自定義事件,但還是不知道他在哪個(gè)文件哪一行啊。
下面我們就來(lái)定位他的具體位置,我們就拿 1.7 的試試。
PS: 下面操作都是在控制臺(tái)完成,我的環(huán)境是 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事件的第一個(gè)事件源碼地址
復(fù)制到控制臺(tái),按回車(chē)運(yùn)行后,不出意外可以看到下面這個(gè)結(jié)果。
有沒(méi)有看到右下角的 1.html:36 這個(gè)就是源碼所在的文件和對(duì)應(yīng)的行號(hào)了。
你可以直接點(diǎn)擊 1.html:36 跳到對(duì)應(yīng)的代碼處,是不是覺(jué)得很給力啊。
上面方法適用于 1.5+ 版本的 jQuery,對(duì)于 1.2.6-1.4 的版本,稍微有點(diǎn)不同,不過(guò)也非常簡(jiǎn)單。
function lookEvents (elem) { return $.data ? $.data( elem, "events", undefined, true ) :?
$._data( elem, "events" );}var event = lookEvents($("#testbtn")[0]); // 獲取綁定的事件
event.click; // 查看有幾個(gè)click事件,如果要查看其他事件直接輸入 event 然后回車(chē)即可
上面看到的編碼就是對(duì)應(yīng)事件句柄了,比如我這的 1,2 事件(如下圖顯示), 這個(gè)編號(hào)不是按順序的,
這個(gè)要注意。
?event.click[1] // 獲取click事件的 id是1 的事件源碼地址?
不出意外可以看到下面這個(gè)結(jié)果。
從操作來(lái)說(shuō),不管是 1.2.6-1.4 還是 1.5+ 版本 都差不多,只是 1.5+ 利用數(shù)組模式管理函數(shù)句柄了
,比較方便。
好了,該說(shuō)的都說(shuō)完了,小伙伴們各種測(cè)試起來(lái)吧。
========
JSFiddle:在線(xiàn)JS代碼調(diào)試工具
http://www.egouz.com/topics/7865.html英文網(wǎng)址:http://jsfiddle.net/英文網(wǎng)址
JSFiddle:在線(xiàn)JS代碼調(diào)試工具是一個(gè)老牌的支持javascript、css、html代碼可視化在線(xiàn)調(diào)試工具,支
持多種應(yīng)用多種主流框架,用起來(lái)非常方便,而且還可以將調(diào)試好的結(jié)果以非常簡(jiǎn)潔的頁(yè)面直接嵌入在
其他網(wǎng)頁(yè)里。
JSFiddle:在線(xiàn)JS代碼調(diào)試工具
對(duì)于網(wǎng)頁(yè)設(shè)計(jì)師來(lái)說(shuō)需要寫(xiě)演示用的JavaScript實(shí)例代碼的時(shí)候,就完全可以在jsFiddle里面直接完成
編寫(xiě)后調(diào)試,再將結(jié)果直接嵌入Blog正文里即可了,真的是很方便的選擇。
除了可以調(diào)試代碼外,還可以方便的發(fā)布到社區(qū),論壇或者社交媒體上與朋友們分享或者提問(wèn)。整合了
很多的不同的類(lèi)庫(kù)供大家選擇。 類(lèi)似的工具還有jsbin.com,也非常不錯(cuò)。
========
http://runjs.cn/
RunJS - 在線(xiàn)編輯、展示、分享、交流你的 JavaScript 代碼========
總結(jié)
- 上一篇: js调试学习总结
- 下一篇: 数据结构学习工具总结