[譯] 你不知道的 console 命令

相比使用 console.log 去輸出值,咱們有更多的方式去調試 JavaScript。你覺得我要聊調試器麼?不不不你想錯了。

告訴寫 JavaScript 的人應該使用瀏覽器的調試器去調試代碼,這看來很不錯,而且確定有其適用的時間和場合。可是大多數時候你僅僅只想查看一段特定的代碼是否執行或者一個變量的值是什麼,而不是迷失在 RxJS 代碼庫或者一個 Promise 庫的深處。前端

然而,儘管 console.log 有其適用的場合,大多數人仍然沒有意識到 console 自己除了基礎 log 還有許多選擇。合理使用這些方法能讓調試更簡單、更快速,而且更加直觀。android

console.log()

不少人不知道經典的 console.log 其實有着豐富的函數特性。儘管大多數人只使用 console.log(object) 這種語法,但你仍然能寫 console.log(object, otherObject, string) 而且它會將全部東西都整齊的打印出來。有時候確實很方便。ios

不止那些,這兒還有另外一種格式:console.log(msg, values)。這個執行方式和 C 或者 PHP 的 sprintf 很類似。git

console.log('I like %s but I do not like %s.', 'Skittles', 'pus');
複製代碼

會準確的輸出你所預期的東西。github

> I like Skittles but I do not like pus.
複製代碼

通常的佔位符有 %o(這是字符 o,不是 0)表示一個對象,%s 表示一個字符串,以及 %d 表明一個小數或者整數。後端

你可能並不認爲另外一個有趣是 %c。實際上它是做爲 CSS 值的佔位符。數組

console.log('I am a %cbutton', 'color: white; background-color: orange; padding: 2px 5px; border-radius: 2px');
複製代碼

後面的值能夠一直添加,在這裏沒有「結束標籤」確實有點怪異。可是你能夠像這樣將它們隔開。瀏覽器

這並不優美,也不是特別的有用。固然這也不是真實的按鈕。bash

真的頗有用嗎?不太認同。ide

console.dir()

一般來看,console.dir() 功能和 log() 很是類似,儘管看起來有略微不一樣。

下拉小箭頭展現的對象信息和 console.log 的視圖裏同樣。可是在你觀察元素節點的時候,二者結果會很是有趣而且大相徑庭。

let element = document.getElementById('2x-container');
複製代碼

這是 log 輸入 element 的輸出:

我打開了一些元素節點。清晰的展現了 DOM 節點,盡收眼底,並且咱們還能夠跳轉到子DOM節點。可是 console.dir(element) 給咱們一個意外不一樣的輸出。

這是一種更對象化的方式去觀察元素節點。也許在某些像監測元素節點的時候,這樣的結果纔是你所想要的。

console.warn()

多是 log() 最直接明顯的替換,你能夠用相同的方式使用 console.warn()。惟一的區別在於輸出是一抹黃色。確切的說,輸出是一個 warn 級別而不是一個 info 級別的信息,所以瀏覽器的處理稍稍有些不一樣。在一堆雜亂的輸出中高亮你的輸出是頗有效果的。

不過,這還有一個更大的優勢。由於輸出是一個 warn 級別而不是一個 info 級別,你能夠將全部的 console.log 過濾掉只留下 console.warn。這有時在那些不停輸出一堆無用和無心義的東西到瀏覽器的隨意的應用程序中是很是有用。屏蔽干擾能更容易的看到你本身的輸出。

console.table()

使人驚訝的是這個並無廣爲人知,可是 console.table() 方法更偏向於一種方式展現列表形式的數據,這比只扔下原始的對象數組要更加整潔。

舉一個例子,下面是數據的列表。

const transactions = [{
  id: "7cb1-e041b126-f3b8",
  seller: "WAL0412",
  buyer: "WAL3023",
  price: 203450,
  time: 1539688433
},
{
  id: "1d4c-31f8f14b-1571",
  seller: "WAL0452",
  buyer: "WAL3023",
  price: 348299,
  time: 1539688433
},
{
  id: "b12c-b3adf58f-809f",
  seller: "WAL0012",
  buyer: "WAL2025",
  price: 59240,
  time: 1539688433
}];
複製代碼

若是使用 console.log 去列出以上信息,咱們能獲得一些中看不中用的輸出:

▶ (3) [{…}, {…}, {…}]
複製代碼

這小箭頭容許你點擊並會展開這個數組,但這並非咱們想要的「一目瞭然」。

console.table(data) 的輸出則對咱們更爲有幫助。

第二個可選參數是你想要顯示列表的某列。默認是整個列表,可是咱們也能這樣作。

> console.table(data, ["id", "price"]);
複製代碼

咱們獲得這樣的輸出,僅僅只展現 id 和 price。在有着大量不相關信息的龐雜對象中很是有用。index 列是自動生成的而且據我所知是不會消失。

值得一提的是在最右一列頭部的右上角有個箭頭能夠顛倒次序。點擊了它,會排序整個列。很是方便的找出一列的最大或者最小值,或者只是獲得不一樣的數據展現形式。這個功能特性並無作什麼,只是對列的展現。但總會是有用的。

console.table() 只有處理最多1000行的數據的能力,因此它可能並不適用於全部的數據集合。

console.assert()

一個常常被忽視的實用的函數,assert() 在第一個參數是 falsey 時和 log() 同樣。當第一個參數爲真值時也什麼都不作。

這個在你須要循環(或者不一樣的函數調用)而且只有一個要顯示特殊的行爲的場景下特別有用。本質上和這個是同樣的。

if (object.whatever === 'value') {
  console.log(object);
}
複製代碼

澄清一下,當我說「同樣」的時候,我本應該說是作相反的事。因此你須要變換一下場合。

因此,假設咱們上面的值在時間戳裏有一個 null 或者 0,這會破壞咱們代碼日期格式。

console.assert(tx.timestamp, tx);
複製代碼

當和任何有效的事物對象一塊兒使用時會跳過。可是有一個觸發了咱們的日誌記錄,由於時間戳在 0 和 null 時爲假值

有時咱們想要更加複雜的場景。舉個例子,咱們看到了關於用戶 WAL0412 的數據問題而且想要只展現來自它們的事務。這將會是一個很是簡便的方案。

console.assert(tx.buyer === 'WAL0412', tx);
複製代碼

看起來正確,可是並不奏效。牢記,場景必須是爲否認態,我門想要的是斷言,而不是過濾

console.assert(tx.buyer !== 'WAL0412', tx);
複製代碼

咱們想作的就是這樣。在那種狀況下,全部不是 WAL0412 號顧客的事務都爲真值,只留下那些符合的事務。或者,也不徹底是。

諸如此類,console.assert() 並非一直都很管用。可是在特定的場景下會是最優雅的的解決方法。

console.count()

另一個合適的用法是,將console做爲一個計數器使用。

for(let i = 0; i < 10000; i++) {
  if(i % 2) {
    console.count('odds');
  }
  if(!(i % 5)) {
    console.count('multiplesOfFive');
  }
  if(isPrime(i)) {
    console.count('prime');
  }
}
複製代碼

這不是一段有用的代碼,而且有點抽象。我也不打算去證實 isPrime 函數,只假設能夠運行。

咱們將獲得應該是這樣的列表

odds: 1
odds: 2
prime: 1
odds: 3
multiplesOfFive: 1
prime: 2
odds: 4
prime: 3
odds: 5
multiplesOfFive: 2
...
複製代碼

以及剩下的。在你只想列出索引,或者想保留一次(或屢次)計數的狀況下很是有用。

你也能像那樣使用 console.count(),不須要參數。使用 default 調用。

這還有關聯函數 console.countReset(),若是你但願重置計數器可使用它。

console.trace()

這在簡單的數據中演示更加困難。在你試圖找出有問題的內部類或者庫的調用這一塊是它最擅長。

舉個例子,這兒可能有 12 個不一樣的組件正在調用一個服務,可是其中一個沒有正確配置依賴。

export default class CupcakeService {
    
  constructor(dataLib) {
    this.dataLib = dataLib;
    if(typeof dataLib !== 'object') {
      console.log(dataLib);
      console.trace();
    }
  }
  ...
}
複製代碼

這裏單獨使用 console.log() 咱們只能知道執行了哪個基礎庫,並不知道執行的具體位置。可是,堆棧軌跡會清楚的告訴咱們問題在於 Dashboard.js,咱們從中發現 new CupcakeService(false) 是形成出錯的罪魁禍首。

console.time()

console.time() 是專門用於監測操做的時間開銷的函數,也是監測 JavaScript 細微時間的更好的方式。

function slowFunction(number) {
  var functionTimerStart = new Date().getTime();
  // something slow or complex with the numbers. 
  // Factorials, or whatever.
  var functionTime = new Date().getTime() - functionTimerStart;
  console.log(`Function time: ${ functionTime }`);
}
var start = new Date().getTime();

for (i = 0; i < 100000; ++i) {
  slowFunction(i);
}

var time = new Date().getTime() - start;
console.log(`Execution time: ${ time }`);
複製代碼

這是一個過期的方法。我指的一樣還有上面的 console.log。大多數人沒有意識到這裏你本可使用模版字符串和插值法。它時不時的會幫助到你。

那麼讓咱們更新一下上面的代碼。

const slowFunction = number =>  {
  console.time('slowFunction');
  // something slow or complex with the numbers. 
  // Factorials, or whatever.
  console.timeEnd('slowFunction');
}
console.time();

for (i = 0; i < 100000; ++i) {
  slowFunction(i);
}
console.timeEnd();
複製代碼

我如今不須要去作任何算術或者設置臨時變量。

console.group()

現在咱們可能在大多數 console 中要輸出高級和複雜的東西。分組可讓你概括這些。尤爲是讓你能使用嵌套。它擅長展現代碼中存在的結構關係。

// this is the global scope
let number = 1;
console.group('OutsideLoop');
console.log(number);
console.group('Loop');
for (let i = 0; i < 5; i++) {
  number = i + number;
  console.log(number);
}
console.groupEnd();
console.log(number);
console.groupEnd();
console.log('All done now');
複製代碼

這又有一點難以理解。你能夠看看這裏的輸出。

這並非頗有用,可是你能看到其中一些是如何組合的。

class MyClass {
  constructor(dataAccess) {
    console.group('Constructor');
    console.log('Constructor executed');
    console.assert(typeof dataAccess === 'object', 
      'Potentially incorrect dataAccess object');
    this.initializeEvents();
    console.groupEnd();
  }
  initializeEvents() {
    console.group('events');
    console.log('Initialising events');
    console.groupEnd();
  }
}
let myClass = new MyClass(false);
複製代碼

不少工做和代碼在調試信息上可能並非那麼有用。可是仍然是一個有意思的辦法,同時你能夠看到它使你打印的上下文是多麼的清晰。

關於這個,還有最後一點須要說明,那就是 console.groupCollapsed。功能上和 console.group 同樣,可是分組塊一開始是摺疊的。它沒有獲得很好的支持,可是若是你有一個無心義的龐大的分組並想默認隱藏它,能夠試試這個。

結語

這裏真的沒有過多的總結。在你可能只想獲得比 console.log(pet) 的信息更多一點,而且不太須要調試器的時候,上面這些工具均可能幫到你。

也許最有用的是 console.table,可是其餘方法也都有其適用的場景。在咱們想要調試一些東西時,我熱衷於使用 console.assert,但那也只在某種特殊狀況下。

若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索