快速入門:偵錯工具巡覽 (JavaScript)
本快速入門將示範如何巡覽 Visual Studio 偵錯工具,以及如何在工作階段中檢視程式狀態。
本快速入門適用於新近使用 Visual Studio 進行偵錯的開發人員,以及想要進一步了解在 Visual Studio 偵錯工作階段中巡覽的開發人員。但不涉及偵錯本身的技巧。範例程式碼中的函式只是設計用來說明本主題中所描述的偵錯程序。這些函式並不會採用應用程式或函式設計的最佳做法。實際上,您很快會發現函式和應用程式本身不會執行什麼動作。
本快速入門的各節已盡可能設計為獨立的小節,所以您可略過包含已熟悉資訊的任何小節。您也不需要建立範例應用程式。但是我們建議您這麼做,同時也已將其程序盡可能簡化。
**偵錯工具鍵盤快速鍵。**Visual Studio 偵錯工具中的巡覽功能已同時針對滑鼠和鍵盤進行最佳化。本主題中的許多步驟都包含以括號註記的鍵盤快速鍵。例如,(快速鍵:F5) 表示輸入按鍵 F5 可開始或繼續執行偵錯工具。
注意事項 |
---|
模組模式 Windows 市集應用程式常會使用 JavaScript「模組模式」(Module Pattern),將資料與函式封裝到一個頁面中。[模組] 模式會使用單一、自動執行且匿名的封閉區段,將頁面功能與全域命名空間區隔開。在此主題中,我們將該函式稱為「模組」(Module)。 |
本主題內容
您將學習如何:
建立範例應用程式
設定並執行至中斷點、逐步執行函式,以及檢查程式資料
逐步執行、跳過和跳離函式
設定條件式中斷點,執行到游標所在處,並將變數視覺化
在 [區域變數] 視窗中檢視變數資料
檢視物件的變數資料與原型鏈結
檢查範圍鏈結資料
使用 [呼叫堆疊] 視窗巡覽程式碼
建立範例應用程式
偵錯與程式碼息息相關,所以範例應用程式只會使用 Windows 市集應用程式的架構建立原始程式檔,您可以在此檔案中看見巡覽偵錯工作階段的運作方式,以及檢查程式狀態的方式。所有您將叫用的程式碼,都會從 default.js 檔案的 module 函式中呼叫。此時不會新增控制項,也不會處理任何事件。
**建立空白的 JavaScript Windows 市集應用程式。**開啟 Visual Studio。在首頁上,選擇 [新增專案] 連結。在 [新增專案] 對話方塊上,選擇 [已安裝] 清單中的 [JavaScript],然後選擇 [Windows 市集]。在專案範本清單中,選擇 [空白的應用程式]。Visual Studio 會建立新的方案和專案,並在程式碼編輯器中顯示 default.htm 檔案。
請注意載入頁面中的指令碼檔案。
base.js 與 ui.js 檔案會建立 Windows Library for JavaScript。Windows Library for JavaScript 是一組 JavaScript 與 CSS 檔案,可讓您輕鬆使用 JavaScript 建立 Windows 市集應用程式。它可以與 HTML、CSS 和 Windows 執行階段搭配使用,以建立您的應用程式。
您的程式碼從 default.js 檔案開始。
**開啟 default.js 原始程式檔。**在 [方案總管] 中開啟 js 節點,然後選擇 default.js。
**以範例程式碼取代頁面內容。**從 default.js 檔案中刪除所有內容。依循此連結:偵錯工具導覽範例程式碼 (JavaScript),然後將 JavaScript 小節中所列的程式碼複製到剪貼簿。(在瀏覽器或說明檢視器中選擇 [上一頁],返回此快速入門頁面)。在 Visual Studio 編輯器中,將程式碼貼到目前空白的 default.js 中。選擇 Ctrl+ S 以儲存檔案。
您現在可以跟著本主題中的範例進行。
設定並執行至中斷點、逐步執行函式,以及檢查程式資料
要開始偵錯工作階段,最常見的方式是從 [偵錯] 功能表中選擇 [開始偵錯] (快速鍵:F5)。應用程式隨即開始執行,並持續執行到中斷點為止,若以手動方式暫停執行,就會發生例外狀況,或結束應用程式。
在偵錯工具中暫停執行時,將滑鼠停留在變數上方,可以在資料提示中檢視使用中變數的值。
暫停執行應用程式 (也稱為中斷偵錯工具) 之後,您可控制其餘程式碼的執行方式。您可以逐行繼續進行 (從函式呼叫移至函式本身),也可以在單一步驟中執行呼叫的函式。這些程序會在逐步執行應用程式時呼叫。您也可以繼續應用程式的標準執行,執行到您所設定的下一個中斷點,或執行到游標所在的程式碼行。您可以隨時停止偵錯工作階段。偵錯工具已設計成執行必要的清理作業並結束執行。
範例 1
在此範例中,您會在它呼叫我們的第一個使用者陳述式時,在 default.js 的 module 函式主體中設定中斷點。接著您會逐步執行函式、在偵錯工具的資料提示中檢視變數值,然後停止偵錯。
**設定中斷點。**在呼叫 app.start() 後緊接著會執行的陳述式 callTrack = "module function"; 中,設定中斷點。選擇原始程式碼編輯器之灰色邊框中的程式行 (快速鍵:將游標放在程式行上,然後選擇 F9 鍵)。
中斷點圖示會出現在邊框中。
**執行到中斷點。**在 [偵錯] 功能表上選擇 [開始偵錯] (快速鍵:F5),開始偵錯工作階段。
應用程式會開始執行,並在您設定中斷點的陳述式之前立即暫停執行。邊框中的目前程式碼行圖示會識別您的位置,而且目前的陳述式會反白顯示。
您現在便已掌控應用程式的執行,還可在逐步執行程式陳述式時檢查程式狀態。
**逐步執行函式。**在 [偵錯] 功能表上,選擇 [逐步執行] (快速鍵:F11)。
請注意,偵錯工具會移到下一行,而該程式行會呼叫 example1 函式。再次選擇 [逐步執行]。偵錯工具會移至 example1 函式的第一個程式碼行。反白顯示的程式行並未執行,但函式已在呼叫堆疊上載入,並且已配置區域變數的記憶體。
當您逐步執行一行程式碼時,偵錯工具會執行下列其中一個動作:
如果下一個陳述式不會呼叫方案中的函式,則偵錯工具會執行此陳述式、移到下一個陳述式,然後暫停執行。
在您的方案中,如果陳述式會呼叫函式,則偵錯工具會移至所呼叫之函式的第一行,然後暫停執行。
請繼續逐步執行 example1 的陳述式,直到您到達結束點為止。偵錯工具會反白顯示函式的右大括號。
**在資料提示中檢視變數值。**請繼續逐步執行 example1 的陳述式,直到您到達結束點為止。偵錯工具會反白顯示函式的右大括號。當您將滑鼠游標置於變數名稱上方時,此變數的名稱與值隨即顯示在資料提示中。
**為 callTrack 變數加入監看式。**在本快速入門中,callTrack 變數用來顯示在範例中呼叫的函式。為了更方便檢視此變數的值,請將該變數加入 [監看式] 視窗。在編輯器中選取變數名稱,然後從捷徑功能表中選擇 [加入監看式]。
您可以在監看式視窗中監看多個變數。每次暫停執行時,監看的變數值 (如資料提示視窗中的值) 都會進行更新。您監看的變數會跨偵錯工作階段儲存下來。
**停止偵錯。**在 [偵錯] 功能表上,選擇 [停止偵錯] (快速鍵:Shift+F5)。這麼做會結束偵錯工作階段。
逐步執行、跳過和跳離函式
相對於逐步執行父函式所呼叫的函式,跳過函式時會執行子函式,然後在父函式繼續時,暫停執行呼叫函式。當您很熟悉函式的運作方式並確定其執行不會影響您所調查的問題時,即可跳過此函式。
跳過一行不包含函式呼叫的程式碼時,會像逐步執行程式行一樣執行該程式行。
跳離子函式時會繼續執行函式,然後在函式回到其呼叫函式之後暫停執行。當您判斷長函式的其餘部分都不重要時,可以跳離該函式。
跳過和跳離函式時都會執行函式。
範例 2
在這個範例中,您會逐步執行、跳過和跳離函式。
**呼叫模組函式中的 example2 函式。**編輯 module 函式,並將 var callTrack = "module function" 之後的程式行取代為 example2();。
**執行到中斷點。**在 [偵錯] 功能表上選擇 [開始偵錯] (快速鍵:F5),開始偵錯工作階段。偵錯工具會在中斷點暫停執行。
**跳過程式碼行。**在 [偵錯] 功能表上,選擇 [跳過] (快速鍵:F10)。偵錯工具執行 var callTrack = "module function" 陳述式的方式,與逐步執行此陳述式的方式相同。
**逐步執行 example2 和 example2_a。**選擇 F11 鍵,逐步執行 example2 函式。繼續逐步執行 example2 陳述式,直到您到達程式行 var x = example2_a(); 為止。再次逐步執行這一行,以移至 example2_a 的進入點。繼續逐步執行 example2_a 的每個陳述式,直到您回到 example2 為止。
**跳過函式。**請注意,example2 的下一行 var y = example2_a(); 基本上與前一行相同。您可以放心地跳過這一行。選擇 F10 鍵,從繼續執行的 example2 移至這個第二次呼叫的 example2_a。請注意,callTrack 字串表示 example2_a 函式已執行兩次。
**跳離函式。**選擇 F11 鍵,逐步執行 example2_b 函式。請注意,example2_b 與 example2_a 差異不大。若要跳離函式,請選擇 [偵錯] 功能表上的 [跳離] (快速鍵:Shift+F11)。請注意,callTrack 變數表示 example2_b 已執行,而且偵錯工具已回到 example2 的繼續點。
**停止偵錯。**在 [偵錯] 功能表上,選擇 [停止偵錯] (快速鍵:Shift+F5)。這麼做會結束偵錯工作階段。
設定條件式中斷點,執行到游標所在處,並將變數視覺化
條件式中斷點可指定導致偵錯工具暫停執行的條件。此條件是由可評估為 true 或 false 的任何程式碼運算式所指定。例如,只有在變數達到特定值時,您才能使用條件式中斷點來檢查常呼叫之函式中的程式狀態。
執行到游標所在處就如同設定一次性中斷點。暫停執行時,您可以選取原始碼中的一行並繼續執行,直到您到達選取的程式碼行為止。例如,您可以逐步執行函式中的迴圈,並判斷迴圈中的程式碼是否正常執行。您可以執行到在迴圈執行後的游標所在處,而不用逐步執行迴圈的每一個反覆項目。
但是有時候,要在資料提示列或其他資料視窗中檢視變數值並不容易。偵錯工具可以在文字視覺化檢視中顯示字串、HTML 和 Xml,而文字視覺化檢視會在可捲動視窗中呈現值的格式化檢視。
範例 3
在這個範例中,您會設定條件式中斷點,在迴圈的特定反覆項目中斷,然後執行到迴圈之後的游標所在處。您也可以在文字視覺化檢視中檢視變數值。
**呼叫模組函式中的 example3 函式。**編輯 module 函式,並將 var callTrack = "module function"; 之後的程式行取代為程式行 example3();。
**執行到中斷點。**在 [偵錯] 功能表上選擇 [開始偵錯] (快速鍵:F5),開始偵錯工作階段。偵錯工具會在 module 函式中的中斷點暫停執行。
**逐步執行 example3 函式。**選擇 [偵錯] 功能表上的 [逐步執行] (快速鍵:F11),以移至 example3 函式的進入點。繼續逐步執行函式,直到您已反覆執行 for 區塊的一或兩個迴圈為止。請注意,逐步執行全部 1000 個反覆項目會花費較長的時間。
**設定條件式中斷點。**在程式碼視窗的左邊框中,以滑鼠右鍵按一下程式行 s += i.toString() + "\n";,然後在捷徑功能表上選擇 [條件]。
選取 [條件] 核取方塊,然後在文字方塊中輸入 i == 500;。選擇 [為 True] 選項,然後選擇 [確定]。此中斷點可讓您檢查位於 for 迴圈的第 500 個反覆項目的值。您可以藉由白色十字來識別條件式中斷點圖示。
**執行到中斷點。**在 [偵錯] 功能表上選擇 [繼續] (快速鍵:F5)。停留在 i 上,確認 i 的目前值為 500。另請注意,變數 s 是以單行表示,而且比資料提示視窗要長很多。
**顯示字串變數。**在 s 的資料提示中按一下放大鏡圖示。
[文字視覺化檢視] 視窗隨即出現,而字串值會呈現為多行的字串。
**執行至游標處。**選取程式行 callTrack += "->example3";,然後在捷徑功能表上選擇 [執行至游標處] (快速鍵:Ctrl+F10)。偵錯工具會完成迴圈反覆項目,然後在這一行暫停執行。
**停止偵錯。**在 [偵錯] 功能表上,選擇 [停止偵錯] (快速鍵:Shift+F5)。這麼做會結束偵錯工作階段。
使用 [執行至游標處] 回到您的程式碼,然後刪除中斷點
當您逐步執行來自 Microsoft 或協力廠商的程式庫程式碼時,「執行至游標處」相當有用。雖然逐步執行程式庫程式碼可能有其效益,但這通常較為耗時。再者,通常您較為關注自己的程式碼。本練習將示範其執行方式。
**在 app.start 呼叫中設定中斷點。**在 module 函式中的程式行 app.start() 上設定中斷點
執行至中斷點,然後逐步執行程式庫函式。
當您逐步執行 app.start() 時,編輯器會在 base.js 中顯示程式碼。多逐步執行幾行。
**跳過和跳離函式。**當您跳過 (F10) 及跳離 (SHIFT+F11) base.js 中的程式碼時,表示您可能認為檢查起始函式的複雜度與長度並不是您要執行的作業。
**將游標設定至您的程式碼並執行至該處。**在程式碼編輯器中切換回 default.js 檔案。選取 app.start() 之後的第一個程式碼行 (您無法執行至註解或空白行)。從捷徑功能表選擇 [執行至游標處]。偵錯工具會繼續執行 app.start 函式,並在中斷點暫停執行。
在 [區域變數] 視窗中檢視變數資料
[區域變數] 視窗是一個樹狀檢視,會就目前執行的函式顯示其範圍鏈結中的參數與變數。
檢視物件的變數資料與原型鏈結
**爲陣列物件加入模組函式。**編輯 module 函式,並將 var callTrack = "module function" 之後的程式行取代為 var myArray = new Array(1, 2, 3);。
**執行到中斷點。**在 [偵錯] 功能表上選擇 [開始偵錯] (快速鍵:F5),開始偵錯工作階段。偵錯工具會在中斷點暫停執行。逐步執行至程式行。
**開啟 [區域變數] 視窗。**在 [偵錯] 功能表上,指向 [視窗],然後選擇 [區域變數] (快速鍵:Alt+4)。
檢查模組函式中的區域變數 [區域變數] 視窗會將目前執行之函式 (module 函式) 的變數顯示為樹狀結構的最上層節點。當您輸入函式時,JavaScript 建立所有的變數,並爲其指定 undefined 值。在該函式中定義的函式,會有其文字形式的值。
**逐步執行 callTrack 與 myArray 定義。**在 [區域變數] 視窗中尋找 callTrack 與 myArray 變數。跳過 (F10) 這兩個定義,並留意 [値] 與 [類型] 欄位已有所變更。[區域變數] 視窗會反白顯示自前次中斷後有所變更的變數値。
檢查 myArray 物件 展開 myArray 變數。陣列的每個項目都會列出。[prototype] 節點會包含 Array 物件的繼承階層。請展開這個節點。
[方法] 節點會列出 Array 物件的所有方法。
[prototype] 節點會包含衍生出 Array 之 Object 物件的原型。[prototype] 節點是可遞迴的。物件階層的各個父物件會分別說明於其子系的 [prototype] 節點中。
**停止偵錯。**在 [偵錯] 功能表上,選擇 [停止偵錯] (快速鍵:Shift+F5)。這麼做會結束偵錯工作階段。
檢查範圍鏈結資料
函式的「範圍鏈結」(Scope Chain) 會包含所有可供函式取用的作用中變數。全域變數是範圍鏈結的一部分,如同定義目前執行之函式的函式中所定義的任何物件 (包括函式) 一般。例如,default.js 的 module 函式中所定義的 callTrack 變數,可供任何定義於 module 函式中的函式取用。每個範圍會個別列示於 [區域變數] 視窗中。
目前執行之函式的變數會列示於視窗頂端。
範圍鏈結中各個函式範圍的變數,會列示於函式的 [Scope] 節點下方。範圍函式會依照它們在鏈結中的順序列出,從定義目前函式的函式列示到鏈結的最外層函式。
[Globals] 節點會列出在任何函式以外定義的全域物件。
範圍鏈結可能不容易了解,最好能以範例說明。在下列範例中,您可以看到 module 函式如何建立本身的範圍,以及您如何藉由建立封閉區段來建立另一個範圍層級。
範例 4
**呼叫模組函式中的 example4 函式。**編輯 module 函式,並將 var callTrack = "module function" 之後的程式行取代為 example4():
**執行到中斷點。**在 [偵錯] 功能表上選擇 [開始偵錯] (快速鍵:F5),開始偵錯工作階段。偵錯工具會在中斷點暫停執行。
**開啟 [區域變數] 視窗。**如有需要,請在 [偵錯] 功能表上指向 [視窗],然後選擇 [區域變數] (快速鍵:Alt+4)。請注意,視窗中會列出 module 函式中的所有變數與函式,同時也會包含 [Globals] 節點。
**檢查全域變數。**展開 [Globals] 節點。Global 中的物件與變數由 Windows Library for JavaScript 所設定。您可以將自己的變數加入至全域範圍。
逐步執行 example4 並檢查其區域與範圍變數 逐步執行 (快速鍵:F11) example4 函式。由於 example4 定義於 module 函式中,因此 module 函式會成為父範圍。example4 可以呼叫 module 函式中的任何函式,並存取其變數。展開 [區域變數] 視窗中的 [Scope] 節點,並留意此節點包含相同的 module 函式及其變數。
逐步執行 example4_a 並檢查其區域與範圍變數 繼續逐步執行 example4 以及 example4_a 的呼叫。請注意,此時的區域變數來自於 example4_a,而 [Scope] 節點仍會保留 module 函式的變數。即使 example4 的變數是作用中變數,但已無法供 example4_a 取用,而且已不是範圍鏈結的一部分。
逐步執行 multipyByA 並檢查其區域與範圍變數 逐步執行其餘的 example4_a 以及程式行 var x = multilpyByA(b);。
函式變數 multipyByA 已設定為屬於「封閉區段」(Closure) 的 multiplyClosure 函式。multipyClosure 會定義並傳回內部函式 mulitplyXby,並擷取 (封閉) 其參數與變數。在封閉區段中,傳回的內部函式有權存取外部函式的資料,以建立其本身的範圍層級。
當您逐步執行 var x = multilpyByA(b); 時,您會移至 mulitplyXby 內部函式中的 return a * b; 程式行。
在 [區域變數] 視窗中,只有參數 b 會列示為 multiplyXby 中的區域變數,但會新增新的 [Scope] 層級。展開此節點後,您會看見其中包含 multiplyClosure 的參數、函式與變數,包括在 multiplyXby 的第一行中呼叫的 a 變數在內。快速檢查第二個 [Scope] 節點可呈現模組函式變數,此為 multiplyXby 在其下一行中存取的變數。
**停止偵錯。**在 [偵錯] 功能表上,選擇 [停止偵錯] (快速鍵:Shift+F5)。這麼做會結束偵錯工作階段。
使用 [呼叫堆疊] 視窗巡覽程式碼
呼叫堆疊是一種資料結構,其中包含與應用程式的目前執行緒中執行的函式相關的資訊。當您到達中斷點時,[呼叫堆疊] 視窗即會顯示堆疊上所有作用中函式的清單。目前執行的函式位於 [呼叫堆疊] 視窗清單的頂端。啟始執行緒的函式位於清單底部。介於兩者之間的函式會顯示啟始函式到目前函式的呼叫路徑。
除了顯示目前執行之函式的呼叫路徑以外,[呼叫堆疊] 視窗也可用來巡覽程式碼編輯器中的程式碼。當您處理多個檔案而想要快速移至特定函式時,這項功能可能很有幫助。
範例 5
在此範例中,您會逐步執行包含五個使用者定義函式的呼叫路徑。
**呼叫模組函式中的 example5 函式。**編輯 module 函式,並將 var callTrack = "module function"; 之後的程式行取代為程式行 example5();。
**執行到中斷點。**在 [偵錯] 功能表上選擇 [開始偵錯] (快速鍵:F5),開始偵錯工作階段。偵錯工具會在模組函式中的中斷點暫停執行。
**開啟 [呼叫堆疊] 視窗。**在 [偵錯] 功能表上選擇 [視窗],然後選擇 [呼叫堆疊] (快速鍵:Alt+7)。請注意,[呼叫堆疊] 視窗會顯示兩個函式:
[全域程式碼] 是位於呼叫堆疊底部之 module 函式的進入點。
[匿名函式] 會顯示 module 函式中暫停執行處的程式行。這是呼叫堆疊的頂端。
**逐步執行函式到 example5_d 函式。**在 [偵錯] 功能表上選擇 [逐步執行] (快速鍵:F11),以執行呼叫路徑中的呼叫,直到您到達 example5_d 函式的進入點為止。請注意,每當函式呼叫另一個函式時,都會儲存呼叫函式的行號,並將所呼叫函式置於堆疊頂端。呼叫函式的行號即為呼叫函式暫停執行的位置。目前執行的函式會以黃色箭號指出。
**使用 [呼叫堆疊] 視窗巡覽至 example5_a 程式碼,並設定中斷點。**在 [呼叫堆疊] 視窗中選取 example5_a 清單項目,然後選擇捷徑功能表上的 [移至原始檔]。程式碼編輯器會將其游標設定於函式的傳回行上。請在此行上設定中斷點。請注意,目前執行的程式行不會變更。只有編輯器游標會移動。
**逐步執行函式,然後執行至中斷點。**繼續逐步執行 example5_d。請注意,當您從函式返回時,該函式已從呼叫堆疊中移出。按 F5 繼續執行程式。您會在前一個步驟中建立的中斷點停止執行。
**停止偵錯。**在 [偵錯] 功能表上,選擇 [停止偵錯] (快速鍵:Shift+F5)。這麼做會結束偵錯工作階段。