你不知道的 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?()?=>?{})?//?true

But,在 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
e8b68cb738241b57f6678fed556c9951.png

該方法同樣可以用來判斷數組,是否嚴格相等:

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))?//?true
131c8fd990032a923bce476fce33fea2.png

Error 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))
3acf7b7e9e0f386cacec6333504edcea.png

不過,后來也有很多人覺得這些原生 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))
8ee9ab9ea61daefbd852cb05e95ab776.png

注意: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))
ca6f709962a6b2ad381137e1b41a9605.png

除了將 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)
46cdde3ba51afdc9fa957e8faa1751b6.png

其實,通過 util.debug 也能實現類似的效果:

const?debug?=?require('debug')
const?log?=?debug('app')const?user?=?{?name:?'shenfq'?}log('當前用戶:?%o',?user)

只是在啟動時,需要將 DEBUG 環境變量替換為 NODE_DEBUG

a203a13c16ab3589db11ba33b08fff44.png

如果你有認真看上面的代碼,應該會發現,在 log('當前用戶: %o', user) 方法前面的字符串中,有一個 %o 占位符,表示這個地方將會填充一個對象(object)。這與 C 語言或 python 中的,printf 類似。同樣,在 util 模塊中,直接提供了格式化的方法:util.format

const?{?format?}?=?require('util')console.log(format('當前用戶:?%o',?{name:?'shenfq',?age:?25})
)
16e9a4acfa74ed3e9a8ce9abd49077a5.png

除了 %o 占位符,不同的數據類型應使用不同的占位符。

占位符類型
%s字符串
%d數字(包括整數和浮點數)
%i整數
%f浮點數
%jJSON
%oObject

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))
5e9afdd4324966b600b460c878a67de0.png

這么看 inspect 好像什么都沒做,但是 inspect 方法還有第二個參數,用來進行格式化時的一些個性化配置。

  • depth: number:控制顯示層級;

  • sorted: boolean|Function: 是否按照key的編碼值進行排序;

  • compact: boolean:是否進行單行顯示;

當然上面只是一部分配置,更詳細的配置可查閱 node 文檔,下面我們寫幾個案例:

所有的屬性都換行顯示:

inspect(user,?{compact:?false
})
587987c83050731fe7cc73fdad5ed647.png

只格式化對象第一層的值:

inspect(user,?{depth:?0,compact:?false
})
f81f7417cddf8280b2b9181a82afca95.png

按照key值的編碼倒序輸出:

inspect(user,?{compact:?false,sorted:?(a,?b)?=>?a?<?b???1?:?-1
})
7b582b16784d7746a4c45fde323d0365.png- END -

最近組建了一個湖南人的前端交流群,如果你是湖南人可以加我微信?ruochuan12?私信 湖南 拉你進群。

推薦閱讀

1個月,200+人,一起讀了4周源碼
我歷時3年才寫了10余篇源碼文章,但收獲了100w+閱讀

老姚淺談:怎么學JavaScript?

我在阿里招前端,該怎么幫你(可進面試群)

019c16e72c9ebac005c40bc8c53c79d1.gif

·················?若川簡介?·················

你好,我是若川,畢業于江西高校。現在是一名前端開發“工程師”。寫有《學習源碼整體架構系列》20余篇,在知乎、掘金收獲超百萬閱讀。
從2014年起,每年都會寫一篇年度總結,已經寫了7篇,點擊查看年度總結。
同時,最近組織了源碼共讀活動,幫助1000+前端人學會看源碼。公眾號愿景:幫助5年內前端人走向前列。

bfb4333ccaee148e578073ab4675108c.png

識別方二維碼加我微信、拉你進源碼共讀

今日話題

略。分享、收藏、點贊、在看我的文章就是對我最大的支持~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/275175.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/275175.shtml
英文地址,請注明出處:http://en.pswp.cn/news/275175.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java應用集群下的定時任務處理方案(mysql)

今天來說一個Java多機部署下定時任務的處理方案。 需求: 有兩臺服務器同時部署了同一套代碼&#xff0c; 代碼中寫有spring自帶的定時任務&#xff0c;但是每次執行定時任務時只需要一臺機器去執行。 當拿到這個需求時我腦子中立馬出現了兩個簡單的解決方案&#xff1a; 利用ip…

概念驗證_設置成功的UX概念驗證

概念驗證用戶體驗/概念證明/第1部分 (USER EXPERIENCE / PROOF OF CONCEPT / PART 1) This is the first article of a four-part series. Please read Part 2 and Part 3.這是由四個部分組成的系列文章的第一篇。 請閱讀 第2 部分 和 第3部分 。 How do today’s top UX desi…

從 vue3 和 vite 源碼中,我學到了一行代碼統一規范團隊包管理器的神器

1. 前言大家好&#xff0c;我是若川。最近組織了源碼共讀活動&#xff0c;感興趣的可以加我微信 ruochuan12 參與&#xff0c;每周大家一起學習200行左右的源碼&#xff0c;共同進步。已進行四個月了&#xff0c;很多小伙伴表示收獲頗豐。想學源碼&#xff0c;極力推薦之前我寫…

什么事接口

假設你設計一個和人交流的程序。 先建立一個接口 interface 人 //定義接口&#xff0c;它代表一個人&#xff0c; {void Hello(); }//接口虛函數&#xff0c;用來跟這個人說話 但不同的人有不用的交流方式&#xff0c;具體方式用類來實現&#xff0c;比如。 class 美國人&#…

6個高效辦公的Excel小技巧,學會讓你高效辦公

很多人在做Excel表格的時候&#xff0c;會出現下面這種情況&#xff1a;好不容易把內容都輸入好了&#xff0c;才發現文字或是數字的排列組合需要重新調整&#xff0c;這個時候頭就大了&#xff0c;到底是要一個個復制黏貼&#xff0c;還是要刪除后再添加&#xff1f;不管哪種方…

unity 完美像素_像素完美

unity 完美像素從Kidpix到設計系統 (From Kidpix to design systems) Did you ever create stamps in KidPix? Kidpix is bitmap drawing software that’s been around since the nineties, and I remember many happy — more like maddening — hours creating tiny pixela…

整整4個月了,盡全力組織了源碼共讀活動~

大家好&#xff0c;我是若川。從8月份到現在11月結束了。每周一期&#xff0c;一起讀200行左右的源碼&#xff0c;撰寫輔助文章&#xff0c;截止到現在整整4個月了。由寫有《學習源碼整體架構系列》20余篇的若川【若川視野公眾號號主】傾力組織&#xff0c;召集了各大廠對于源碼…

kvm 學習(二)

Linux下 如何通過命令行使用現有的鏡像創建、啟動kvm虛擬機 這里假定已經創建好了相應的鏡像&#xff1a; eg&#xff1a;我這里制作的鏡像名稱為zu1-centos7.img # lszu1-centos7.img 1、拷貝這個鏡像到某一個目錄 cp zu1-centos7.img /data2/ 2、編寫鏡像的配置文件&#x…

字節內部前端開發手冊(完整版)開放下載!

備戰2022&#xff0c;準備好了嗎&#xff1f;據字節HR部門發布的最新信息&#xff0c;2019年以來字節連續3年擴招&#xff0c;而即將到來的2022年春招前端崗位數不低于3000&#xff0c;雖連年擴招&#xff0c;但是報錄比卻從2019年的3%下降到今年的1%。BAT等一線大廠同樣有類似…

EBS中Java并發程序筆記(1)

在Oracle EBS中的Java并發程序&#xff08;Java Concurrent Program&#xff09;是系統功能中的一個亮點&#xff0c;它的出現使得用戶可以在ERP系統中運行自己定義的Java程序。本文為學習筆記&#xff0c;所以不會介紹太多背景知識。 使用Java并發程序的好處&#xff1a; 當遇…

figma設計_5位來自雜亂無章的設計師的Figma技巧

figma設計When starting a design project, a fast pace and multiple design iterations can easily lead to a cluttered mess. Taking the time in the beginning to build good organizational habits will save you time later. You’ll thank your past self when you do…

hello,你知道獲取元素有哪幾種方式嗎?

收下我的小心心&#xff01;&#xff08;害羞臉&#xff09; 根據id屬性的值獲取元素&#xff0c;返回來的是一個元素對象 document.getElementById("id屬性的值") 根據標簽名獲取元素&#xff0c;返回來的是一個偽數組&#xff0c;里面保存了多個的DOM對象 documen…

設計和實現一個 Chrome 插件提升登錄效率

大家好&#xff0c;我是若川。最近組織了源碼共讀活動&#xff0c;感興趣的可以點此加我微信ruochuan12 進群參與&#xff0c;每周大家一起學習200行左右的源碼&#xff0c;共同進步。已進行4個月了&#xff0c;很多小伙伴表示收獲頗豐。前言在我們的工作過程中&#xff0c;每當…

[待總結]redmine

先列出來&#xff0c;有空再總結轉載于:https://www.cnblogs.com/gracexiao/archive/2011/11/18/2253834.html

qq空間網頁設計_網頁設計中的負空間

qq空間網頁設計重點 (Top highlight)Because screens are limited, web design is also limited. It can be said that in the small box of the screen, each pixel is a piece of real estate.由于屏幕有限&#xff0c;因此網頁設計也受到限制。 可以說&#xff0c;在屏幕的小…

前端組件化-抽象公共組件類

優化上次的組件化小demo 上次的組件化demo只是為了簡單的實現前端組件化的思想&#xff0c;這次我們稍微優化一下抽離公共類 下面代碼 html <div id"wrapper"></div> 復制代碼js /* DOM字符串轉DOM節點 */ const createStringToDom str > {const ele…

時隔一年半,我,一個卑微的前端菜雞,又來寫面經了

大家好&#xff0c;我是若川。最近組織了源碼共讀活動&#xff0c;感興趣的可以點此加我微信ruochuan12 進群參與&#xff0c;每周大家一起學習200行左右的源碼&#xff0c;共同進步。已進行4個月了&#xff0c;很多小伙伴表示收獲頗豐。作者&#xff1a;刮涂層_贏大獎原文地址…

javascript模版引擎-tmpl的bug修復與性能優化

http://www.planeart.cn/?p1594 http://ejohn.org/blog/javascript-micro-templating http://bbs.phpchina.com/thread-224712-1-1.html [ Noevil: 下面直接貼出改進好的MicroTemp&#xff0c;但是還是建議看一下原文&#xff0c;里面有詳細的改進細節&#xff0c;和改進前后的…

2019.5.8_此書真乃寶書也_從定位參數到僅限關鍵字參數

《摘自流暢的Python》 此書真乃寶書也,雖說還是有點兒沒懂 從定位參數到僅限關鍵字參數 Python最好的特性之一是提供了極為靈活的參數處理機制&#xff0c;而且Python3進一步提供了僅限關鍵字參數(keyword-only argument)。與之密切相關的是&#xff0c;調用函數時使用*和**“展…

用戶體驗與可用性測試_可用性作為用戶體驗的原則

用戶體驗與可用性測試Every UX Designer has his views and best practices. We all have a guide book created through time and experience. I want to share mine with you.每個UX設計器都有他的觀點和最佳實踐。 我們都有一本通過時間和經驗編寫的指南。 我想和你分享我的…