lodash庫中判斷數據類型涉及兩個方法,getTag和baseGetTag,下面是baseGetTag:
const objectProto = Object.prototype const hasOwnProperty = objectProto.hasOwnProperty//Object.prototype.hasOwnProperty const toString = objectProto.toString//Object.prototype.toString const symToStringTag = typeof Symbol != 'undefined' ? Symbol.toStringTag : undefined //當前環境是否支持Symbol然后獲取對應的Symbol.toStringTag /** * The base implementation of `getTag` without fallbacks for buggy environments. * * @private * @param {*} value The value to query. * @returns {string} Returns the `toStringTag`. */ function baseGetTag(value) { if (value == null) {//如果值是undefined和null返回對應tag return value === undefined ? '[object Undefined]' : '[object Null]' } if (!(symToStringTag && symToStringTag in Object(value))) { //如果不支持Symbol或者value值上面沒有Symbol.toStringTag屬性,直接返回Object.prototype.toString調用后的值 return toString.call(value) } const isOwn = hasOwnProperty.call(value, symToStringTag)//value自身是否有Symbol.toStringTag屬性 const tag = value[symToStringTag]//存下value上的Symbol.toStringTag屬性 let unmasked = false//將value自身上的Symbol.toStringTag屬性重置為undefined是否成功 try {//嘗試將value自身上的Symbol.toStringTag屬性重置為空 value[symToStringTag] = undefined unmasked = true } catch (e) {} const result = toString.call(value) //value自身Symbol.toStringTag屬性置空后獲取toString處理后的tag if (unmasked) {//如果Symbol.toStringTag屬性置空成功,再將Symbol.toStringTag屬性變回原樣 if (isOwn) { value[symToStringTag] = tag } else { delete value[symToStringTag] } } return result } export default baseGetTag
下面是getTag:
import baseGetTag from './baseGetTag.js' /** `Object#toString` result references. */ //Dateview,Map,Promise,Set,WeakMap這幾種類型和Object應該返回的類型tag 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. */ //Dateview,Map,Promise,Set,WeakMap這幾種類型的構造函數屬性返回的字符串 const dataViewCtorString = `${DataView}` const mapCtorString = `${Map}` const promiseCtorString = `${Promise}` const setCtorString = `${Set}` const weakMapCtorString = `${WeakMap}` /** * Gets the `toStringTag` of `value`. * * @private * @param {*} value The value to query. * @returns {string} Returns the `toStringTag`. */ 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)) {//如果在某些環境下無法判斷這5種類型,就做一下兼容處理 getTag = (value) => { const result = baseGetTag(value) const Ctor = result == objectTag ? value.constructor : undefined const ctorString = Ctor ? `${Ctor}` : '' //獲取值的constructor構造函數屬性,如果獲取到了就返回對應的tag,如果獲取不到就返回原始toString值 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 } } export default getTag