JavaScript代碼調試
JavaScript 調試
沒有調試工具是很難去編寫 JavaScript 程序的;你的代碼可能包含語法錯誤,邏輯錯誤,如果沒有調試工具,這些錯誤比較難於發現;通常,如果 JavaScript 出現錯誤,是不會有提示信息,這樣你就無法找到代碼錯誤的位置
JavaScript 調試工具
在程序代碼中尋找錯誤叫做代碼調試。調試很難,但幸運的是,很多瀏覽器都內置了調試工具;內置的調試工具可以開始或關閉,嚴重的錯誤信息會發送給用戶
瀏覽器啟用調試工具一般是按下 F12 鍵,然後通過console調試
console方法
Console 是用於顯示 JS和 DOM 對象信息的單獨窗口。並且向 JS 中注入1個 console 對象,使用該對象 可以輸出信息到 Console 窗口中
有了調試工具,我們就可以設置斷點 (代碼停止執行的位置), 且可以在代碼執行時檢測變量
console對象的方法,都可以使用printf風格的占位符。不過,占位符的種類比較少,隻支持字符(%s)、整數(%d或%i)、浮點數(%f)和對象(%o)四種
console.log("%d年%d月%d日",2011,3,26);
console.log("圓周率是%f",3.1415926);
%o占位符,可以用來查看一個對象內部情況
還有一種特殊的標示符%c,對輸出的文字可以附加特殊的樣式,當進行大型項目開發的時候,代碼中可能有很多其他開發者添加的控製台語句
var dog = {};
dog.name = "大毛";
dog.color = "黃色";
console.log("%o", dog);
console.log(object[, object, ...])
使用頻率最高的一條語句:向控製台輸出一條消息。支持 C 語言 printf 式的格式化輸出。當然,也可以不使用格式化輸出來達到同樣的目的:
var animal='frog', count=10;
console.log("The %s jumped over %d tall buildings", animal, count);
console.log("The", animal, "jumped over", count, "tall buildings");
console.debug(object[, object, ...])
向控製台輸出一條信息,它包括一個指向該行代碼位置的超鏈接。
console.info(object[, object, ...])
向控製台輸出一條信息,該信息包含一個表示“信息”的圖標,和指向該行代碼位置的超鏈接。
console.debug(object[, object, ...])
在控製台輸出一條消息,包含一個指向代碼調用位置的超鏈接。假如是直接在控製台輸入該命令,就不會出現超鏈接(和console.log()一樣)
console.warn(object[, object, ...])
在控製台輸出一條帶有“警告”圖標的消息和一個指向代碼調用位置的超鏈接
console.error(object[, object, ...])
在控製台輸出一條帶有“錯誤”圖標的消息和一個指向代碼調用位置的超鏈接。error 實際上和 throw new Error() 產生的效果相同,使用該語句時會向瀏覽器拋出一個 js 異常。
console.assert(expression[, object, ...])
接收至少兩個參數,第一個參數的值或返回值為false的時候,將會在控製台上輸出後續參數的值
console.assert(1 == 1, object); // 無輸出,返回 undefined
console.assert(1 == 2, object); // 輸出 object
var isDebug = false;
console.assert(isDebug,'為false時輸出的log信息...');
console.dir(object)
輸出一個對象的全部屬性(輸出結果類似於 DOM 麵板中的樣式)。直接將該DOM結點以DOM樹的結構進行輸出,可以詳細查對象的方法發展等等
var myObject = {
a:'1',
b:2,
c:true,
myFunc:function(){
alert('hello world');
}
};
console.dir(myObject);
console.dirxml(node)
用來顯示網頁的某個節點(node)所包含的html/xml代碼,輸出一個 HTML 或者 XML 元素的結構樹,點擊結構樹上麵的節點進入到 HTML 麵板
<table >
<tr>
<td>A</td>
<td>A</td>
<td>A</td>
</tr>
<tr>
<td>bbb</td>
<td>aaa</td>
<td>ccc</td>
</tr>
</table>
<script type="text/javascript">
window.onload = function () {
var mytable = document.getElementById(‘mytable‘);
console.dirxml(mytable);
}
</script>
console.trace()
console.trace()用來追蹤函數的調用過程。在大型項目尤其是框架開發中,函數的調用軌跡可以十分複雜,console.trace()方法可以將函數的被調用過程清楚地輸出到控製台上
function tracer(a) {
console.trace();
return a;
}
function foo(a) {
return bar(a);
}
function bar(a) {
return tracer(a);
}
var a = foo('tracer');
console.group(object[, object, ...])
這是個有趣的方法,它能夠讓控製台輸出的語句產生不同的層級嵌套關係,每一個console.group()會增加一層嵌套,相反要減少一層嵌套可以使用console.groupEnd()方法
console.log('這是第一層');
console.group();
console.log('這是第二層');
console.log('依然第二層');
console.group();
console.log('第三層了');
console.groupEnd();
console.log('回到第二層');
console.groupEnd();
console.log('回到第一層');
和console.group()相似的方法是console.groupCollapsed()作用相同,不同點是嵌套的輸出內容是折疊狀態,在有大段內容輸出的時候使用這個方法可以使輸出版麵不至於太長
console.groupEnd()
關閉最近一個由console.group打開的塊
console.group('aaa');
console.warn('aaa.aaa');
console.groupEnd();
console.group('bbb');
console.info('bbb.bbb');
console.groupEnd();
console.groupCollapsed()
同 console.group(); 區別在於嵌套塊默認是收起的。
console.time(name)
創建一個名字為name的計時器,當調用 console.timeEnd(name);並傳遞相同的 name 為參數時,計時停止,並輸出執行兩條語句之間代碼所消耗的時間(毫秒)。
console.timeEnd(name)
停止同名的計時器並輸出所耗時間(毫秒)
//第一種方法是用console.time來統計實例化1000000個對象所需時間
console.time('Array initialize');
var array = new Array(1000000);
for(var i = array.length-1;i>=0;i--){
array[i] = new Object();
};
console.timeEnd('Array initialize');
//第二種方法使用傳統的時間差相減來統計實例化1000000個對象所需的時間
var start = new Date().getTime();
var array1 = new Array(1000000);
for(var i = array.length-1;i>=0;i--){
array[i] = new Object();
};
console.log(new Date().getTime()-start);
console.profile([title])
這是個挺高大上的東西,可用於性能分析。在 JS 開發中,我們常常要評估段代碼或是某個函數的性能。在函數中手動打印時間固然可以,但顯得不夠靈活而且有誤差。借助控製台以及console.profile()方法我們可以很方便地監控運行性能;與 profileEnd() 結合使用,用來做性能測試,與 console 麵板上 profile 按鈕的功能完全相同。
頁麵加載過程的性能優化是前端開發的一個重要部分,使用控製台的 profiles 麵板可以監控所有 JS 的運行情況使用方法就像錄像機一樣,控製台會把運行過程錄製下來
console.profileEnd()
關閉Javascript性能測試開關並輸出報告
console.profile('Array initialize');
var array = new Array(1000000);
for(var i = array.length-1;i>=0;i--){
array[i] = new Object();
};
console.profileEnd('Array initialize');
在Profiles麵板裏麵查看就可以看到cpu相關使用信息
console.count([title])
當你想統計代碼被執行的次數時,輸出該行代碼被執行的次數,參數 title 將在輸出時作為輸出結果的前綴使用。
function myFunction(){
console.count('myFunction被執行的次數:');
}
myFunction();
myFunction();
myFunction();
console.table()
可將傳入的對象,或數組以表格形式輸出,相比傳統樹形輸出,這種輸出方案更適合內部元素排列整齊的對象或數組,不然可能會出現很多的 undefined
var obj = {
foo: {
name: 'foo',
age: '33'
},
bar: {
name: 'bar',
age: '45'
}
};
var arr = [
['foo', '33'],
['bar', '45']
];
console.table(obj);
console.table(arr);
console.timeLine和console.timeLineEnd配合一起記錄一段時間軸
console.clear()
清空控製台
控製台的一些快捷鍵
方向鍵盤的上下鍵
大家一用就知曉。比如用上鍵就相當於使用上次在控製台的輸入符號
$
命令返回最近一次表達式執行的結果,功能跟按向上的方向鍵再回車是一樣的
在頁麵右擊選擇審查元素,然後在彈出來的DOM結點樹上麵隨便點選,這些被點過的節點會被記錄下來,而$0會返回最近一次點選的DOM結點,以此類推,$1返回的是上上次點選的DOM節點,最多保存了5個,如果不夠5個,則返回undefined
Chrome 控製台中原生支持類jQuery的選擇器
也就是說你可以用$加上熟悉的css選擇器來選擇DOM節點
copy
通過此命令可以將在控製台獲取到的內容複製到剪貼板
keys和values
前者返回傳入對象所有屬性名組成的數據,後者返回所有屬性值組成的數組
var myObj = {name:'angela',sex:'female',hobby:'programs'};
keys(myObj);
values(myObj);
monitor & unmonitor
monitor & unmonitor
monitor(function),它接收一個函數名作為參數,比如function a,每次a被執行了,都會在控製台輸出一條信息,裏麵包含了函數的名稱a及執行時所傳入的參數。而unmonitor(function)便是用來停止這一監聽
function sayHello(name){
alert('hello,'+name);
}
monitor(sayHello);
sayHello('angular');
unmonitor(sayHello);
sayHello('haha');
也就是說在monitor和unmonitor中間的代碼,執行的時候會在控製台輸出一條信息,裏麵包含了函數的名稱a及執行時所傳入的參數。當解除監視(也就是執行unmonitor時)就不再在控製台輸出信息了
命令行
控製台的輸出麵板右邊,是控製台的輸入麵板(Chrome 調試工具對應為下方),在這裏除了可以運行常規的 javascript 代碼,還內置了相當數量的命令行可以輔助我們的調試工作,下麵是一些常用命令行的簡單介紹。
$(id)
返回一個給定 id 的元素。
$$(selector)
返回給定的 css 選擇器匹配到的一組元素。
$x(xpath)
返回給定的 XPath 表達式匹配到的一組元素。
$0
在 HTML 麵板中選中的元素。
$1
上一次在 HTML 麵板中選中的元素。
$n(index)
訪問最近 5 個被選中過的元素,index 的範圍: 0 – 4。
dir(object)
同 console.dir(object)。
dirxml(node)
同 console.dirxml(node)。
clear()
同 console.clear()。
inspect(object[, tabName])()
在合適的(或一個指定的) tab 中檢視一個對象。
keys(object)
返回一個對象的所有屬性的鍵。
values(object)
返回一個對象的所有屬性的值。
debug(fn)
在函數第一行添加一個斷點,使用 undebug(fn) 移除斷點。
monitor(fn)
開啟一個函數的調用日誌,使用 unmonitor(fn) 關閉該功能。非常有用的一個命令,但是它似乎並沒有很好地工作。
monitorEvents(object[, types])
開啟一個元素的某個事件(或所有事件)被觸發時的日誌記錄。用例如下:
monitorEvents($0,['click'])
上麵的命令行被執行後,將開啟當前在 HTML 麵板中被選中元素的 click 事件監控,一旦這個元素的 click 事件被觸發,事件對象將會在控製台輸出。如果不指定第二個參數,將對所有事件進行記錄。
profile([title])
同 console.profile([title])
設置斷點
在這裏,我們可以使用快捷鍵進行操作,常用的快捷鍵如下:
F9:添加/移除 斷點
F10:逐過程,即跳過該語句中的方法、表達式等
F11:逐語句調試,即單步調試,會跳入方法、表達式,進行逐語句的跟蹤調試
斷點調試是啥
斷點調試其實並不是多麼複雜的一件事,簡單的理解無外唿就是打開瀏覽器,打開sources找到js文件,在行號上點一下罷了
斷點怎麼打才合適
假設我們現在正在實現一個加載更多的功能出現了問題,點擊以後數據沒有加載出來,這時候我們第一時間想到的應該是什麼?
我最先想到的是,我點擊到底有沒有成功?點擊事件裏的方法有沒有運行?好,要想知道這個問題的答案,我們當然是在代碼中的點擊事件處添加一個斷點,然後做什麼呢?然後我們當然是回去點擊加載更多按鈕來確定是否有問題啦
debugger 關鍵字
這種方法很簡單,我們隻需要在進行調試的地方加入debugger關鍵字,然後當瀏覽器運行到這個關鍵字的時候,就會提示是否打開調試,我們選擇是就可以了。這種調試可以選擇調試工具,是新打開vs還是在現有的VS中調試,都可以選擇
debugger 關鍵字用於停止執行 JavaScript,並調用調試函數;這個關鍵字與在調試工具中設置斷點的效果是一樣的;如果沒有調試可用,debugger 語句將無法工作;下麵例子開啟 debugger ,代碼在第三行前停止執行
var x = 15 * 5;
debugger;
document.getElementbyId("demo").innerHTML = x;
主要瀏覽器的調試工具
通常,瀏覽器啟用調試工具一般是按下 F12 鍵,並在調試菜單中選擇 "Console"
各瀏覽器的步驟如下:
Chrome 瀏覽器
打開瀏覽器 - 在菜單中選擇工具 - 在工具中選擇開發者工具 - 最後,選擇 Console
Firefox 瀏覽器
打開瀏覽器 - 訪問頁麵:https://www.getfirebug.com - 按照說明安裝 Firebug
Internet Explorer 瀏覽器。
打開瀏覽器 - 在菜單中選擇工具 - 在工具中選擇開發者工具 - 最後,選擇 Console
Opera
打開瀏覽器 - Opera 的內置調試工具為 Dragonfly,詳細說明可訪問頁麵:https://www.opera.com/dragonfly/
Safari
打開瀏覽器 - 訪問頁麵:https://extentions.apple.com - 按說明操作:install Firebug Lite
最後更新:2017-05-03 21:49:06