一個微小的JavaScript調試工具,以Node.js核心的調試技術爲模型。 適用於Node.js和Web瀏覽器 傳送門node
src/index.jswebpack
if (typeof process === 'undefined' || process.type === 'renderer' || process.browser === true || process.__nwjs) {
module.exports = require('./browser.js');
} else {
module.exports = require('./node.js');
}
複製代碼
經過第三方庫 supports-color 判斷終端是否支持顏色。git
src/node.jsgithub
exports.colors = [ 6, 2, 3, 4, 5, 1 ];
try {
var supportsColor = require('supports-color');
if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
exports.colors = [
20, 21, 26, 27, 32, 33, 38, 39, 40, 41, 42, 43, 44, 45, 56, 57, 62, 63, 68,
69, 74, 75, 76, 77, 78, 79, 80, 81, 92, 93, 98, 99, 112, 113, 128, 129, 134,
135, 148, 149, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171,
172, 173, 178, 179, 184, 185, 196, 197, 198, 199, 200, 201, 202, 203, 204,
205, 206, 207, 208, 209, 214, 215, 220, 221
];
}
} catch (err) {
// swallow - we only care if `supports-color` is available; it doesn't have to be.
}
複製代碼
debug 容許用戶可使用以下格式定義 options (至關於給程序傳參)web
$ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
複製代碼
相比於常見的給程序傳參的格式 node script --xx=xx,更酷一些。數組
exports.inspectOpts = Object.keys(process.env).filter(function (key) {
return /^debug_/i.test(key);
}).reduce(function (obj, key) {
var prop = key
.substring(6)
.toLowerCase()
.replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() });
var val = process.env[key];
if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
else if (val === 'null') val = null;
else val = Number(val);
obj[prop] = val;
return obj;
}, {});
複製代碼
經過以上格式設置的參數會存在 process.env 內。process.env 爲一個對象,以 DEBUG_COLORS=no 爲例, DEBUG_COLORS 爲 key,no 爲 value。瀏覽器
例如:bash
DEBUG_COLORS=no DEBUG_DEPTH=10
process.env = {
DEBUG_COLORS: no,
DEBUG_DEPTH: 10
}
複製代碼
經過 reduce 把數組轉換爲對象,技巧是 reduce 的第二個參數(可選),初始化的值。app
var list = [1,2,3,4];
var a = list.reduce((obj,num)=>{
//此時 obj 在第一次執行時就是初始化的值 {}
obj[`${num}`] = num;
return obj;
},{})
console.log(a);
//a : { '1': 1, '2': 2, '3': 3, '4': 4 }
複製代碼
if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
else if (val === 'null') val = null;
else val = Number(val);
複製代碼
經過正則處理相同含義的字符串,比起用 === 斷定優雅許多。electron
//bad
if(val === 'yes' || val === 'on' || val === 'true'){
val = true;
}
//good
if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
複製代碼
src/common.js 爲一個公共的模塊,導出值爲函數 createDebug。無論是 node 仍是 瀏覽器 壞境最後都做爲參數傳入到 common 內,這樣就作到了代碼分離,把可重用的代碼組織在一塊兒。
這裏的 env 爲壞境對象,把 env 全部的屬性掛載到 createDebug 對象。這樣能夠隨意擴展 env 對象,最終全部方法都會賦值給導出的對象 createDebug。
src/common.js
//賦值操做 源碼
Object.keys(env).forEach(function(key) {
createDebug[key] = env[key];
});
//便捷寫法
let obj1 = {'name':'cxr','age':18};
let obj2 = {...obj1};
console.log(obj2);//{ name: 'cxr', age: 18 }
console.log(obj1 === obj2);//false
複製代碼
利用 tty 模塊(nodejs 原生模塊),當 Node.js 檢測到正運行在一個文本終端(TTY)時,則 process.stdin 默認會被初始化爲 tty.ReadStream 實例,且 process.stdout 和 process.stderr 默認會被初始化爲 tty.WriteStream 實例。經過 isTTY 來檢測:若是是 tty.WriteStream 實例,則返回 true。
// writeStream.isTTY 老是返回 true
if(process.stdout.isTTY === true)
複製代碼
首先要了解的是,在 Linux 下,一切皆爲文件。內核(kernel)利用文件描述符(file descriptor)來訪問文件。文件描述符是非負整數。打開現存文件或新建文件時,內核會返回一個文件描述符。讀寫文件也須要使用文件描述符來指定待讀寫的文件。 Linux 下:
這裏經過 process.stderr.fd 返回一個 fd 做爲參數,tty.isatty 檢測若是給定的 fd 有關聯 TTY,則返回 true,不然返回 false。換句話說,就是這個輸出流是否是在終端裏。
//用戶若是不設置color選項的狀況下 將檢測錯誤流是否在終端裏
function useColors() {
return 'colors' in exports.inspectOpts
? Boolean(exports.inspectOpts.colors)
: tty.isatty(process.stderr.fd);
}
複製代碼
用於控制視頻文本終端上的光標位置,顏色和其餘選項。 某些字節序列(大多數以Esc和'['開頭)嵌入到文本中,終端查找並解釋爲命令,而不是字符代碼。實現 node 壞境下帶顏色輸出的核心。 wiki
node 中書寫格式:
\u001b[31mHello 它將被解析爲輸出紅色的 Hello 。
複製代碼
在 node 中使用改變終端字體顏色:
//31m 爲紅色 32m 爲綠色
console.log('\u001b[31mHello \u001b[32mWorld');
複製代碼
debug 容許用戶自定義格式化插件,例如:
const createDebug = require('debug')
createDebug.formatters.h = (v) => {
return v.toString('hex')
}
// …elsewhere
const debug = createDebug('foo')
debug('this is hex: %h', new Buffer('hello world'))
// foo this is hex: 68656c6c6f20776f726c6421 +0ms
複製代碼
能夠看到只須要在 createDebug.formatters 對象上掛載自定義的函數 h 便可。在格式化輸出的時候發現是 %h 的時候將調用用戶自定義函數。 源碼實現:
// apply any `formatters` transformations
var index = 0;
args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
// if we encounter an escaped % then don't increase the array index
if (match === '%%') return match;
index++;
var formatter = createDebug.formatters[format];
if ('function' === typeof formatter) {
var val = args[index];
match = formatter.call(self, val);
// now we need to remove `args[index]` since it's inlined in the `format`
args.splice(index, 1);
index--;
}
return match;
});
// apply env-specific formatting (colors, etc.)
createDebug.formatArgs.call(self, args);
複製代碼
遵循了對修改關閉,對擴展開放的原則(OCP)。
最後在總結下學習到的知識:
經過閱讀優秀源碼提升本身,厚積薄發。歡迎大神指正~