你不知道的 Node.js 工具函数
從類型判斷說起
在 JavaScript 中,進行變量的類型校驗是一個非常令人頭疼的事,如果只是簡單的使用 typeof 會到各種各樣的問題。
舉幾個簡單的🌰:
console.log(typeof?null)?//?'object' console.log(typeof?new?Array)?//?'object' console.log(typeof?new?String)?//?'object'后來,大家發現可以使用 Object.prototype.toString() 方法來進行變量類型的判斷。
const?getTypeString?=?obj?=>?Object.prototype.toString.call(obj)getTypeString(null)?//?'[object?Null]' getTypeString('string')?//'[object?String]' getTypeString(new?String)?//'[object?String]'對 toString() 方法進行代理,可以得到一個類型字符串,我們就可以在這個字符串上面搞事情。
const?getTypeString?=?obj?=>?{return?Object.prototype.toString.call(obj) } const?isType?=?type?=>?{return?obj?=>?{return?getTypeString(obj)?===?`[object?${type}]`} }const?isArray?=?isType('Array')?//?該方法一般通過?Array.isArray?代替const?isNull?=?isType('Null') const?isObject?=?isType('Object') const?isRegExp?=?isType('RegExp') const?isFunction?=?isType('Function') const?isAsyncFunction?=?isType('AsyncFunction')isNull(null)?//?true isObject({})?//?true isRegExp(/\w/)?//?true isFunction(()?=>?{})?//?true isAsyncFunction(async?()?=>?{})?//?trueBut,在 Node.js 中,內部其實是有一組用來判斷變量類型的 api 的。而且功能異常豐富,除了基礎類型的判斷,還支持判斷 Promise 對象、Date 對象、各種ArrayBuffer。
const?types?=?require('util/types')types.isDate(new?Date)?//?true types.isPromise(new?Promise(()?=>?{}))?//?true types.isArrayBuffer(new?ArrayBuffer(16))?//?true嚴格相等
在 JavaScript 中,對象、數組等變量在判斷相等的過程中,如果用 === 通常只會判斷這兩個變量是否指向同一內存地址。如果想判斷對象的鍵對應的所有值是否相等,需要對兩個對象進行遍歷。在 util 中,也提供了一個方法可以用來判斷兩個對象是否嚴格相等:util.isDeepStrictEqual(val1, val2)
const?util?=?require('util')const?val1?=?{?name:?'shenfq'?} const?val2?=?{?name:?'shenfq'?}console.log('val1?===?val2',?val1?===?val2)?//?false console.log('isDeepStrictEqual',?util.isDeepStrictEqual(val1,?val2))?//?true該方法同樣可以用來判斷數組,是否嚴格相等:
const?util?=?require('util')const?arr1?=?[1,?3,?5] const?arr2?=?[1,?3,?5]console.log('arr1?===?arr2',?arr1?===?arr2)?//?false console.log('isDeepStrictEqual',?util.isDeepStrictEqual(arr1,?arr2))?//?trueError First & Promise
早期的 Node API 都是 Error First 風格的,也就是所有的異步函數都會接受一個回調函數,該回調的一個參數為 error 對象,如果正常返回 error 對象為 null,后面的參數為成功響應的結果。
//?下面是一個讀取文件的示例 const?fs?=?require('fs') fs.readFile('nginx.log',?(error,?data)?=>?{if?(error)?{//?讀取文件失敗console.error(error)return}//?讀取文件成功,打印結果console.log(data) })在 Node 8 發布的時候,新增了一個 promisify 接口,用于將 Error First 風格的 API 轉為 Promise API。
const?fs?=?require('fs') const?util?=?require('util')const?readFile?=?util.promisify(fs.readFile) readFile('./2021-11-11.log',?{?encoding:?'utf-8'?}).then(text?=>?console.log(text))?.catch(error?=>?console.error(error))不過,后來也有很多人覺得這些原生 API 支持 Promise 的方式太過繁瑣,每個 API 都需要單獨的包裝一層 promisify 方法。在 Node 10 發布的時候,原生模塊都新增了一個 .promises 屬性,該屬性下的所有 API 都 Promise 風格的。
const?fs?=?require('fs').promises fs.readFile('./2021-11-11.log',?{?encoding:?'utf-8'?}).then(text?=>?console.log(text))?.catch(error?=>?console.error(error))注意:Node 14 后,promises API 又新增了一種引入方式,通過修改包名的方式引入。
const?fs?=?require('fs/promises') fs.readFile('./2021-11-11.log',?{?encoding:?'utf-8'?}).then(text?=>?console.log(text))?.catch(error?=>?console.error(error))除了將 Error First 風格的 API 轉為 Promise API,util 中還提供 callbackify 方法,用于將 async 函數轉換為 Error First 風格的函數。
下面通過 callbackify 將 promise 化的 fs 還原為 Error First 風格的函數。
const?fs?=?require('fs/promises') const?util?=?require('util')const?readFile?=?util.callbackify(fs.readFile) readFile('./2021-11-12.log',?{?encoding:?'utf-8'?},?(error,?text)?=>?{if?(error)?{console.error(error)return}console.log(text) })調試與輸出
如果有開發過 Node 服務,應該都用過 debug 模塊,通過該模塊可以在控制臺看到更加明晰的調試信息。
const?debug?=?require('debug') const?log?=?debug('app')const?user?=?{?name:?'shenfq'?}log('當前用戶:?%o',?user)其實,通過 util.debug 也能實現類似的效果:
const?debug?=?require('debug') const?log?=?debug('app')const?user?=?{?name:?'shenfq'?}log('當前用戶:?%o',?user)只是在啟動時,需要將 DEBUG 環境變量替換為 NODE_DEBUG。
如果你有認真看上面的代碼,應該會發現,在 log('當前用戶: %o', user) 方法前面的字符串中,有一個 %o 占位符,表示這個地方將會填充一個對象(object)。這與 C 語言或 python 中的,printf 類似。同樣,在 util 模塊中,直接提供了格式化的方法:util.format。
const?{?format?}?=?require('util')console.log(format('當前用戶:?%o',?{name:?'shenfq',?age:?25}) )除了 %o 占位符,不同的數據類型應使用不同的占位符。
| %s | 字符串 |
| %d | 數字(包括整數和浮點數) |
| %i | 整數 |
| %f | 浮點數 |
| %j | JSON |
| %o | Object |
JavaScript 中的對象是一個很復雜的東西,除了直接使用 util.format 外加 %o 占位符的方式格式化對象,util 中還提供了一個叫做 inspect 方法來進行對象格式化。
const?{?inspect?}?=?require('util')const?user?=?{age:?25,name:?'shenfq',work:?{name:?'coding',seniority:?5} }console.log(inspect(user))這么看 inspect 好像什么都沒做,但是 inspect 方法還有第二個參數,用來進行格式化時的一些個性化配置。
depth: number:控制顯示層級;
sorted: boolean|Function: 是否按照key的編碼值進行排序;
compact: boolean:是否進行單行顯示;
當然上面只是一部分配置,更詳細的配置可查閱 node 文檔,下面我們寫幾個案例:
所有的屬性都換行顯示:
inspect(user,?{compact:?false })只格式化對象第一層的值:
inspect(user,?{depth:?0,compact:?false })按照key值的編碼倒序輸出:
inspect(user,?{compact:?false,sorted:?(a,?b)?=>?a?<?b???1?:?-1 })- END -最近組建了一個湖南人的前端交流群,如果你是湖南人可以加我微信?ruochuan12?私信 湖南 拉你進群。
推薦閱讀
1個月,200+人,一起讀了4周源碼
我歷時3年才寫了10余篇源碼文章,但收獲了100w+閱讀
老姚淺談:怎么學JavaScript?
我在阿里招前端,該怎么幫你(可進面試群)
·················?若川簡介?·················
你好,我是若川,畢業于江西高校。現在是一名前端開發“工程師”。寫有《學習源碼整體架構系列》20余篇,在知乎、掘金收獲超百萬閱讀。
從2014年起,每年都會寫一篇年度總結,已經寫了7篇,點擊查看年度總結。
同時,最近組織了源碼共讀活動,幫助1000+前端人學會看源碼。公眾號愿景:幫助5年內前端人走向前列。
識別上方二維碼加我微信、拉你進源碼共讀群
今日話題
略。分享、收藏、點贊、在看我的文章就是對我最大的支持~
總結
以上是生活随笔為你收集整理的你不知道的 Node.js 工具函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 工作392-选择Hbuilder x导入
- 下一篇: tf卡工具android,SD/TF卡专