首页 > 解决方案 > 通过任意数量的参数设置对象的嵌套键/值

问题描述

假设我有一些对象,例如:

const someObj = {
  x: null,
  y: {
    z: null
  },
  a: {
    b: {
      c: null
    }
  }
}

我想创建一个函数来使用类似的东西设置值:

const setKV = (obj, ...keyArray) => {
  /* Not quite sure how to phrase this function */
  const val = keyArray.pop()
}

这样我就可以设置值:

我如何通过这个任意数量的参数定义对象的嵌套键?

标签: javascript

解决方案


您可以使用...rest下面的 rest 参数和 spread 参数轻松地做到这一点。setKV不改变其输入对象o;总是返回一个新对象。

const setKV = (o = {}, key, value, ...rest) =>
  rest.length === 0
    ? { ...o, [key]: value }
    : { ...o, [key]: setKV (o[key], value, ...rest) }

console.log
  ( setKV ({ a: 0 }, 'b', 1)
    // { a: 0, b: 1 }

  , setKV ({ a: { b: { c: false } } }, 'a', 'b', 'c', true)
    // { a: { b: { c: true } } }
    
  , setKV ({}, 'a', 'b', 'c', 1)
    // { a: { b: { c: 1 } } }
    
  , setKV ({ a: { b: { c: 0 } } }, 'a', 'b', 'd', 0)
    // { a: { b: { c: 0, d: 0 } } }
    
  , setKV ({ a: { b: { c: 0 } } }, 'a', 'b', 1)
    // { a: { b: 1 } }
    
  , setKV ({ a: 1, b: { c: 2, d: { e: 3 } } }, 'b', 'd', 'e', { f: 4 })
    // { a: 1, b: { c: 2, d: { e: { f: 4 } } } }

  , setKV ({ a: 0 }, 'b')
    // { a: 0, b: undefined }
  )

“如果我确实想改变输入对象......”

虽然应该避免突变,但您的程序的特定需求可能需要使用它们。在这种情况下,检查mutKV一下,看看它与上面的实现有何不同

const mutKV = (o = {}, key, value, ...rest) =>
  rest.length === 0
    ? (o[key] = value, o)
    : (o[key] = mutKV (o[key], value, ...rest), o)

const data =
  { a: 0 }

mutKV (data, 'b', 1)
console.log (data) 
// { a: 0, b: 1 }

mutKV (data, 'c', 'd', 2)
console.log (data)
// { a: 0, b: 1, c: { d: 2 } }

mutKV (data, 'c', 'd', 3)
console.log (data)
// { a: 0, b: 1, c: { d: 0 } }

mutKV (data, 'c', 4)
console.log (data)
// { a: 0, b: 1, c: 4 }

这为本书打开了关于副作用的简短课程,并使用effect. mut下面我们使用创建一个效果effect,然后mut在每个分支中使用mutKV。该程序的行为与mutKV上述相同。

const effect = f => x =>
  (f (x), x)

const mut = (key, value) =>
  effect (o => o[key] = value)

const mutKV = (o = {}, key, value, ...rest) =>
  rest.length === 0
    ? mut (key, value) (o)
    : mut (key, mutKV (o[key], value, ...rest)) (o)

推荐阅读