通过任意数量的参数设置对象的嵌套键/值

时间:2018-09-20 18:21:50

标签: javascript

假设我有一些像这样的对象:

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()
}

这样我就可以设置值:

  • xsetKV(someObj, 'x', true)
  • zsetKV(someObj, 'y', 'z', true)
  • csetKV(someObj, 'a', 'b', 'c', true)

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

3 个答案:

答案 0 :(得分:3)

您可以使用rest参数和下面的...rest这样的散布参数轻松地做到这一点。 setKV不会更改其输入对象o;总是返回 new 对象。

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)

答案 1 :(得分:1)

lodash提供您想要的内容,无需重写

https://lodash.com/docs/4.17.10#set

_.set(someObj, ['a', 'b', 'c'], true);

答案 2 :(得分:1)

我们可以创建函数,其中剩余参数是两个元素数组,其中第一项是键名,而secound是所需值

function setKV(obj, ...kvs) {
    return kvs.reduce((obj, [k, v]) => {
        obj[k] = v;
        return obj;
    }, obj);
}

function setKV(obj, ...kvs) {
	return kvs.reduce((obj, [k, v]) => {
		obj[k] = v;
		return obj;
	}, obj);
}

console.log(setKV({}, [
	"a",
	1
], [
	"b",
	"b"
]));