除了可以在 JavaScript 執行的 Console API 外,Console 還提供了一些 Debug 專用的 Function,每一個都身懷絕技。
閱讀本篇文章時建議搭配 Demo 頁面 Console - Utilities,效果更佳。
還記得筆者第一次看到這些 Function 時特別興奮,直接寫在自己的程式碼中,想當然是跳出了各種 Uncaught ReferenceError: xxx is not defined
。
$_
會儲存的執行結果,在 Console 測試 JavaScript 行為的時候通常都會逐步確認,正是使用 $_
的好時機:
用到很多不能 Chain 的 Function 時能利用 $_
來避免游標來回修改:
順帶一提,未來也有可能出現 Pipeline operator 來做到任意 Function chaining ,提升可讀性或避免需要修改內建 Prototypes。
let a;
a = 1
|> ((n) => add(n, 5))
|> double;
console.log(a); // 12
$(selector[, element])
, $$(selector[, element])
$
和 $$
分別就是 document.querySelector
和 document.querySelectorAll
的縮寫,來源就是大家熟知的 JQuery。
第二個參數可以放入起始的元素。搭配 $0
就可以先 Inspect 一個元素,再從它開始搜尋。
$('.btn', $0)
筆者常用 $$
來快速測試一些行為,例如印出個人 GitHub 頁面的所有 Repository 名稱:
不過如果已經引入套件如 JQuery 為
$
的話,還是會正常執行JQuery。
debug(function)
參數為一個 Function,只要執行到該 Function 就會觸發 Debugger,可以用 undebug(fn)
來取消:
function a() {
console.log(1);
}
debug(a);
// undebug(a);
其效果相當於:
function a() {
console.log(1);
}
a = (function() {
const origin = a;
return function() {
debugger;
origin();
}
})();
關於斷點(Breakpoints)的使用,會在之後關於 Sources 的文章有更詳細的解釋。
monitor(function)
用法和 debug
很像,monitor
的 Function 被執行時會印出 Function 名稱和參數,
可用 unmonitor(function)
來停止,不過無法用在 Arrow function,需要監聽 Arrow function 的執行就只能手動覆寫了。
monitorEvents(element[, eventType])
可以在監聽並印出元素的特定事件,比較特別的是除了能監聽單一事件,還能監聽事件類型,例如印出 window
的點擊事件和所有 touch
類別的事件:
效果和以下 JavaScript 相同:
window.addEventListener('click', console.log)
window.addEventListener('touchstart', console.log)
window.addEventListener('touchmove', console.log)
window.addEventListener('touchend', console.log)
window.addEventListener('touchcancel', console.log)
另外可用 unmonitorEvents(element[, eventType])
來停止監聽。
getEventListeners(element)
印出已註冊在元素上的監聽器,以剛剛的例子來說,輸入 monitorEvents(element)
後再輸入 getEventListeners(element)
就會看到所有事件都被註冊了一輪:
展開的話可以看到監聽器的各種屬性:
scroll
上述的屬性都是能在執行 addEventListener
時提供的參數,記得在 removeEventListener
時也要填入相同的參數才能移除監聽器。
const options: {
capture: true,
passive: true,
once: false
}
window.addEventListener('click', console.log, options);
// window.removeEventListener('click', console.log, options);
queryObjects(object)
官方文件說明是返回 Constructor 產生的所有 Instances,不過筆者認為應該解釋為:印出所有原型鍊包含該原型的物件。
可以看到以 a
為原型建立的 b
也會出現在 queryObjects(A)
的結果中。
另外由於 queryObjects
並不會直接 return 陣列,而是過了一下才印出來,這邊利用右鍵 > Store as global variable
來把陣列放進變數 temp1
。
copy(object)
copy
能夠把 DOM、物件複製到剪貼簿,例如筆者有時候會用 copy
把物件轉為 JSON,貼到對話框來討論 API Spec,或是用 Console 來快速建立、修改假資料。
貼心的加入縮排了呢!
keys(object)
, values(object)
印出物件自身的所有 key 或 value,效果和 Object.keys(object)
、Object.values(object)
相同,為何強調自身呢?如果是用 in
來遍歷物件的各個屬性,就會把 Protoype 鍊上的屬性全都拿出來跑一遍:
const object = Object.create({ foo: 1});
object.bar = 2;
for (let key in object) {
console.log(key)
}
// bar
// foo
除了是自身的 key,還要 enumerable。
如果想要確認屬性是否是定義在物件自身可以用 Object.prototype.hasOwnProperty
:
for (let key in object) {
if (Object.prototype.hasOwnProperty.call(object, key)) {
console.log(key);
}
}
// bar
至於為什麼不用 object.hasWonProperty(key)
,請參考下方程式碼:
const object1 = {
hasOwnProperty: function() {
return false;
},
};
const object2 = Object.create(null);
object1.key = 'key';
object2.key = 'key';
object1.hasOwnProperty('key'); // ?
object2.hasOwnProperty('key'); // ?
clear()
雖然按下左上角的 ? 就能把 Console 清乾淨,但筆者還是習慣用 clear()
,就像在 terminal 輸入 clear
一樣。
注意在 Preserve log
開啟的狀況下 clear
並不會清空 Console。
終於講完了 Console Utility Functions,明天將會繼續講一些在 Console 內執行 JavaScript 的小撇步。