大家好,我是 Echa。之前給大家介紹了《H5移動端調試攻略——超實用》,有興趣的小夥們可以回過頭看看。
浏覽器的開發者工具為我們提供了強大的調試系統,可以用來檢視DOM樹結構、CSS樣式調試、動畫調試、JavaScript代碼斷點調試等。今天我們就來看看console調試的那些實用的調試技巧。
如今,我們項目的開發通常會使用React、Vue等前端架構,前端調試也變得更加有難度,除了使用React DevTools,Vue DevTools 等插件之外,我們使用最多的就是console.log()了,當然多數情況下,console.log() 就能滿足我們的需求,但是當資料變得比較複雜時,console.log() 就顯得有些單一。其實 console 對象提供了很多方法,下面是console對象包含的方法:
console 對象提供了浏覽器控制台調試的接口,我們可以從任何全局對象中通路到它,如果你平時隻是用console.log()來輸出一些變量,那你可能沒有用過console那些強大的功能。下面帶你用console玩玩花式調試。
一、基本列印
1. console.log()
console.log()就是最基本、最常用的用法了。它可以用在JavaScript代碼的任何地方,然後就可以浏覽器的控制台中看到列印的資訊。其基本使用方法如下:
let name = "CUGGZ";
let age = 18;
console.log(name) // CUGGZ
console.log(name, age) // CUGGZ 18
console.log("message:", name, age) // message: CUGGZ 18
除此之外,console.log()還支援下面這種輸出方式:
let name = "CUGGZ";
let age = 18;
let height = 180;
console.log('Name: %s, Age: %d', name, age) // Name: CUGGZ, Age: 18
console.log('Age: %d, Height: %d', age, height) // Age: 18, Height: 180
這裡将後面的變量指派給了前面的占位符的位置,他們是一一對應的。這種寫法在複雜的輸出時,能保證模闆和資料分離,結構更加清晰。不過如果是簡單的輸出,就沒必要這樣寫了。在console.log中,支援的占位符格式如下:
- 字元串:%s
- 整數:%d
- 浮點數:%f
- 對象:%o或%O
- CSS樣式:%c
可以看到,除了最基本的幾種類型之外,它還支援定義CSS樣式:
let name = "CUGGZ";
console.log('My Name is %cCUGGZ', 'color: skyblue; font-size: 30px;')
列印結果如下(好像并沒有什麼卵用):
這個樣式列印可能有用的地方就是列印圖檔,用來檢視圖檔是否正确:
console.log('%c ','background-image:url("http://iyeslogo.orbrand.com/150902Google/005.gif");background-size:120% 120%;background-repeat:no-repeat;background-position:center center;line-height:60px;padding:30px 120px;');
列印結果如下:
嚴格地說,console.log()并不支援列印圖檔,但是可以使用CSS的背景圖來列印圖檔,不過并不能直接列印,因為是不支援設定圖檔的寬高屬性,是以就需要使用line-heigh和padding來撐開圖檔,使其可以正常顯示出來。
我們可以使用console.log()來列印字元畫,就像知乎的這樣:
可以使用字元畫線上生成工具,将生成的字元粘貼到console.log()即可。線上工具:mg2txt。我的頭像生成效果如下,中間的就是生成的字元:
除此之外,可以看到,當占位符表示一個對象時,有兩種寫法:%c或者%C,那它們兩個有什麼差別呢?當我們指定的對象是普通的object對象時,它們兩個是沒有差別的,如果是DOM節點,那就有有差別了,來看下面的示例:
可以看到,使用 %o 列印的是DOM節點的内容,包含其子節點。而%O列印的是該DOM節點的對象屬性,可以根據需求來選擇性的列印。
2. console.warn()
console.warn() 方法用于在控制台輸出警告資訊。它的用法和console.log是完全一樣的,隻是顯示的樣式不太一樣,資訊最前面加一個黃色三角,表示警告:
const app = ["facebook", "google", "twitter"];
console.warn(app);
列印樣式如下:
3. console.error()
console.error()可以用于在控制台輸出錯誤資訊。它和上面的兩個方法的用法是一樣的,隻是顯示樣式不一樣:
const app = ["facebook", "google", "twitter"];
console.error(app);
需要注意,console.exception() 是 console.error() 的别名,它們功能是相同的。
當然,console.error()還有一個console.log()不具備的功能,那就是列印函數的調用棧:
function a() {
b();
}
function b() {
console.error("error");
}
function c() {
a();
}
c();
列印結果如下:
可以看到,這裡列印出來了函數函數調用棧的資訊:b→a→c。
console對象提供了專門的方法來列印函數的調用棧(console.trace()),這個下面會介紹到。
4. console.info()
console.info()可以用來列印資訊類說明資訊,它和console.log()的用法一緻,列印出來的效果也是一樣的:
二、列印時間
1. console.time() & console.timeEnd()
如果我們想要擷取一段代碼的執行時間,就可以使用console對象的console.time() 和console.timeEnd()方法,來看下面的例子:
console.time();
setTimeout(() => {
console.timeEnd();
}, 1000);
// default: 1001.9140625 ms
它們都可以傳遞一個參數,該參數是一個字元串,用來标記唯一的計時器。如果頁面隻有一個計時器時,就不需要傳這個參數 ,如果有多個計時器,就需要使用這個标簽來标記每一個計時器:
console.time("timer1");
console.time("timer2");
setTimeout(() => {
console.timeEnd("timer1");
}, 1000);
setTimeout(() => {
console.timeEnd("timer2");
}, 2000);
// timer1: 1004.666259765625 ms
// timer2: 2004.654052734375 ms
2. console.timeLog()
這裡的console.timeLog()上面的console.timeEnd()類似,但是也有一定的差别。他們都需要使用console.time()來啟動一個計時器。然後console.timeLog()就是列印計時器目前的時間,而console.timeEnd()是列印計時器,直到結束的時間。下面來看例子:
console.time("timer");
setTimeout(() => {
console.timeLog("timer")
setTimeout(() => {
console.timeLog("timer");
}, 2000);
}, 1000);
// timer: 1002.80224609375 ms
// timer: 3008.044189453125 ms
而使用console.timeEnd()時:
console.time("timer");
setTimeout(() => {
console.timeEnd("timer")
setTimeout(() => {
console.timeLog("timer");
}, 2000);
}, 1000);
列印結果如下:
可以看到,它會終止目前的計時器,是以裡面的timeLog就無法在找到timer計數器了。是以兩者的差別就在于,是否會終止目前的計時。
三、分組列印
1. console.group() & console.groupEnd()
這兩個方法用于在控制台建立一個資訊分組。一個完整的資訊分組以 console.group() 開始,console.groupEnd() 結束。來看下面的例子:
console.group();
console.log('First Group');
console.group();
console.log('Second Group')
console.groupEnd();
console.groupEnd();
列印結果如下:
再來看一個複雜點的:
console.group("Alphabet")
console.log("A");
console.log("B");
console.log("C");
console.group("Numbers");
console.log("One");
console.log("Two");
console.groupEnd("Numbers");
console.groupEnd("Alphabet");
列印結果如下:
可以看到,這些分組是可以嵌套的。目前我們需要調試一大堆調試輸出,就可以選擇使用分組輸出,
2. console.groupCollapsed()
console.groupCollapsed()方法類似于console.group(),它們都需要使用console.groupEnd()來結束分組。不同的是,該方法預設列印的資訊是折疊展示的,而group()是預設展開的。來對上面的例子進行改寫:
console.groupCollapsed("Alphabet")
console.log("A");
console.log("B");
console.log("C");
console.groupCollapsed("Numbers");
console.log("One");
console.log("Two");
console.groupEnd("Numbers");
console.groupEnd("Alphabet");
其列印結果如下:
可以看到,和上面方法唯一的不同就是,列印的結果被折疊了,需要手動展開來看。
四、列印計次
1. console.count()
可以使用使用console.count()來擷取目前執行的次數。來看下面的例子:
for (i = 0; i < 5; i++) {
console.count();
}
// 輸出結果如下
default: 1
default: 2
default: 3
default: 4
default: 5
它也可以傳一個參數來進行标記(如果為空,則為預設标簽default):
for (i = 0; i < 5; i++) {
console.count("hello");
}
// 輸出結果如下
hello: 1
hello: 2
hello: 3
hello: 4
hello: 5
這個方法主要用于一些比較複雜的場景,有時候一個函數被多個地方調用,就可以使用這個方法來确定是否少調用或者重複調用了該方法。
2. console.countReset()
顧名思義,console.countReset()就是重置電腦,它會需要配合上面的console.count()方法使用。它有一個可選的參數label:
- 如果提供了參數label,此函數會重置與label關聯的計數,将count重置為0。
- 如果省略了參數label,此函數會重置預設的計數器,将count重置為0。
console.count();
console.count("a");
console.count("b");
console.count("a");
console.count("a");
console.count();
console.count();
console.countReset();
console.countReset("a");
console.countReset("b");
console.count();
console.count("a");
console.count("b");
列印結果如下:
default:1
a:1
b:1
a:2
a:3
default:2
default:3
default:1
a:1
b:1
五、其他列印
1. console.table()
我們平時使用console.log較多,其實console對象還有很多屬性可以使用,比如console.table(),使用它可以友善的列印數組對象的屬性,列印結果是一個表格。console.table() 方法有兩個參數,第一個參數是需要列印的對象,第二個參數是需要列印的表格的标題,這裡就是數組對象的屬性值。來看下面的例子:
const users = [
{
"first_name":"Harcourt",
"last_name":"Huckerbe",
"gender":"Male",
"city":"Linchen",
"birth_country":"China"
},
{
"first_name":"Allyn",
"last_name":"McEttigen",
"gender":"Male",
"city":"Ambelókipoi",
"birth_country":"Greece"
},
{
"first_name":"Sandor",
"last_name":"Degg",
"gender":"Male",
"city":"Mthatha",
"birth_country":"South Africa"
}
]
console.table(users, ['first_name', 'last_name', 'city']);
列印結果如下:
通過這種方式,可以更加清晰地看到數組對象中的指定屬性。
除此之外,還可以使用console.table()來列印數組元素:
const app = ["facebook", "google", "twitter"];
console.table(app);
列印結果如下:
通過這種方式,我們可以更清晰的看到數組中的元素。
需要注意,console.table() 隻能處理最多1000行,是以它可能不适合所有資料集。但是也能适用于多數場景了。
2. console.clear()
console.clear() 顧名思義就是清除控制台的資訊。當清空控制台之後,會列印一句:“Console was clered”:
當然,我們完全可以使用控制台的清除鍵清除控制台:
3. console.assert()
console.assert()方法用于語句斷言,當斷言為 false時,則在資訊到控制台輸出錯誤資訊。它的文法如下:
console.assert(expression, message)
它有兩個參數:
- expression: 條件語句,語句會被解析成 Boolean,且為 false 的時候會觸發message語句輸出;
- message: 輸出語句,可以是任意類型。
該方法會在expression條件語句為false時,就會列印message資訊。當在特定情況下才輸出語句時,就可以使用console.assert()方法。
比如,當清單元素的子節點數量大于等于100時,列印錯誤資訊:
console.assert(list.childNodes.length < 100, "Node count is > 100");
其輸出結果如下圖所示:
4. console.trace()
console.trace()方法可以用于列印目前執行的代碼在堆棧中的調用路徑。它和上面的console.error()的功一緻,不過列印的樣式就和console.log()是一樣的了。來看下面的例子:
function a() {
b();
}
function b() {
console.trace();
}
function c() {
a();
}
c();
列印結果如下:
可以看到,這裡輸出了調用棧的資訊:b→a→c,這個堆棧資訊是從調用位置開始的。
5. console.dir()
console.dir()方法可以在控制台中顯示指定JavaScript對象的屬性,并通過類似檔案樹樣式的互動清單顯示。它的文法如下:
console.dir(object);
它的參數是一個對象,最終會列印出該對象所有的屬性和屬性值。
在多數情況下,使用consoledir()和使用console.log()的效果是一樣的。但是當列印元素結構時,就會有很大的差異了,console.log()列印的是元素的DOM結構,而console.dir()列印的是元素的屬性:
6. console.dirxml()
console.dirxml()方法用于顯示一個明确的XML/HTML元素的包括所有後代元素的互動樹。如果無法作為一個element被顯示,那麼會以JavaScript對象的形式作為替代。它的輸出是一個繼承的擴充的節點清單,可以讓你看到子節點的内容。其文法如下:
console.dirxml(object);
該方法會列印輸出XML元素及其後代元素,對于XML和HTML元素調用console.log()和console.dirxml()是等價的。
7. console.memory
console.memory 是 console 對象的一個屬性,而不是一個方法。它可以用來檢視目前記憶體的使用情況,如果使用過多的console.log()會占用較多的記憶體,導緻浏覽器出現卡頓情況。
如果你覺得有用的話,請點贊我,關注我,最後,感謝你的閱讀,程式設計愉快!