Node.js Util

util是Node.js的核心模塊拢军,提供了常用函數(shù)的集合,用于彌補(bǔ)核心JavaScript功能過(guò)于精簡(jiǎn)的不足送巡。util模塊設(shè)計(jì)的主要目的是為了滿(mǎn)足Node.js內(nèi)部API的需求摹菠。

const util = require("util");

Node.js的util模塊提供了實(shí)用函數(shù)來(lái)格式化字符串、將對(duì)象轉(zhuǎn)化為字符串骗爆、檢查對(duì)象類(lèi)型次氨、執(zhí)行對(duì)輸出流的同步寫(xiě)入,以及對(duì)對(duì)象繼承的增強(qiáng)摘投。

格式化字符串format

在處理字符串時(shí)通常需要快速格式化字符串煮寡,Node.js在util模塊中提供了一個(gè)基本的字符串格式化方法用于處理字符串格式化的需求虹蓄。

util.format(format, [...])

util.form()函數(shù)接收 一個(gè)格式化字符串format作為第一個(gè)參數(shù),并返回格式化后的字符串幸撕。

format參數(shù)是可用包含零個(gè)或多個(gè)占位符的字符串薇组,每個(gè)占位符都是以一個(gè)%字符開(kāi)始,并最終被對(duì)應(yīng)的參數(shù)轉(zhuǎn)換的字符串值取代坐儿。

占位符 描述
%s 指定字符串
%d 指定數(shù)值
%j 指定JSON可轉(zhuǎn)化為字符串的對(duì)象
%o Object律胀,包括不可枚舉的屬性。
%O Object貌矿,不包括不可枚舉的屬性炭菌。
% 若%后保留為空則不作為占位符
%% 輸出%

使用format函數(shù)時(shí)需要注意

  • 若參數(shù)沒(méi)有占位符多則多余占位符都不會(huì)被替換
console.log(util.format("%s = %s", "alice"));//alice = %s
  • 當(dāng)有比占位符更多的參數(shù)時(shí)多余的參數(shù)會(huì)被轉(zhuǎn)換為字符串,然后以空格分隔符連接逛漫。
console.log(util.format("%s = %s", "name", "alice", 18));//name = alice 18
  • 若第一個(gè)參數(shù)不是格式化字符串黑低,則會(huì)將每個(gè)參數(shù)都轉(zhuǎn)換為字符串,并使用空格分隔符將其連接酌毡,返回連接后的字符串投储。
console.log(util.format(1,2,3));//1 2 3

對(duì)象轉(zhuǎn)字符串inspect

util.inspect(object, [showHidden], [depth], [colors])
util.inspect(object[, options])

inspect是將任意對(duì)象轉(zhuǎn)化為字符串的方法,用于調(diào)試和錯(cuò)誤輸出阔馋。它至少接受一個(gè)參數(shù)object即需要轉(zhuǎn)換的對(duì)象。

function Klass(){
    this.name = "alice";
    this.toString = function(){
        return this.name;
    }
}
const obj = new Klass();
console.log(util.inspect(obj));//Klass { name: 'alice', toString: [Function] }
參數(shù) 描述
object 需要轉(zhuǎn)換的對(duì)象
showHidden 可選娇掏,表示是否枚舉顯式對(duì)象的隱藏屬性呕寝,默認(rèn)false,若為true則輸出更多隱藏信息婴梧。
depth 可選下梢,表示最大遞歸層數(shù)即設(shè)置對(duì)象枚舉顯式的深度,默認(rèn)為2塞蹭。若指定為null表示不限遞歸層數(shù)完整遍歷孽江。
colors 可選,colors為true表示輸出格式會(huì)以ANSI顏色編碼番电,用于終端顯式岗屏。

例如:對(duì)象轉(zhuǎn)字符串并顯式隱藏信息

console.log(util.inspect(obj, true));

Klass {
  name: 'alice',
  toString:
   { [Function]
     [length]: 0,
     [name]: '',
     [arguments]: null,
     [caller]: null,
     [prototype]: { [constructor]: [Circular] } } }

例如:JSON對(duì)象轉(zhuǎn)字符串

const obj = {id:1, name:"alice"}
console.log(util.inspect(obj, true));//{ id: 1, name: 'alice' }

同步寫(xiě)入輸出流

util模塊具有同步寫(xiě)數(shù)據(jù)到標(biāo)準(zhǔn)輸入stdout和標(biāo)準(zhǔn)錯(cuò)誤stderr的能力,意味著進(jìn)程會(huì)保持阻塞直到數(shù)據(jù)被寫(xiě)出來(lái)為止漱办≌馑ⅲ可用于確保當(dāng)前數(shù)據(jù)被寫(xiě)入時(shí),系統(tǒng)并沒(méi)有改變其行為娩井。

函數(shù) 描述
util.debug(string) 將字符串寫(xiě)入到標(biāo)準(zhǔn)錯(cuò)誤stderr中暇屋,已過(guò)時(shí)使用console.error()替代。
util.error([...]) 接受多個(gè)參數(shù)將其寫(xiě)入到標(biāo)準(zhǔn)錯(cuò)誤stderr中洞辣,已過(guò)時(shí)使用console.error()替代咐刨。
util.puts([...]) 接受多個(gè)參數(shù)將其寫(xiě)入到標(biāo)準(zhǔn)輸出stdout中昙衅,已過(guò)時(shí)使用console.log()替代。
util.print([...]) 接受多個(gè)參數(shù)將其轉(zhuǎn)換為字符串后寫(xiě)入到標(biāo)準(zhǔn)輸出stdout中定鸟,已過(guò)時(shí)使用console.log()替代而涉。
util.log(string) 將字符串以及時(shí)間戳寫(xiě)入到標(biāo)準(zhǔn)輸出stdout中

控制臺(tái)標(biāo)準(zhǔn)輸出util.log

util.log(string)

log方法用于在控制臺(tái)標(biāo)準(zhǔn)輸出stdout,輸出時(shí)會(huì)帶有時(shí)間戳仔粥。

util.log("hello world");//21 Dec 12:42:07 - hello world

調(diào)試輸出util.debuglog

util.debuglog(section)

debuglog方法用于根據(jù)NODE_DEBUG環(huán)境變量來(lái)選擇性的輸出debug信息婴谱。

檢查對(duì)象類(lèi)型

判斷對(duì)象類(lèi)型最常用的方式是使用instanceof運(yùn)算符,util模塊提供了常用的便捷函數(shù)躯泰。

console.log([] instanceof Array);//true
判斷函數(shù) 描述
util.isArray(object) 判斷給定對(duì)象是否為數(shù)組
util.isDate(object) 判斷給定對(duì)象是否為日期
util.isRegExp(object) 判斷給定對(duì)象是否為正則
util.isError(object) 判斷給定對(duì)象是否為錯(cuò)誤

檢查對(duì)象是否為數(shù)組util.isArray

util.isArray(object)

isArray方法用于檢查傳入對(duì)象object是否為數(shù)組谭羔,返回布爾值,是為true否為false麦向。

console.log(util.isArray([]));//true
console.log(util.isArray(new Array));//true
console.log(util.isArray({}));//false

檢查對(duì)象是否為Date類(lèi)型util.isDate

util.isDate(object)

isDate方法用于檢查傳入的對(duì)象object是否為Date日期類(lèi)型瘟裸,返回布爾值,是為true否為false诵竭。

console.log(util.isDate({}));//false
console.log(util.isDate(new Date()));//true
console.log(util.isDate(Date()));//false

檢查對(duì)象是否為Error類(lèi)型util.isError

util.isError(object)

isError方法用于檢查對(duì)象是否為Error類(lèi)型话告,返回布爾值,是為true否為false卵慰。

console.log( util.isError({name:"Error", message:"an error occurred"}) );//false
console.log( util.isError(new Error()) );//true
console.log( util.isError(new TypeError()) );//true

檢查對(duì)象是否為正則表達(dá)式util.isRegExp

util.isRegExp(object)

isRegExp方法用于檢查給定對(duì)象objet是否為RegExp正則表達(dá)式沙郭,返回布爾值,是為true否為false裳朋。

console.log( util.isRegExp({}) );//false
console.log( util.isRegExp(/regexp rule/) );//true
console.log( util.isRegExp(new RegExp("pattern")) );//true

對(duì)象原型繼承util.inherits

inherits方法用于實(shí)現(xiàn)對(duì)象之間的原型繼承病线,JavaScript面向?qū)ο筇匦允腔谠偷模c基于類(lèi)不同鲤嫡。JavaScript中沒(méi)有提供對(duì)象繼承的語(yǔ)言級(jí)別特性送挑,是通過(guò)原型復(fù)制來(lái)實(shí)現(xiàn)。

util.inherits(constructor, superConstructor)

inherits方法允許創(chuàng)建一個(gè)繼承自另一個(gè)對(duì)象prototype原型方法的對(duì)象暖眼。當(dāng)創(chuàng)建新對(duì)象時(shí)prototype原型方法會(huì)自動(dòng)被使用惕耕。

const util = require("util");
//父類(lèi)
function Base(opts){
    //父類(lèi)私有屬性
    this.id = opts.id || 0;
    this.name = opts.name || "";
    //父類(lèi)私有方法
    this.output = function(){
        console.log(this.id, this.name);
    };
}
//父類(lèi)原型方法
Base.prototype.getName = function(){
    return this.name;
};

//子類(lèi)
function Sub(opts){
    //子類(lèi)繼承父類(lèi)屬性
    Base.call(this, opts)
    //子類(lèi)屬性覆寫(xiě)父類(lèi)屬性
    this.name = "subname";
    //子類(lèi)新增私有屬性
    this.type = opts.type||"";
}
//子類(lèi)原型繼承
util.inherits(Sub, Base);


//創(chuàng)建子類(lèi)對(duì)象
const sub = new Sub({id:1, type:"subtype"});
console.log(sub);//Sub { id: 1, name: 'subname', output: [Function], type: 'subtype' }

//子類(lèi)繼承父類(lèi)原型方法
console.log(sub.getName());//subname

在新對(duì)象被創(chuàng)建時(shí)會(huì)執(zhí)行原型constructor設(shè)定為原型superConstructor,可使用constructor.super_屬性從自定義對(duì)象的構(gòu)造函數(shù)中訪問(wèn)父類(lèi)構(gòu)造函數(shù)superConstructor诫肠。

例如:使用inherits方法繼承events.EventEmitter事件觸發(fā)器對(duì)象的構(gòu)造函數(shù)來(lái)創(chuàng)建一個(gè)Writable寫(xiě)入流

const util = require("util");
const EventEmitter = require("events").EventEmitter;

//定義類(lèi)
function Writer(){
    EventEmitter.call(this);
}
//類(lèi)的繼承
util.inherits(Writer, EventEmitter);
//自定義寫(xiě)入方法并調(diào)用父類(lèi)觸發(fā)方法
Writer.prototype.write = function(data){
    this.emit("data", data);
};

//實(shí)例化對(duì)象
const writer = new Writer();
//判斷對(duì)象是否為繼承自父類(lèi)
console.log(writer instanceof EventEmitter);//true

//為writer注冊(cè)data事件
writer.on("data", function(data){
    console.log("receive data:", data);//receive data: hello world
});

//寫(xiě)入數(shù)據(jù)并觸發(fā)data事件
writer.write("hello world");
console.log(writer);
Writer {
  _events: [Object: null prototype] {},
  _eventsCount: 0,
  _maxListeners: undefined }

風(fēng)格轉(zhuǎn)換util.promisify

Node.js的回調(diào)函數(shù)根據(jù)約定具有統(tǒng)一的形式司澎,即(error, value) => {}。因此可將這種回調(diào)函數(shù)作為參數(shù)的函數(shù)轉(zhuǎn)化為返回Promise的函數(shù)区赵。

例如:結(jié)合async/await使用util.promisify異步讀取文件內(nèi)容

const util = require("util");
const fs = require("fs");

const asyncReadFile = util.promisify(fs.readFile);

async function main(file, charset = "utf-8"){
    const content = await asyncReadFile(file, charset);
    //console.log(content);
    return content;
}

main("./README.md").then(data=>{
    console.log(data);
});

例如:獲取文件夾統(tǒng)計(jì)信息

const util = require("util");
const fs = require("fs");

const stats = util.promisify(fs.stat);

async function main(dirname){
    const content = await stats(dirname);
    //console.log(content);
    return content;
}

main(".").then(data=>{
    console.log(data);
}).catch(error=>{
    console.log(error);
});
Stats {
  dev: 1650279073,
  mode: 16822,
  nlink: 1,
  uid: 0,
  gid: 0,
  rdev: 0,
  blksize: undefined,
  ino: 9007199255333340,
  size: 0,
  blocks: undefined,
  atimeMs: 1576835786059.209,
  mtimeMs: 1576835772463.417,
  ctimeMs: 1576835772463.417,
  birthtimeMs: 1576232793857.817,
  atime: 2019-12-20T09:56:26.059Z,
  mtime: 2019-12-20T09:56:12.463Z,
  ctime: 2019-12-20T09:56:12.463Z,
  birthtime: 2019-12-13T10:26:33.858Z }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末惭缰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子笼才,更是在濱河造成了極大的恐慌漱受,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異昂羡,居然都是意外死亡絮记,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)虐先,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)怨愤,“玉大人,你說(shuō)我怎么就攤上這事蛹批∽矗” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵腐芍,是天一觀的道長(zhǎng)差导。 經(jīng)常有香客問(wèn)我,道長(zhǎng)猪勇,這世上最難降的妖魔是什么设褐? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮泣刹,結(jié)果婚禮上助析,老公的妹妹穿的比我還像新娘。我一直安慰自己椅您,他們只是感情好外冀,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著掀泳,像睡著了一般锥惋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上开伏,一...
    開(kāi)封第一講書(shū)人閱讀 51,521評(píng)論 1 304
  • 那天,我揣著相機(jī)與錄音遭商,去河邊找鬼固灵。 笑死,一個(gè)胖子當(dāng)著我的面吹牛劫流,可吹牛的內(nèi)容都是我干的巫玻。 我是一名探鬼主播,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼祠汇,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼仍秤!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起可很,我...
    開(kāi)封第一講書(shū)人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤诗力,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后我抠,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體苇本,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡袜茧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了瓣窄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片笛厦。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖俺夕,靈堂內(nèi)的尸體忽然破棺而出裳凸,到底是詐尸還是另有隱情,我是刑警寧澤劝贸,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布姨谷,位于F島的核電站,受9級(jí)特大地震影響悬荣,放射性物質(zhì)發(fā)生泄漏菠秒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一氯迂、第九天 我趴在偏房一處隱蔽的房頂上張望践叠。 院中可真熱鬧,春花似錦嚼蚀、人聲如沸禁灼。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)弄捕。三九已至,卻和暖如春导帝,著一層夾襖步出監(jiān)牢的瞬間守谓,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工您单, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留斋荞,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓虐秦,卻偏偏與公主長(zhǎng)得像平酿,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子悦陋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容