除了console.log以外,還有更多方式調試JavaScript來輸出值。 看起來很明顯咱們沒有。程序員
人們告訴我,作JavaScript應該使用瀏覽器的調試器,但這確定是要看運行環境的。 可是不少時候你只想知道代碼的某一部分是執行仍是變量是什麼,而不會看着斷點消失龐大的代碼類庫中。api
儘管如此,雖然咱們使用console.log
,可是不少人都沒有意識到控制檯自己除了基本日誌以外還有不少其餘選項。 適當使用這些功能可使調試更容易,更快速,更直觀。數組
在舊的console.log中有超出人指望使人驚訝的功能。 雖然大多數人將它用做console.log(obj)
,但您也能夠執行console.log(object,otherObject,string)
,它會將它們所有記錄下來。 有時候方便。瀏覽器
除此以外,還有另外一種格式:console.log(msg,values)
。 這很像像C或PHP中的sprintf。微信
console.log('I like %s but I do not like %s.', 'Skittles', 'pus');
將徹底按照您的預期輸出。ide
> I like Skittles but I do not like pus.
常見的佔位符是%o
(這是一個字母o,而不是零),它接受一個對象,%s
接受一個字符串,%d
是一個十進制或整數。函數
另外一個有趣的是%c
, 它其實是CSS值的佔位符。工具
console.log('I am a %cbutton', 'color: white; background-color: orange; padding: 2px 5px; border-radius: 2px');
這些值會運行到後面的任何內容上,沒有「結束標記」,這有點奇怪。 但你能夠將它變得像這樣。oop
它不優雅,也不是特別有用。 固然,這不是一個真正的按鈕。this
它有用嗎?Ehhhhh。
在大多數狀況下,console.dir()
函數很是相似於log()
,儘管它看起來有點不一樣。
向下的小箭頭將顯示與上面相同的確切對象詳細信息,這也能夠從console.log
版本中看到。 當你看到元素時,事物的分歧更加重烈,更有趣。
let element = document.getElementById('2x-container');
這是記錄輸入的輸出:
我打開了一些元素。 這清楚地顯示了DOM,咱們能夠瀏覽它。 可是console.dir(element)爲咱們提供了驚人的不一樣輸出。
這是一種更加客觀的方式來查看元素。 有時候這就是你真正想要的東西,更像是檢查元素。
多是最明顯的直接替換log()
,你能夠用徹底相同的方式使用console.warn()
。 惟一真正的區別是輸出有點黃。 具體來講,輸出處於警告級別而不是信息級別,所以瀏覽器將稍微區別對待它。 這具備使其在雜亂輸出中更明顯的效果。
可是,有一個更大的優點。 由於輸出是警告而不是信息,因此您能夠過濾掉全部console.log
並僅保留console.warn
。 這對於偶爾會在瀏覽器中輸出大量無用廢話的偶爾繁瑣的應用程序尤爲有用。 清除噪音可讓您更輕鬆地看到輸出。
使人驚訝的是,這並非更爲人所知,可是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.tabl(data)
的輸出更有幫助。
可選的第二個參數是您想要的列的列表。 顯然默認爲全部列,但咱們也能夠這樣作。
> console.table(data, ["id", "price"]);
咱們獲得這個輸出,只顯示id和價格。 適用於過大的物體,細節基本無關。 索引列是自動建立的,而且據我所知不能夠去掉。
這裏要注意的是這是亂序的 - 最右邊的列標題上的箭頭顯示了緣由。 我點擊該列進行排序。 找到列的最大或最小,或者只是對數據進行不一樣的查看很是方便。 順便說一句,該功能與顯示部分列無關。 它始終可用。
console.table()
只能處理最多1000行,所以可能不適合全部數據集。
斷言有用的函數assert()
與log()
相同,但僅在第一個參數爲false的狀況下。 若是第一個參數爲真,它什麼都不作。
這對於有循環(或幾個不一樣的函數調用)而且只有一個顯示特定行爲的狀況特別有用。 基本上它和這樣作是同樣的。
if (object.whatever === 'value') { console.log(object); }
澄清的是,當我說「相同」時,作起來倒是相反的。 因此你須要反轉條件。
所以,讓咱們假設上面的一個值是在時間戳中使用null
或0
,這會搞砸咱們的代碼格式化日期。
console.assert(tx.timestamp, tx);
當與任何有效的事務對象一塊兒使用時,它只是跳過去。 可是false
會觸發咱們的日誌記錄,由於時間戳是0
或null
。
有時咱們想要更復雜的條件。 例如,咱們已經看到用戶WAL0412的數據存在問題,而且只想顯示來自它們的事務。 這是直觀的解決方案。
console.assert(tx.buyer === 'WAL0412', tx);
這看起來正確,但不起做用。 請記住,條件必須是false...咱們要斷言,而不是過濾。
console.assert(tx.buyer !== 'WAL0412', tx);
這將作咱們想要的。 買方不是WAL0412的任何交易在該條件下都是正確的,只留下那些。 或者......不是。
像其中的一些,console.assert()
並不老是特別有用。 但在特定狀況下它能夠是一個優雅的解決方案。
另外一個使用有用的功能,count只是做爲一個計數器,可選擇做爲一個命名計數器。
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()
,不帶參數。 這樣作會將其稱爲默認值。
若是您願意,還可使用相關的console.countReset()
來重置計數器。
這很難用簡單的數據進行演示。 它擅長的地方在於你試圖弄清楚實際調用者致使問題的類或庫。
例如,可能有12個不一樣的組件調用服務,但其中一個組件沒有正確設置依賴關係。
export default class CupcakeService { constructor(dataLib) { this.dataLib = dataLib; if(typeof dataLib !== 'object') { console.log(dataLib); console.trace(); } } ... }
在這裏單獨使用console.log()
會告訴咱們傳入的dataLib是什麼,而不是在哪裏。 可是,堆棧跟蹤將很是清楚地告訴咱們問題是Dashboard.js,咱們能夠看到它是新的CupcakeService(false)並致使錯誤。
用於跟蹤操做所用時間的專用函數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();
咱們如今再也不須要作任何數學運算或設置臨時變量。
如今多是控制檯輸出中最複雜和最早進的區域。 group讓你......好吧,分組。 特別是它可讓你嵌套東西。 它擅長的地方在於顯示代碼中存在的結構。
// 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
,但全部其餘api也都有本身的做用。 我是console.assert的粉絲,由於咱們想調試一些東西,但只能在特定狀況下調試。
建立了一個程序員交流微信羣,你們進羣交流IT技術
若是已過時,能夠添加博主微信號15706211347,拉你進羣