你需要知道的 19 個 console 實用調試技巧!

大家好,我是 CUGGZ。

瀏覽器的開發者工具爲我們提供了強大的調試系統,可以用來查看 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 中,支持的佔位符格式如下:

可以看到,除了最基本的幾種類型之外,它還支持定義 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:

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 條件語句爲 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() 會佔用較多的內存,導致瀏覽器出現卡頓情況。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/MEg0MsIPbnSa5u6e6yOn7Q