lodash源碼分析之數據類型獲取的兼容性

焦慮和恐懼的區別是,恐懼是對世界上的存在的恐懼,而焦慮是在"我"面前的焦慮。

——薩特《存在與虛無》javascript

本文爲讀 lodash 源碼的第十九篇,後續文章會更新到這個倉庫中,歡迎 star:pocket-lodashjava

gitbook也會同步倉庫的更新,gitbook地址:pocket-lodashgit

前言

在前文《lodash源碼分析之獲取數據類型》已經解釋了獲取數據類型的方法,可是在有些環境下,一些 es6 新增的對象獲取到的類型都爲 [object Object] ,這樣就沒辦法作細緻的區分。例如在 IE11 中,經過 Object.prototype.toString 獲取到的 DataView 對象類型爲 [object Object]。 所以在 getTag 中,lodash 針對這些對象作了一些兼容性的事情。es6

依賴

import baseGetTag from './baseGetTag.js'

lodash源碼分析之獲取數據類型github

源碼分析

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 的源碼很簡單,處理的是 DataViewMapSetPromiseWeakMap 等對象,下面就關鍵的幾點說明一下。promise

函數的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]源碼分析

License

署名-非商業性使用-禁止演繹 4.0 國際 (CC BY-NC-ND 4.0)spa

最後,全部文章都會同步發送到微信公衆號上,歡迎關注,歡迎提意見:

做者:對角另外一面

相關文章
相關標籤/搜索