请实现 Lodash 的 .get()

2022年10月2日

💎 加入 E+ 成長計畫 與超過 300+ 位軟體工程師一同在社群中成長,並且獲得更多的軟體工程學習資源

Lodash 的 .get() 在做什么?

.get() 是很常被用到的一个效用函式,他做的事情是给定一个物件,以及某个路径,要回传此路径的值;如果该路径不存在于给定的物件,则返回预设值。透过例子会比较好理解 (以下例子来自 Lodash 原始码)

const object = { a: [{ b: { c: 3 } }] };

//=> 3
get(object, "a[0].b.c");

//=> 3
get(object, 'a[0]["b"]["c"]');

//=> 'default
get(object, "a[100].b.c", "default");

从上面的例子可以看到 Lodash 这个函式库,可以接收各种类型的路径,主要是原始码当中有castPath这个 helper function。 castPath 会把上面的"a[0].b.c"'a[0]["b"]["c"]' 以及"a[100].b.c" 都转成好处理的['a', '0', 'b', 'c']

因此,如果给定有内建的 castPath.get() 实际在做的事情是

// 给定一个物件,例如
const object = { a: [{ b: { c: 3 } }] };

// 给一个路径,透过 .get() 找到该路径的值,例如
get(object, ["a", "0", "b", "c"]); // 回传 3

实现 .get()

一起来看看如何实现 .get()

function lodashGet(object, path, defaultValue) {
  // 先确认传进来的 object 不是 null,如果是则直接回传 defaultValue
  if (object == null) {
    return defaultValue;
  }

  let count = 0;
  const length = path.length;

  // 依循路径一层层走过该物件,以上面的例子来说,会是
  // path[0] 为 'a',所以第一次回圈 object 会变成 object['a'] 也就是 [{ b: { c: 3 } }]
  // 第一次回圈后,count 加 1,所以变成 object[path[1]]
  // 也就是 [object['0']],意即 { b: { c: 3 } }
  // 接着 count 再加一,所以 object 会成为 object[path[2]]
  // 也就是 object['b'],意即 { c: 3 }
  // 接着 count 再加一,所以 object 会成为 object[path[3]]
  // 也就是 object['c'],意即 3
  // 这时 count 为 4,由于 length 也是 4,因为 4 不小于 4,所以跳出回圈
  while (object != null && count < length) {
    object = object[path[count++]];
  }

  // 因为上面如果 object 是 null 的话,在走完 length 长度前,就会跳出 while 回圈
  // 这种情况下,就代表依循该路径,会找不到值,所以会是 undefined
  // 举例来说,如果 path 是 ['a', '1', 'b', 'c']
  // 因为 object['1'] 会是 undefined,所以这时 while 回圈会在 count 为 2 时终止
  // 这种情况下就会是 count < length,所以当 count < length,result 会是 undefined
  const result = count && count == length ? object : undefined;

  // 如果 result 是 undefined,代表依循该路径,会找不到值,所以回传预设值
  // 如果依循路径有找到值,就回传 result
  return result === undefined ? defaultValue : result;
}
🧵 如果你想收到最即時的內容更新,可以在 FacebookInstagram 上追蹤我們