現在的位置: 首頁 > 綜合 > 正文

如何實現 lodash.get 函數及可選鏈操作簡化取值

2020年02月21日 綜合 ⁄ 共 1823字 ⁄ 字型大小 評論關閉

  本篇文章簡介 lodash.get 函數的實現以及可替代的可選鏈操作,源於我自己的倉庫 面試每日一題 ,其中記錄了關於前端進階及工程化的各種問題。

  lodash 基本上成為了 js 項目的標配工具函數,廣泛應用在各種服務端以及前端應用中,但是它的包體積略大了一些。對於服務端來說,包的體積並不是十分的重要,或者換句話說,不像前端那樣對包的體積特別敏感,一分一毫都會影響頁面打開的性能,從而影響用戶體驗。

  正因為前端打包體積對於用戶體驗的重要性,因此有各種各樣減小包體積的方法。針對 lodash來說,你完全不必要引入 lodash 的所有工具函數,你只需要按需引入或者直接使用單函數包。

  另一方面,隨著 ES6+ 的發展,以及瀏覽器與 Node 對 ES 標準的支持增強,很多 lodash 的函數都很容易實現或者說已被 ES6+ 實現。如 _.assign , _.trim , _.startsWith 等等已被 ES6+ 實現,而 _.uniq 又很容易通過 new Set() 來解決。

  根據山月浸淫 JS 項目的多年經驗,使用 lodash 的大多數場景都是在 lodash.get ,其頻繁程度就好比 redis 界的 set/get 。那為什麼 lodash.get 會使用如此頻繁呢,這要從它解決什麼問題開始。

  lodash.get 解決什麼問題

  如上所示,當我們無法正確獲取數據時將會報錯,那如果我們想要避免錯誤的發生呢?那隻能寫一條很長很長的判斷了。

  在 js 中經常會出現嵌套調用這種情況,如 a.b.c.d.e ,但是這麼寫很容易拋出異常。你需要這麼寫 a && a.b && a.b.c && a.b.c.d && a.b.c.d.e ,但是顯得有些啰嗦與冗長了。特別是在 graphql 中,這種嵌套調用更是難以避免。

  const o = {}

  o && o.a && o.a.b && o.a.b.c && o.a.b.c.d

  恩,光是想一想每次取數據都要這麼長就很難受...

  而 lodash.get 就是解決這個問題的,這時就需要一個 get 函數,使用 get(a, 'b.c.d.e') 簡單清晰,並且容錯性提高了很多。

  _.get(o, 'a.b.c.d.e')

  如何實現 lodash.get

  get(object: object, path: [never]): never

  實現 lodash.get 的函數功能之前,先標明它的測試用例。它除了可以應用在嵌套對象上,還可以應用在嵌套數組中:

  get({ a: null }, 'a.b.c', 3)

  // output: 3

  get({ a: undefined }, 'a', 3)

  // output: 3

  get({ a: null }, 'a', 3)

  // output: 3

  get({ a: [{ b: 1 }]}, 'a[0].b', 3)

  // output: 1

  path 中也可能是數組的路徑,全部轉化成 . 運算符並組成數組:

  // a[3].b -> a.3.b

  const paths = path.replace(/\[(\d+)\]/g, '.$1').split('.')

  然後層層迭代屬性即可,另外注意 null 與 undefined 取屬性會報錯,所以使用 Object 包裝一下。

  function get (source, path, defaultValue = undefined) {

  // a[3].b -> a.3.b

  const paths = path.replace(/\[(\d+)\]/g, '.$1').split('.')

  let result = source

  for (const p of paths) {

  result = Object(result)[p]

  if (result === undefined) {

  return defaultValue

  }

  }

  return result

  }

  You Dont Need Lodash: 可選鏈

  const o = {}

  o && o.a && o.a.b && o.a.b.c && o.a.b.c.d

  可選鏈,( optional chaining ),操作符表示為 ?. ,屬於 ES2020 新增的內容,另外在 Typescript 3.7 中也添加了可選鏈的操作,大大簡化了對象的訪問。通過獲取對象屬性獲得的值可能是undefined或null時,可選鏈操作符提供了一種方法來簡化被連接對象的值訪問。

  const o = {}

  o?.a?.b?.c?.d

  當引入可選鏈之後, _.get 就不是很必要了。

抱歉!評論已關閉.