手把手帶你寫一個JavaScript型別判斷小工具

掘金範兒發表於2018-10-19
      業務寫了很多,依然不是前端大神,我相信這是很多‘入坑’前端開發同學的迷茫之處,個人覺得前端職業發展是有路徑可尋的,前期寫業務是一個積累過程,後期提煉總結,比如程式設計思想,父子類的原型繼承,還是物件之間的關聯委託,設計模式的熟悉和運用,這都是一個前端工程師成長為高階工程師的必經之路,而這條道路是需要我們耐住性子,請相信,生活早晚會回報我們的努力。

      話不多說,進入我們今天的主題,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)的結果

手把手帶你寫一個JavaScript型別判斷小工具

是不是很驚喜~~

我們可以利用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}複製程式碼

希望對你有所幫助,這條路還很長,慢慢來~~~

後續敬請期待演算法與資料結構系列~~~~

如果你覺得對你又幫你,請點個贊,這是對原創者最大的寫作分享動力~~~~


相關文章