控制檯應該是大多數前端開發人員平常開發調試離不開的神器。然而控制檯仍有不少鮮爲人知的屬性及方法,能讓你更爽地使用,固然也包括了一些隱藏的深坑(console.log
對象打印bug #feature)...
* 本文探討的是chrome開發工具中的控制檯,其餘瀏覽器也許存在不一樣的表現,此文不涉獵
* 對象打印問題在本文的最末尾點擊跳轉css
開始前,讓咱們來造一個馬里奧!
打開開發者工具的控制檯,將下述代碼複製粘貼,而後猛敲回車!html
!(navigator.userAgent.toLowerCase().indexOf('chrome') > -1) ? null : (function() {
var args = [], eightBitHack = [], coordinates = ["41n8r2", "42t3wu", "449u8a", "4h4014", "4h2c4y", "4g6ia1", "4286dm", "447r6w", "4fudcv", "61z2xp", "70rmyd", "71sfq1", "6zgplp", "42spfv", "4frvnp", "61wzpd"];
for (var row = coordinates.length; row--;) {
var decompressedRow = parseInt(coordinates[row], 36).toString(5).split('');
coordinates[row] = decompressedRow.splice(1, decompressedRow.length-1);
for (var cell = coordinates[row].length; cell--;) {
var dot = parseInt(coordinates[row][cell]);
var color = dot === 4 ? '#ecd585' : dot === 3 ? '#e1c25b' : dot === 2 ? '#805936' : dot ? '#ec2733' : '#fff';
args.unshift("border: 8px solid color;".replace('color', color));
eightBitHack.unshift("%c");
}
eightBitHack.unshift("\n");
}
eightBitHack.push("%c\n\n\n", "\nIt's me, Mario!", "\nmade by %chttps://twitter.com/aristretto");
args.push("font-weight: bold;", "font-weight: bold; color: teal;");
args.unshift(eightBitHack.join(''));
console.log.apply(console, args);
})();
複製代碼
能夠看到,一個充滿色彩的馬里奧出如今了控制檯 前端
主要是使用瞭如下命令實現: console.log('%c','/*css*/');
web
*固然這裏面還有到了其餘的trick處理方式,詳情請看做者連接chrome
從上述的例子能夠看出,控制檯還有不少咱們不知道的進階玩法,如輸出更好的格式,利用一些trick,使得咱們的調試更具效率。瀏覽器
在控制檯中輸入console.
能夠看出,console中有不少方法能夠調用,網上已有不少資源說明,這次僅說起幾個比較有用的APIapp
console.log
除了常見的將須要輸出的結果直接傳入第一個參數中,還有如下用法:chrome-devtools
console.log('Hello','world!\t','Current Time:',Date.now());
// Hello world! Current Time: 1530694211342
複製代碼
print
函數%s
(字符串)、%i``%d
(均爲整型)、%f
外,還支持%c
(樣式)、%o
(DOM元素)、%O
(JavaScript對象)輸出console.log('Hello world!\t%s: %i','Current Time',Date.now());
console.log("normal text,%c large blue text,%c white text with black background ", "color: blue; font-size: x-large","color:white;background:black;");
console.log('%o\n%O',document,{a:1,b:2,c:3});
複製代碼
上述代碼輸出結果見下圖: 函數
寫入在同一行使用相同標籤調用count()
的次數,可用於某些setInterval
或者事件重複觸發的調試。工具
const fn = function(name){
console.count(name);
};
fn('Bob'); // Bob: 1
fn('John'); // John: 1
fn('Bob'); // Bob: 2
fn('Bob'); // Bob: 3
複製代碼
輸出一條消息,幷包含了調用該方法的地方的堆棧信息。區別是error
會將消息設置成錯誤的樣式。
(()=>{
const fn1 = (fn)=>{
fn();
};
const fn2 = ()=>{
console.trace('Target Not Found');
console.error('Target Not Found');
};
fn1(fn2);
})();
複製代碼
上述代碼輸出結果見下圖:
啓動一個具備關聯標籤的新計時器。使用相同標籤調用console.timeEnd()
時,定時器將中止,通過的時間將顯示在控制檯中。計時器值精確到亞毫秒。傳遞到time()
和timeEnd()
的字符串必須匹配,不然計時器不會結束。
可用於分析某段代碼的時間消耗。
console.time('test');
for(let i = 0; i < 100000000; i++){}
console.timeEnd('test');
// 輸出:
// test: 122.71923828125ms
複製代碼
此外,還有不少好用的Console API,如console.table
、console.group
、console.assert
等。能夠在Chrome的Console API文檔中找到他們的使用方法.
嘗試一下,在一個未引入jQuery
和zepto
的頁面的控制檯中,直接輸入$
、$$
會出現什麼?
// 直接打開控制檯輸入
console.log($,$$);
// 輸出:
// ƒ $(selector, [startNode]) { [Command Line API] } ƒ $$(selector, [startNode]) { [Command Line API] }
複製代碼
能夠看到,輸出的函數中,包含了[Command Line API]
。Command Line API
是由控制檯提供的一系列便捷函數集合,大概的功能有:選擇和檢查 DOM元素,以可讀格式顯示數據,中止和啓動分析器,以及監控 DOM 事件。
* 注1:此類API僅經過控制檯自己獲取,在JS代碼中帶上此類代碼會報錯。
* 注2:若全局已覆蓋了相同名稱的方法,則此類方法將被覆蓋。
$(selector)
等同於document.querySelector
,一樣的,$(selector)
等同於document.querySelectorAll
。Command Line API
只是提供了較快捷的方式便於開發者進行調試。
$0
、$1
、$2
、$3
和$4
命令用做在 Elements 面板中檢查的最後五個DOM元素或在 Profiles面板中選擇的最後五個JavaScript堆對象的歷史參考。$0
返回最近一次選擇的元素或JavaScript對象,$1
返回僅在最近一次以前選擇的元素或對象,依此類推。
如下結果是在測試頁面上依次點擊html標籤、head標籤、meta標籤的結果:
此外,還有不少好用的Command Line API,如copy
、debug
、monitor
、profile
等。能夠在Chrome的Command Line API文檔中找到他們的使用方法.
試想一下如下代碼在控制檯中輸出的結果:
const fn = function(length){
const o = {
arr: [],
key1: 'test',
key2: 'test',
key3: 'test',
key4: 'test',
key5: 'test',
index: 0
};
console.log(JSON.stringify(o));
console.log(o);
console.log('Handling data');
for(let i = 0; i < length; i++){
o.arr.push(i);
}
o.index = length;
console.log(JSON.stringify(o));
console.log(o);
};
fn(5);
複製代碼
不難看出,控制檯中輸出的結果應該以下圖:
此時,咱們展開一下第二行與第五行,會發現一個很奇怪的現象:
定位上述的問題,只須要將鼠標移至行尾的藍色info標記上,控制檯會提示如下內容:
Value below was evaluated just now. #因此這不是bug是feature
這句話意味着,展開當前的object的時候,控制檯纔會去計算出這個對象的key-value,再反饋到控制檯中顯示。
使用Console打印的時候,若控制檯發現當前須要打印的內容是一個對象,會將其保存下來,先輸出一個簡要的快照(Snapshot),待開發者須要查看其中詳細內容時,再點擊展開,返回內存中的值。
這個是控制檯的一個已知的坑點,有可能設計該功能是爲了不控制檯對大對象深複製輸出,致使調試過慢,也有多是爲了方便查看原型鏈上的屬性,但這無疑是開發者調試代碼時須要避開的問題。
要避免這種調試問題,建議使用JSON.stringify()進行輸出調試,而不是直接打印當前對象。
上面提到,使用Console打印對象時,會將這個對象的引用保存下來。因爲開發者工具在瀏覽器中默認開啓,且默認了「開發者以後須要查看該對象」的行爲,就會致使在Console中引入的對象是不會進入GC(垃圾回收)邏輯中的,這就引起了內存泄漏問題。 要避免內存泄漏問題,須要將開發環境與線上環境進行分離,線上環境中避免產生控制檯打印的語句,亦能夠在項目打包時,將ESLint
中的no-console
的開關打開。
medium.com/@aristretto…
developers.google.com/web/tools/c…
stackoverflow.com/questions/1…