lodash原始碼分析之資料型別獲取的相容性
焦慮和恐懼的區別是,恐懼是對世界上的存在的恐懼,而焦慮是在"我"面前的焦慮。
——薩特《存在與虛無》
本文為讀 lodash 原始碼的第十九篇,後續文章會更新到這個倉庫中,歡迎 star:ofollow,noindex">pocket-lodash
gitbook也會同步倉庫的更新,gitbook地址:pocket-lodash
前言
在前文《lodash原始碼分析之獲取資料型別
》已經解釋了獲取資料型別的方法,但是在有些環境下,一些es6
新增的物件獲取到的型別都為[object Object]
,這樣就沒辦法做細緻的區分。例如在 IE11 中,通過Object.prototype.toString
獲取到的DataView
物件型別為[object Object]
。 因此在getTag
中,lodash 針對這些物件做了一些相容性的事情。
依賴
import baseGetTag from './baseGetTag.js' 複製程式碼
原始碼分析
const dataViewTag = '[object DataView]' const mapTag = '[object Map]' const objectTag = '[object Object]' const promiseTag = '[object Promise]' const setTag = '[object Set]' const weakMapTag = '[object WeakMap]' /** Used to detect maps, sets, and weakmaps. */ const dataViewCtorString = `${DataView}` const mapCtorString = `${Map}` const promiseCtorString = `${Promise}` const setCtorString = `${Set}` const weakMapCtorString = `${WeakMap}` let getTag = baseGetTag // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || (getTag(new Map) != mapTag) || (getTag(Promise.resolve()) != promiseTag) || (getTag(new Set) != setTag) || (getTag(new WeakMap) != weakMapTag)) { getTag = (value) => { const result = baseGetTag(value) const Ctor = result == objectTag ? value.constructor : undefined const ctorString = Ctor ? `${Ctor}` : '' if (ctorString) { switch (ctorString) { case dataViewCtorString: return dataViewTag case mapCtorString: return mapTag case promiseCtorString: return promiseTag case setCtorString: return setTag case weakMapCtorString: return weakMapTag } } return result } } 複製程式碼
getTag
的原始碼很簡單,處理的是DataView
、Map
、Set
、Promise
、WeakMap
等物件,下面就關鍵的幾點說明一下。
函式的toString方法
const dataViewCtorString = `${DataView}` const mapCtorString = `${Map}` const promiseCtorString = `${Promise}` const setCtorString = `${Set}` const weakMapCtorString = `${WeakMap}` 複製程式碼
我們都知道,DataView
這些其實都是建構函式,函式有toString
的方法,呼叫後返回的是function DataView() { [native code] }
這樣的格式,因為其例項呼叫Object.prototype.toString
在某些環境下返回的是[object Object]
,而建構函式的toString
返回的字串中,包含了建構函式名,可以通過這點來區分。
例項中建構函式的獲取
const Ctor = result == objectTag ? value.constructor : undefined const ctorString = Ctor ? `${Ctor}` : '' 複製程式碼
每個例項中都包含一個constructor
的屬性,這個屬性指向的是例項的建構函式,在獲取到這個建構函式後,就可以呼叫它的toString
方法,然後就可以比較了。
Promise.resolve
getTag(Promise.resolve()) != promiseTag 複製程式碼
在條件判斷時,使用了Promise.resolve()
,這樣使用的目的是獲取到promise
物件,因為Promise
是一個函式函式,如果直接呼叫Object.prototype.toString
,返回的是[object Function]
。