手寫 lodash/get、lodash/set 方法


動機:平時寫js代碼時經常遇到要使用 lodash 中 _.get 和 _.set 的情況,每次使用都要引用 lodash,總感覺很煩,能不能自己實現一個簡單的方法來實現一樣的功能呢?

get 方法實現

  1. get 方法接受三個參數,第一個是目標對象或者數組,第二個是獲取值的路徑,第三個是獲取失敗時的默認值
function get(object, path, defaultValue) {
    // 判斷 object 是否是數組或者對象,否則直接返回默認值 defaultValue
    if (typeof object !== 'object') return defaultValue
    // 沿着路徑尋找到對應的值,未找到則返回默認值 defaultValue
    return _basePath(path).reduce((o, k) => (o || {})[k], object) || defaultValue
}

// 處理 path, path有三種形式:'a[0].b.c'、'a.0.b.c' 和 ['a','0','b','c'],需要統一處理成數組,便於后續使用
function _basePath(path) {
    // 若是數組,則直接返回
    if (Array.isArray(path)) return path
    // 若有 '[',']',則替換成將 '[' 替換成 '.',去掉 ']'
    return path.replace(/\[/g, '.').replace(/\]/g, '').split('.')
}

set 方法實現

  1. set 方法同樣接受三個參數,第一個是源對象或者源數組,第二個是設置值的路徑,第三個是value
function set(object, path, value) {
    if (typeof object !== 'object') return object;
    _basePath(path).reduce((o, k, i, _) => {
        if (i === _.length - 1) { // 若遍歷結束直接賦值
            o[k] = value
            return null
        } else if (k in o) { // 若存在對應路徑,則返回找到的對象,進行下一次遍歷
            return o[k]
        } else { // 若不存在對應路徑,則創建對應對象,若下一路徑是數字,新對象賦值為空數組,否則賦值為空對象
            o[k] = /^[0-9]{1,}$/.test(_[i + 1]) ? [] : {}
            return o[k]
        }
    }, object)
    // 返回object
    return object;
}

測試

let obj = { a: [{ b: { c: 6 } }] }
console.log(get(obj, 'a[0].b.c', '默認值')) // 6
console.log(get(obj, 'a.5.b.c', '默認值')) // '默認值'
console.log(get(obj, ['a', '0', 'b', 'c'], '默認值')) // 6

let obj1 = { a: [{ b: { c: 6 } }] }
let obj2 = { }
let obj3 = { }
set(obj1, 'a[0].b.c', '默認值')
set(obj2, 'a.0.b.5.c', '默認值')
set(obj3, ['1', '2', 'b', 'c'], '默認值')
console.log(JSON.stringify(obj1)) // {"a":[{"b":{"c":"默認值"}}]}
console.log(JSON.stringify(obj2)) // {"a":[{"b":[null,null,null,null,null,{"c":"默認值"}]}]}
console.log(JSON.stringify(obj3)) // {"1":[null,null,{"b":{"c":"默認值"}}]}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM