手把手帶你寫一個JavaScript型別判斷小工具
業務寫了很多,依然不是前端大神,我相信這是很多‘入坑’前端開發同學的迷茫之處,個人覺得前端職業發展是有路徑可尋的,前期寫業務是一個積累過程,後期提煉總結,比如程式設計思想,父子類的原型繼承,還是物件之間的關聯委託,設計模式的熟悉和運用,這都是一個前端工程師成長為高階工程師的必經之路,而這條道路是需要我們耐住性子,請相信,生活早晚會回報我們的努力。
話不多說,進入我們今天的主題,JavaScript中判斷一個數據的型別有多種方式:typeof、instanceof、constructor、Object.prototype.toString.call,一般判斷簡單的資料型別我們會使用typeof,但是對於陣列,正則型別的資料,typeof是無能為力的,instanceof一般用於判斷物件的繼承關係,今天我們主要說的是Object.prototype.toString.call這個方法。
1.判斷型別
我們可以寫一個isType的方法來判斷資料的型別,傳入兩個引數,第一個是需要判斷的資料,第二個是資料型別。
前置知識:各個型別通過Object.prototype.toString.call方法後得到的結果 console.log(Object.prototype.toString.call('hello')) //[object String] console.log(Object.prototype.toString.call(34)) //[object Number] console.log(Object.prototype.toString.call(true))// [object Boolean] console.log(Object.prototype.toString.call(undefined)) //[object Undefined] console.log(Object.prototype.toString.call(function f() {})) // [object Function] 下面我們就開始擼程式碼了: function isType(content,type){ //這裡我們通過正則匹配去掉'[object ]',只留下型別 let t = Object.prototype.toString.call(content).replace(/\[object\s|\]/g,''); //將得到的t與傳入的type進行比較,返回結果,結果為Boolean型別 return t === type; } //執行函式並將結果返回給res,列印res let res = isType('hello','String') console.log(res);//true複製程式碼
是不是非常簡單,對自己又充滿信心了,不過如此嘛!!確實很簡單,來,繼續,一點點深入~~
通過上面的一個函式我們就可以很容易的判斷一個JavaScript資料的型別,但是我們在使用的時候是這個樣子的:
let res1 = isType('hello','String'); let res2 = isType(123,'Number'); let res3 = isType(true,'Boolean'); 複製程式碼
我們每次在使用的時候都是手動傳入型別,很有可能手一抖,就傳錯型別了,本來'String',我們傳入了'Strings',是不是很坑爹呀~~
一般的庫或者外掛不會這樣去讓我們使用,一般會這麼使用utils.isString('hello'),我們只需要傳入我們的資料就可以了,外掛會提供相應的判斷方法,比如
utils.isString('hello'); utils.isNumber(123); utils.isBoolean(true);複製程式碼
這裡我們需要批量化生產函式,就需要用到下面的一個函式返回一個函式,也就是所謂的閉包,也被叫做高階函式,不要那些高大上,我們程式員都是接地氣的~~,初學者對於閉包理解起來比較困難,不著急,隨著你的深入,都會明白的~~~
2.一個函式返回一個函式
接下來我們對上面的isType函式進行改造,
let isNumber = isType('Number'); let isString = isType('String'); let isBoolean = isType('Boolean'); isNumber(12); isString('hello'); isBoolean(true)複製程式碼
通過執行isType(),我們可以得到想要的函式,說明在isType內部,我麼返回了一個函式,返回的這個函式對於外層函式 (也就是isType) 的引數進行了引用,JavaScript的垃圾回收機制是不會回收被引用的資料的,所以type被保留在了返回函式的內部,這就是閉包機制。
function isType(type) { return function(content) { let t = Object.prototype.toString.call(content).replace(/\[object\s|\]/g,''); return t === type; } }複製程式碼
通過執行isType,我們得到了對內部函式的引用。
isNumber(12); isString('hello'); isBoolean(true);複製程式碼
上面其實就是對isType內部函式的執行。
也不過如此嘛,說好的手把手帶我們寫一個判斷型別外掛呢!?
3.屬於我們自己的判斷JavaScript型別外掛
有些同學已經有啟發了,我們可以這樣操作
let type = ['String','Number','Function','Undefined','Boolean','Array']; let utils = {}; type.forEach(item => { utils['is' + item] = isType(item); }) 複製程式碼
下面是console.log(utils)的結果
是不是很驚喜~~
我們可以利用ES6的模組化機制來封裝這個方法,然後erport 出去供小夥伴使用,是不是很簡單,也可以上傳到npm,供廣大開發者使用,是不是很有成就感。(估計這個難度的外掛去你npm下載使用的人幾乎沒有,這裡我們掌握怎麼通過閉包去處理問題這個思想就行)下面是完整版utils.js
function isType(type) { return function(content) { let t = Object.prototype.toString.call(content).replace(/\[object\s|\]/g,''); return t === type; } } function createUtils(){ let utils = {}; let type = ['String','Number','Function','Undefined','Boolean','Array']; type.forEach(item => { utils['is' + item] = isType(item); }) return utils; } let utils = createUtils(); export default{utils}複製程式碼
希望對你有所幫助,這條路還很長,慢慢來~~~
後續敬請期待演算法與資料結構系列~~~~
如果你覺得對你又幫你,請點個贊,這是對原創者最大的寫作分享動力~~~~