日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

 

大家好,我是前端西瓜哥。本文講解如何使用瀏覽器提供的工具進(jìn)行 JS 代碼的斷點(diǎn)調(diào)試。

debugger

在代碼中需要打斷點(diǎn)的地方,加上 debugger,表示一個(gè)斷點(diǎn)。瀏覽器代碼執(zhí)行到該位置時(shí),會(huì)停下來,進(jìn)入調(diào)試模式。

示例代碼:

function a() {
  let a_var = 'a';
  b(a_var);
}

function b(a_var_from_a) {
  debugger;
  console.log(global_var);
  let b_var = 'b';
  c();
}

function c() {
  let c_var = 'c';
}

let module_var = 'module';
var global_var = 'global';

a();

整體就是調(diào)用 a,然后 a 調(diào)用 b,b 調(diào)用 c,然后有各種作用域的變量。

記得打開開發(fā)者工具面板,沒打開的話,debugger 會(huì)靜默失敗。

下面是斷點(diǎn)后的樣子。

圖片

現(xiàn)在是 a 函數(shù)調(diào)用了 b 函數(shù),b 函數(shù)調(diào)用的時(shí)候用 debugger 加了個(gè)斷點(diǎn),于是我們就停在這里了。

此時(shí)上下文狀態(tài)和調(diào)用站會(huì)保留著,方便我們排查是什么分支導(dǎo)致變量狀態(tài)錯(cuò)誤,比如一個(gè)錯(cuò)誤的條件判斷,讓一個(gè)為 null 的變量沒能變成一個(gè)普通對(duì)象,導(dǎo)致訪問它的屬性報(bào)錯(cuò)。

手動(dòng)打斷點(diǎn)

在對(duì)應(yīng)的行號(hào)點(diǎn)一下就可以了,相當(dāng)于加了個(gè) debugger 關(guān)鍵字。

圖片

刷新頁(yè)面后,手動(dòng)打的斷點(diǎn)還會(huì)保留。

調(diào)用棧信息

首先是函數(shù)調(diào)用棧信息。

圖片

調(diào)用的起始端是一個(gè)匿名函數(shù),沒有名字的函數(shù)都會(huì)顯示 anonymouse,這里是 script 最外層的直接調(diào)用,所以沒有名字。我本人建議多給匿名函數(shù)起個(gè)名字,可讀性會(huì)更好。但如果你有起名困難癥,不起也好。

匿名函數(shù),然后調(diào)用了函數(shù) a,函數(shù) a 再調(diào)用了函數(shù) b,然后停下了。之后還會(huì)調(diào)用 c。

看到 b 旁邊的藍(lán)色箭頭沒,它表示我們 正在觀測(cè)哪個(gè)函數(shù)的上下文,默認(rèn)會(huì)選擇棧頂。

你可以用光標(biāo)選擇你要觀測(cè)的函數(shù)下的變量,并且會(huì)高亮對(duì)應(yīng)的代碼。

圖片

作用域

我們看看某個(gè)函數(shù)的函數(shù)作用域的上下文。

找到 Scope 這個(gè)標(biāo)簽頁(yè),目前我們可以看到有三種類型:Local、Script 和 Global。

首先是 Local,本地作用域。這里對(duì)應(yīng) b 函數(shù)的上下文,可以看到(1)傳入的變量,(2)函數(shù)內(nèi)部聲明的變量,以及 (3)this 值。

然后是 Script,表示一個(gè)模塊文件的最外層變量,和全局變量不同,只能被模塊文件內(nèi)的文件的代碼訪問。

最后是 Global,全局作用域。

圖片

再補(bǔ)充一個(gè)比較常見的閉包作用域。如果一個(gè)函數(shù)是通過閉包產(chǎn)生的,那在 Local 和 Script 還會(huì)有一個(gè)閉包作用域。

圖片

在函數(shù)中訪問一個(gè)變量,其實(shí)就是沿著這條鏈路去查找最先找到的那個(gè),如果找不到就會(huì)拿到 undefined。

當(dāng)然除了這些,還有不少,比如塊作用域(Block)、捕獲作用域(Catch Block)、Eval 作用域、With 塊作用域等,篇幅原因,不一一介紹了。

執(zhí)行下一步

實(shí)際我們還要看看代碼是否如預(yù)期進(jìn)入我們希望的分支并拿到正確的值,所以需要 讓代碼一點(diǎn)點(diǎn)執(zhí)行下去,觀察狀態(tài)的變化。

瀏覽器提供了各種執(zhí)行下一步代碼的方式。

圖片

我們一個(gè)個(gè)過一遍。

Resume 恢復(fù)腳本執(zhí)行

首先是最左邊這個(gè) 矩形+三角形 的藍(lán)色按鈕,它表示 結(jié)束當(dāng)前斷點(diǎn),恢復(fù)腳本運(yùn)行。

圖片

但如果往下執(zhí)行,又遇到一個(gè)斷點(diǎn),那又會(huì)進(jìn)入調(diào)試模式。

于是在長(zhǎng)循環(huán)的情況下,就出不來了(悲)。

圖片

這時(shí)候惱羞成怒的西瓜哥有個(gè)辦法,長(zhǎng)按這個(gè)按鈕,然后出現(xiàn)一個(gè)停止按鈕,點(diǎn)它會(huì) 結(jié)束所有的斷點(diǎn)

或者更常見的做法是,只在特定判斷條件下的打斷點(diǎn),比如:

todoItems.forEach(item => {
  // item 不可能為 null,我們來看看發(fā)生甚么事了
  if (!item) {
    debugger;
  }
  // ...
})
 

Step over 跳過下一個(gè)函數(shù)

然后是跳過下一個(gè)函數(shù)。就是遇到下一個(gè)要執(zhí)行的函數(shù),就不進(jìn)去了,執(zhí)行完它繼續(xù)往下運(yùn)行。

圖片

為什么要跳過函數(shù)?因?yàn)楹瘮?shù)里面有很多代碼,或者里面又調(diào)用了其他函數(shù),要走好久才能回到當(dāng)前函數(shù)。

如果我們只是想看當(dāng)前函數(shù)的完整邏輯,那就跳過其下的函數(shù)執(zhí)行。

Step into 進(jìn)入下一個(gè)函數(shù)

如果走著走著遇到一個(gè)函數(shù),進(jìn)入這個(gè)函數(shù)。

圖片

注意,瀏覽器環(huán)境自帶的 api 方法是進(jìn)不去的。

Step out 跳出當(dāng)前函數(shù)

如果你不想再看當(dāng)前函數(shù)的執(zhí)行了,想回到調(diào)用它的函數(shù),就可以選擇這個(gè)方式。

圖片

Step 下一步

就是普通的下一步,它會(huì)嚴(yán)格遵守代碼的執(zhí)行順序,比較常用。

圖片

Step into 和 Step 的區(qū)別

Step into 和 Step 在大體的表現(xiàn)上有些相同,遇到函數(shù)是會(huì)進(jìn)入函數(shù)內(nèi)部的,但在異步代碼下,行為有一些不同。

Step into 在遇到一個(gè)異步代碼的回調(diào)函數(shù),會(huì)直接掛起并讓后面的同步代碼繼續(xù)跑,直到這個(gè)異步函數(shù)被執(zhí)行,然后進(jìn)入這個(gè)函數(shù)。

而 Step 則符合代碼的執(zhí)行順序,先執(zhí)行后面的同步代碼,然后再執(zhí)行異步函數(shù)。

我們用一個(gè)實(shí)例演示一下。代碼為:

window.onclick = () => {
  debugger;
  setTimeout(() => {
    console.log('inside');
    console.log('p1', performance.now() / 1000);
  }, 2000);
  console.log('p2', performance.now() / 1000);
  console.log('p3', performance.now() / 1000);
};

 

Step into 的表現(xiàn):

圖片

可以看到,Step into 會(huì)等待異步函數(shù)被執(zhí)行,才進(jìn)入到函數(shù)內(nèi)部,然后停在它的首行。

然后是 Step:

圖片

Step 遵循正常的代碼執(zhí)行過程順序:先走完同步代碼,然后再進(jìn)入異步代碼。

直接跳到某一行

我們可能想直接跳到中間的一連串邏輯,直接走到后面的某一行,對(duì)此我們可以手動(dòng)跳轉(zhuǎn)。

具體做法是行號(hào)右鍵選擇 continue to here。

需要注意,這個(gè)地方必須是和當(dāng)前位置在同一個(gè)函數(shù)下,否則會(huì)等價(jià)于執(zhí)行了 Resume。

圖片

其他

關(guān)閉斷點(diǎn)功能

關(guān)閉斷點(diǎn)功能(deactivate breakpoint)。

開啟這個(gè),斷點(diǎn)在打開開發(fā)者工具的條件下無效。

圖片

上一篇文章西瓜哥說了一個(gè)用定時(shí)器不斷執(zhí)行 debugger 的方式,防止別人點(diǎn)點(diǎn)點(diǎn)看代碼是怎么執(zhí)行的。但這只能防小白,我們把這個(gè)開了就無視 debugger 關(guān)鍵字了。

報(bào)錯(cuò)時(shí)斷點(diǎn)

代碼報(bào)錯(cuò)時(shí),我們希望知道報(bào)錯(cuò)那瞬間的上下文。

此時(shí)我們可以開啟這個(gè)功能,在報(bào)錯(cuò)且沒有被捕獲時(shí),瀏覽器會(huì)給你打一個(gè)斷點(diǎn),然后你可以看看哪個(gè)變量出了問題。

圖片

還可以勾選這個(gè) Pause on caught exceptions,效果是錯(cuò)誤被捕獲時(shí),打斷點(diǎn):

圖片

結(jié)尾

光說不練假把式,西瓜哥建議你自己嘗試一番。

編程是一個(gè)實(shí)操性很強(qiáng)的學(xué)科,要自己動(dòng)手調(diào)試,這樣才能更好地理解掌握。

分享到:
標(biāo)簽:JS
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定