javascript
[转] 用Firebug调试JavaScript
轉(zhuǎn)載自:?http://blog.csdn.net/xmphoenix/article/details/6299898
在本章里,我們將討論Firebug提供的,以支持JavaScript的開發(fā)、調(diào)試、概覽、以及測試的各種工具。在這里我們將采用典型的 JavaScript用例的方式,并解釋如何使用Firebug來實現(xiàn)這些用例。在本章里,我們將討論以下主題:
- 命令行API及其功能
- 控制臺API
- 單步JavaScript調(diào)試
- 插入條件或無條件斷點
命令行API
在第2章“Firebug窗口概覽”中,我們已經(jīng)看到了如何使用命令行,這里,我們將討論的是命令行API提供的一些方法(methods)。這些方法將幫助我們調(diào)試JavaScript。下面是具體的描述與用法:
$(id)
這個方法類似于JavaScript中的document.getElementById()。它返回指定ID的單個元素。
我們將使用下面的HTML代碼來解釋$(id)方法。將這些代碼寫在一個HTML文件中,并用Firefox將其打開。
現(xiàn)在,當(dāng)我們在Firebug的命令行中執(zhí)行如下代碼,我們將看見如下的輸出窗口:
$("test_id")$$(選擇器)
這個方法返回由指定CSS選擇器匹配元素所組成的數(shù)組。
Tip
關(guān)于CSS選擇器更多的信息,可以參考這個鏈接:http://www.w3.org/TR/css3-selectors下面的HTML代碼片段顯示在其DOM樹上有四個HTML元素。我們將使用$$(選擇器)的方法來選擇全部四個元素:
下面的截圖顯示了在Firebug的命令行中執(zhí)行 $$('input') 之后的輸出結(jié)果:
Tip
為了在Firebug的單一命令行執(zhí)行代碼,你需要去掉“控制臺”標(biāo)簽下拉菜單中的“更大的命令行”選項選擇。$x(xpath)
此方法返回與給定的XPath表達(dá)式相匹配的元素的數(shù)組。
Tip
關(guān)于XPath更多的信息請參考:http://www.w3schools.com/xpath為了解釋此方法,我們將使用前面的HTML文件來講解。現(xiàn)在,當(dāng)我們在Firebug命令行執(zhí)行如下代碼,我們將在Firebug的控制臺標(biāo)簽頁看到輸出結(jié)果:
var objs = $x('html/body/input') console.log(objs[0].name) console.log(objs[1].name) console.log(objs[3].name) console.log(objs[3].name)Note
多行命令行:為了方便,Firebug提供了一個多行命令行編輯器。這是一個迷你編輯器,我們可以在其中輸入多行JavaScript命令,甚至輸入完整的JavaScript程序,并且我們可以即時執(zhí)行這些代碼。我們可以通過點擊控制臺標(biāo)簽頁內(nèi)右下角的紅色圖標(biāo)來打開這個多行編輯器。dir(對象)
這個方法打印出對象的所有屬性的交互清單。這個結(jié)果與我們在DOM標(biāo)簽頁內(nèi)看到的是一致的。
讓我們來看一下與我們在$$(選擇器)方法中使用過的HTML代碼。如果我們在Firebug的命令行中執(zhí)行下面的代碼,我們將會得到如下的輸出:
var objs = $x('html/body/input') dir(objs)dirxml(節(jié)點)
這個方法將打印一個HTML或XML元素的XML源碼樹。這個結(jié)果與我們在HTML標(biāo)簽頁內(nèi)看到的結(jié)果是一致的。我們可以在HTML標(biāo)簽頁內(nèi)點擊任意節(jié)點來觀察它。
使用相同的HTML文件,在Firebug的代碼行中執(zhí)行如下代碼將得到其XML源碼樹。下面的截圖顯示了在控制臺標(biāo)簽頁內(nèi)產(chǎn)生的輸出結(jié)果:
var obj = $$('body')[0] dirxml(obj)我們可以用$(id)選擇一個節(jié)點后,再將其傳遞給此方法,或者采用與此類似的其他獲取一個節(jié)點的方法。
默認(rèn)情況下,命令行表達(dá)式是與頁面的頂層窗口相關(guān)的。cd()方法將使我們可以使用頁面內(nèi)的框架窗口。
clear()
這個方法將對控制臺清屏。此方法提供的功能也可以通過點擊“清除”按鈕實現(xiàn),這個按鈕在控制臺標(biāo)簽頁的左上角。
inspect(object[, tabName])
這個方法讓我們可以用最適合的標(biāo)簽來檢查一個對象,或者使用與可選參數(shù)tabName相一致的標(biāo)簽。
可以使用的標(biāo)簽名字有HTML、CSS、SCRIPT,以及DOM。
現(xiàn)在,對我們已經(jīng)打開的HTML文檔,我們在Firebug的命令行中輸入下面代碼。輸出結(jié)果將顯示在HTML標(biāo)簽頁內(nèi),截圖如下:
inspect($$('input')[0], 'html')keys(object)
這個方法返回一個包含此對象所有屬性的名字的數(shù)組。
還是使用我們前面使用的HTML文件為例,執(zhí)行下面的代碼將顯示第一個input標(biāo)簽的全部屬性、實體、函數(shù)和常量:
keys($$('input')[0])values(object)
這個方法將返回一個包含該對象所有屬性值的數(shù)組。
執(zhí)行下面的代碼將顯示DOM樹中第一個input標(biāo)簽的所有屬性值。
values($$('input')[0])debug(fn)和undebug(fn)
這兩個方法將在函數(shù)的第一行增加或移除斷點。
我們將在后面第8章“AJAX開發(fā)”中學(xué)習(xí)這些方法的細(xì)節(jié)內(nèi)容。
monitor(函數(shù)名)和unmonitor(函數(shù)名)
這些方法被用來打開或關(guān)閉對一個函數(shù)所有調(diào)用的日志記錄。
通常,為了查看JavaScript中某個函數(shù)是否被調(diào)用,我們在其內(nèi)部設(shè)置alert()或console.log()方法。這是非常繁瑣的事情。首先,我們不得不在一個大的JavaScript文件中找到這個方法,然后我們需要添加alert或log方法。接下來,當(dāng)我們看到每樣事情都對了,我們需要從代碼中移除所有的這些日志聲明。
Firebug用巧妙的方式來處理這種監(jiān)視工作。為了判斷某個函數(shù)是否被調(diào)用,我們僅僅需要知道函數(shù)的名字就可以了。通過使用monitor()方法,我們可以跟蹤發(fā)現(xiàn)該函數(shù)被調(diào)用了多少次。我們將在控制臺上看到提示,告訴我們正在被監(jiān)視的函數(shù)是否被調(diào)用了。并且,它還會給我們一個指向函數(shù)腳本的鏈接。
我們以下面的代碼為例來進行討論,創(chuàng)建一個HTML文件,輸入以下代碼,并且用Firefox瀏覽器打開這個文件:
This is the body ;現(xiàn)在,在命令行輸入下面的代碼并且執(zhí)行:
monitor(function1)點擊本文檔中的按鈕“Invoke function1()”。我們將看到,無論何時只要調(diào)用了一次function1()函數(shù),Firebug就會在控制臺面板上顯示其日志記錄。如果我們在控制臺面板上點擊function1()的鏈接,將跳轉(zhuǎn)到function1()函數(shù)所在的行。
下面的代碼將取消對function1()函數(shù)的監(jiān)控:
unmonitor(function1)monitorEvents(object[, types])
此方法將開啟對發(fā)送到一個對象的所有事件的日志記錄。可選的參數(shù)類型指定只記錄特定的消息族。類型中最常使用的值是mouse和key。
全部可用類型包括:composition, context menu, drag, focus, form, key, load, mouse, mutation, paint, scroll, text, ui, 以及 xul。
unmonitorEvents(object[, types])
此方法關(guān)掉發(fā)送到某對象的所有事件的日志記錄。
監(jiān)視和取消監(jiān)視事件與日志事件是一樣的,關(guān)于日志事件我們已經(jīng)在前一章討論過。
讓我們考察全面使用的HTML文件。在命令行執(zhí)行下面的代碼并且點擊第一個按鈕:
monitorEvents($("button1"))下面的截圖顯示了事件監(jiān)控情況:
profile([title])和profileEnd()
這兩個方法用于開啟和關(guān)閉JavaScript概況器。可選參數(shù)title將作為概況報告的抬頭打印在文本中。
下面是在Firebug中啟動JavaScript概況器的三個方法:
- 在控制臺標(biāo)簽頁內(nèi)點擊“概況”按鈕
- 從JavaScript代碼中使用console.profile("Profiler Title")
- 從命令行中使用profile("Profiler Title")
為查看概況器產(chǎn)生的統(tǒng)計信息,輸入如下HTML代碼,并保存為HTML文件,然后在瀏覽器中打開此文件。按F12打開Firebug并且點擊“Start”按鈕。
Click this button to profile JavaScript下面截圖顯示了概況器產(chǎn)生的統(tǒng)計信息:
概況器的欄目與描述
- 函數(shù)(Function):此欄顯示每個函數(shù)的名字。
- 調(diào)用(Call):此欄顯示該函數(shù)被調(diào)用的次數(shù)。(在本例中l(wèi)oop()函數(shù)被調(diào)用了3次。)
- 百分比(Percent):此欄顯示每個函數(shù)消耗的時間百分比。
- 占用時間(Own Time):此欄顯示在某個函數(shù)中代碼所占用的時間。例如,foo()沒有自己的代碼。相反,它只是調(diào)用其他函數(shù)。因此,它的執(zhí)行時間占用大約是~0毫秒。如果你看本欄的某些值,我們在此函數(shù)內(nèi)添加一些循環(huán)。
- 時間(Time):此欄顯示函數(shù)從開始的地方到結(jié)束的地方執(zhí)行所花時間。例如,foo()沒有代碼。所以,它的執(zhí)行時間大約是~0毫秒,但是在這個函數(shù)里要調(diào)用其他函數(shù)。所以,其他函數(shù)執(zhí)行的全部時間是4.491毫秒。于是,這里顯示了4.54毫秒,這是三個loop()函數(shù)執(zhí)行的時間加上自身foo()函數(shù)執(zhí)行的時間之和。
- 平均時間(Avg):此欄顯示某個函數(shù)的平均執(zhí)行時間。如果我們僅僅調(diào)用一次這個函數(shù),我們將看不到差別。但如果此函數(shù)被調(diào)用了多次,我們將看出差別。計算公式如下:
平均時間=自身代碼執(zhí)行時間 / 調(diào)用次數(shù)
- 最小時間和最大時間(Min and Max columns):這里顯示的是函數(shù)的最小執(zhí)行時間。在我們的例子中,我們調(diào)用loop()三次。當(dāng)我們傳遞1000作為參數(shù)時,大約只消耗了很短時間(0.045秒),當(dāng)我們傳遞100000給此函數(shù)時,它消耗更長的時間(4.036秒)。所以,在本例中,最小時間將顯示0.045秒,而最大時間顯示為4.036秒。
- 文件(File):此欄顯示函數(shù)所在的文件的文件名,并顯示所在行數(shù)。
控制臺API
Firebug對所有加載的頁面增加了一個全局變量,命名為“console”。這個對象包括許多方法,這些方法使得我們可以向控制臺寫入信息,以揭示出腳本運行中的信息。
console.log(object[, objcet, ...])
這個方法向控制臺寫入一個消息。我們可以傳遞任意多的參數(shù),這些參數(shù)在一個空格分隔行內(nèi)被鏈接起來。
log的第一個參數(shù)也許是包含類似printf字符串替換模式的字符串。例如:
console.log("The %s jumped over %d tall buildings", animal, count);上面的例子可以用非字串替換的方式來重寫,效果一樣:
console.log("The", animal, "jumped over", count, "tall buildings");這兩個技術(shù)可以聯(lián)合起來用。如果我們使用字符串替換模式,但是給出的參數(shù)多過替換模式使用的參數(shù),其余的參數(shù)將附加在空格分隔行內(nèi),如下面的代碼所示:
console.log("I am %s and I have:", myName, thing1, thing2, thing3);如果對對象進行了日志記錄,這些對象顯示出來的就不止是靜態(tài)文本,還有交互式的超鏈接,這些鏈接分別指向Firebug中與該對象相關(guān)的HTML、CSS、腳本或DOM標(biāo)簽頁。我們也可以使用%o的模式在字符串中替換超鏈接。
下面是我們可以使用的字符串替代的全部模式:
Table�1.1.�
字符串
替換模式
%s
字符串
%d, %i
整數(shù)(還不支持格式化的數(shù)值)
%f
浮點數(shù)(還不支持格式化的數(shù)值)
%o
對象鏈接
console.debug(object[, object, ...])
此方法把一個消息寫到控制臺,這個消息包括了指向此方法被調(diào)用的行的超鏈接。
console.info(object[, object, ...])
此方法向控制臺寫入一個消息,這個消息帶有可視化的信息圖標(biāo)(info icon)、作色代碼、以及指向此方法被調(diào)用的行的超鏈接。
console.warn(object[, object, ...])
此方法向控制臺寫入一個消息,這個消息帶有可視化的警告圖標(biāo)、作色代碼、以及指向此方法被調(diào)用的行的超鏈接。
console.error(object[, object, ...])
此方法向控制臺寫入一個消息,這個消息帶有可視化的錯誤圖標(biāo)(error icon)、作色代碼、以及指向此方法被調(diào)用的行的超鏈接。
console.assert(expression[, object, ...])
此方法測試一個表達(dá)式是否為真,如果不是,它將向控制臺寫入一個消息,并拋出異常。
console.dir(object)
此方法打印出對象的所有屬性的交互式列表。看起來與我們在DOM標(biāo)簽頁中看到的視圖是一致的。
console.dirxml(node)
此方法打印HTML或XML元素的XML源代碼樹。這與我們在HTML標(biāo)簽頁中看到的是一致的。我們可以通過點擊節(jié)點在HTML標(biāo)簽頁內(nèi)檢查此節(jié)點。
console.trace()
此方法輸出Javascript代碼在被調(diào)用時所執(zhí)行交互式棧的跟蹤。
這個棧跟蹤列出了棧中的函數(shù)細(xì)節(jié),以及每一個傳遞給函數(shù)的參數(shù)值。通過點擊函數(shù),將轉(zhuǎn)到腳本標(biāo)簽頁內(nèi)相應(yīng)代碼的位置。并且,點擊參數(shù)值將可以查看其在DOM或HTML標(biāo)簽頁中的情況。
console.group(object[, object, ...])
此方法想控制臺寫入一個消息,并且以后向此控制臺寫入的消息都被縮進的嵌入一個塊中。調(diào)用console.groupEnd()可以關(guān)閉這個塊。
console.groupCollapsed(object[, object, ...])
這個方法類似于console.group(),只不過這個塊最初是折疊的。
console.groupEnd()
此方法關(guān)閉被console.group()或console.groupEnd()最近打開的塊。
console.time(name)
此方法用給定的名字創(chuàng)建一個新的計時器。用相同的名字調(diào)用console.timeEnd(名字)將停止計時器并且打印出所耗用的時間。
console.timeEnd(name)
此方法終止console.time(name)所創(chuàng)建的定時器,并打印出消耗的時間。
console.profile([title])
此方法啟用JavaScript概寫器。作為可選項的參數(shù)將會出現(xiàn)在概寫報告的頭部。
console.profileEnd()
此方法將關(guān)閉JavaScript概寫器并打印出報告。
console.count([title])
此方法將返回count被調(diào)用的代碼行的執(zhí)行時間。作為可選參數(shù)的標(biāo)題,將會在count所在行增加一個消息輸出。
Note
控制臺是一個附加到Web頁面的窗口對象上的對象。在Firebug中,這個對象僅僅在控制臺被啟用時附加。在Firebug Lite,如果Lite在此頁中已經(jīng)安裝,則控制臺就被附加上。JavaScript調(diào)試
本節(jié)介紹使用Firebug如果在內(nèi)部和外部調(diào)試JavaScript。在開始之前,先回憶一下前面章節(jié)所介紹的內(nèi)容:
- 腳本標(biāo)簽頁
- 命令行API
- 控制臺API
使用Mozilla的Firefox和Firebug來調(diào)試JavaScript是一個非常直觀的過程。如果我們是Visual Studio的開發(fā)者,我們將不會感到使用Firebug來調(diào)試JavaScript有什么不同,除了調(diào)試器是作為瀏覽器的一部分之外。
Firebug中單步調(diào)試JavaScript
在一個編輯器中輸入下列代碼,并保存為.html文件,然后使用Firefox打開它:
現(xiàn)在在瀏覽器中按F12來打開并激活Firebug。點擊“腳本”標(biāo)簽頁,并在第6行插入斷點,如下面的截圖所示:
Note
為了核實我們已經(jīng)插入斷點,我們可在腳本標(biāo)簽頁的右邊“斷點”面板中查看斷點列表。在第6行顯示一個大的紅點,表明這里插入了一個斷點。現(xiàn)在,點擊“Click Me!”按鈕來執(zhí)行JavaScript代碼。
一旦我們點擊,JavaScript將停在第6行,斷點所在的地方。
現(xiàn)在我們可以單步調(diào)試JavaScript,通過點擊在腳本標(biāo)簽頁下的這些按鈕來操作:繼續(xù)、單步進入、單步跳過、單步退出。
- 繼續(xù)(F8):只要腳本的執(zhí)行被另一斷點所終止,這個按鈕就使得我們可以繼續(xù)腳本執(zhí)行。
- 單步進入(F11):這個按鈕可以使我們單步進入另一個函數(shù)的內(nèi)部。
- 單步跳過(F10):這個按鈕使我們可以單步跳過函數(shù)調(diào)用。
- 單步退出:這個按鈕使我們可以繼續(xù)腳本的執(zhí)行并停在下一個斷點。
現(xiàn)在,我們點擊“單步跳過”并按F10執(zhí)行第6行并移動到第7行。注意右邊的“監(jiān)控”面板中的divElement的值。在執(zhí)行第6行之前該值是undefined,在執(zhí)行第6行之后,它被賦予一個HTML的div元素作為值。讓我們來看下面的截圖:
如果我們想要看看調(diào)用及執(zhí)行流的棧的情況,只需要點擊在腳本標(biāo)簽頁的右邊點擊“堆棧”標(biāo)簽。
總結(jié)
以上是生活随笔為你收集整理的[转] 用Firebug调试JavaScript的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【博客话题】我的2011项目总结
- 下一篇: dotNet中,取得指定日期所在月份的最