前端面試手寫練習 - get
- 文章發表於
問題
以前在讀取物件中深層嵌套的屬性時,為了確保程式不會因為中間某個屬性不存在而報錯,我們往往會使用第三方函式庫來處理這個問題,例如 lodash 函式庫中的 _.get
函式。
儘管現在可選串連 (optional chaining) 運算子 ?.
的普及,讓我們對這類型的函式依賴度降低,但其實現方式仍值得探討。
const user1 = {profile: {name: { firstName: 'John', lastName: 'Doe' },age: 99,gender: 'Male',},}const user2 = {profile: {age: 79,gender: 'Female',},}function getFirstName(user) {return user.profile.name.firstName}
舉上面例子來說,getFirstName(user1)
可以正常執行,但是執行 getFirstName(user2)
則會因為 user2.profile
裡不存在 name
屬性而噴錯。
接下來讓我們寫一個自己的版本作為 get
。該函式接受一個物件、一個路徑字串或路徑陣列,以及一個可選的預設值。如果路徑存在,則返回路徑對應的值,否則返回預設值。
範例
get(user1, 'profile.name.firstName') // 'John'get(user1, 'profile.gender') // 'Male'get(user2, 'profile.name.firstName') // undefinedget(user2, 'profile.name.firstName', 'Unknown') // 'Unknown'
練習區
在了解問題後,可以嘗試先寫下您的思路,再到下方的練習區域實際寫出程式碼。
追問
- 如果你是用遞迴 (Recursion) 的方式來實踐,那是否可以也用迭代 (Iteration) 的方式來實踐? 反之。
筆者思路
遞迴 (Recursion)
- 首先我們需要判斷
path
是否為字串,如果是字串則將其轉換為陣列。 - 建立一個 helper function 來處理遞迴。
- 定義基本情況 (base case),如果
path
長度為0
則回傳object
本身。 - 將
object
指向path
的第一個元素,並將path
切片 (slice)。 - 重複呼叫 helper function 直到
path
長度為0
。
迭代 (Iteration)
- 首先我們需要判斷
path
是否為字串,如果是字串則將其轉換為陣列。 - 對
path
進行迭代,並判斷如果object
裡有對應的 path 則將object
指向該 path 的值。否則回傳defaultValue
。 - 回傳最後指針 (pointer) 指向的位置
筆者解答
遞迴 (Recursion)
function get(object, path, defaultValue = undefined) {path = Array.isArray(path) ? path : path.split('.')const helper = (obj, p) => {if (p.length === 0) {return obj}if (obj[p[0]]) {return helper(obj[p[0]], p.slice(1))} else {return defaultValue}}return helper(object, path)}
迭代 (Iteration)
function get(object, path, defaultValue = undefined) {path = Array.isArray(path) ? path : path.split('.')let result = objectif (path.length === 0) {return defaultValue}for (let item of path) {if (result[item]) {result = result[item]} else {result = defaultValuebreak}}return result}
相關題目
如果您喜歡這篇文章,請點擊下方按鈕分享給更多人,這將是對筆者創作的最大支持和鼓勵。