猿问

如何使用 JavaScript 将数组中的值注入对象?

我想从对象中提取值(完成),然后将其放入数组(完成),然后更改这些值(通过补间库)并作为值数组返回给我。


我想将这些值重新插入到它们来自的相同形状的对象中。


但我被困在一些相当基本的东西上,而且肯定是可行的。


我有一个示例状态,就像这样(它可能是完全不同的形状,这只是一个示例):


var state = { 

  ignore: "me",

  count: 0,

  foo: 10,

  bar: {

    baz: 99

  }

}

我有一个新状态,我想将它传递给我的补间方法:


var newState = { 

  count: 100,

  foo: 50,

  bar: {

    baz: 999

  }

}

该方法中有一个补间库tweenState,它在动画的每个“帧”处生成这些值的数组:



// NOTE: I only pass in the properties I wanna tween!!


myApp.tweenState({ count: 100, foo: 50, bar: { baz: 999 } })


// internally, the tween lib produces something like this on each frame:


tweenedValues = [ 50.1231, 34.43543, 456.4543 ]


我想将这些补间值插入到与我正在使用的状态对象形状相同的对象中,以在每个帧上创建它(根据上面的示例状态):


tweenedState = { 

  ignore: "me",

  count: 50.1231,

  foo: 34.43543,

  bar: {

    baz: 456.4543

  }

}

...到目前为止,我只有这个糟糕的代码(在每一帧上调用):


  // make sure tweened values are in an array

  var valuesArr = Array.isArray(tweenedValues) ? tweenedValues : [tweenedValues]

  // this object will hold tween values of current frame/progress, 

  // set to original state for now... we'll update it's values from 

  // valuesArr later

  var tweenedState = self.state

  // set the newState properties with new values from valuesArr

  // (newState is the state passed into the tweenState() method)

  Object.keys(newState).forEach((key, index) => {

    if (typeof newState[key] === "object") {

      Object.keys(newState[key]).forEach(key2 => {

        tweenedState[key][key2] = valuesArr[index]

      })

其中有这些明显的问题:

  • 不是递归的,不能深入到一个对象中超过 2 层

  • 在任何情况下,该行都tweenedState[key][key2] = valuesArr[index]没有按预期设置值

  • 当我把它变成一个递归函数时,它永远循环并崩溃

所以,我需要一个函数来获取数组,并将值插入到正确的位置——即传入的属性开始(创建tweenedState对象)。

编辑:显然,状态对象可能看起来完全不同 - 给出的只是一个例子 - 它可能有很多层次,并且可能包含其他未传入的东西。关键是我最终得到了一个状态对象像原来的一样,但插入了补间值。

我再说一遍 - Tween 库创建了值数组,不是我,不是我的选择。是的,我知道对象属性并不总是相同的顺序。

编辑 2:此代码必须是同构的 - 在最近的浏览器(不关心 IE)Node 10 或更高版本中工作,理想情况下没有 polyfills...

编辑 3:现已解决:

NinaScholz 和 mashi 都提供了对我有用的答案(在我修复了其他地方的错误之后)。

Ninas 的答案有更严格的 JS 版本要求,并且比 mashis 的答案更不便携。在此基础上,我接受了 mashis 的回答,尽管 Ninas 的回答也非常好。

谢谢。


翻过高山走不出你
浏览 157回答 3
3回答

跃然一笑

function setTweenedValues(state, values) {  const reducer = (newState, [key, val]) => {    newState[key] = val;    if (typeof val === "number") {      newState[key] = values.shift();    }    if (typeof val === "object") {      newState[key] = Object.entries(val).reduce(reducer, {});    }    return newState;  };  const newState = Object.entries(state).reduce(reducer, {});  return newState;}var state = { count: 200, foo: 10, bar: { zzz: 999 }, ignore: "me" },    tweenedValues = [50.1231, 34.43543, 456.4543],    tweenedState = setTweenedValues(state, [...tweenedValues]);console.log(tweenedState);

有只小跳蛙

您可以迭代条目并再次为嵌套条目调用该函数。function setValues(pattern, values) {    return Object.fromEntries(Object        .entries(pattern)        .map(([k, v]) => [            k,            v && typeof v === 'object'                ? setValues(v, values)                : values.length ? values.shift() : v        ])    );}var state = { count: 200, foo: 10, bar: { zzz: 999 }, ignore: "me" },    tweenedValues = [50.1231, 34.43543, 456.4543],    tweenedState = setValues(state, [...tweenedValues]);console.log(tweenedState);

守候你守候我

如我所见,您在数组中的值始终处于保证顺序,并且您希望它们作为对象中的道具值...您可以使用对象解构const [count, foo, bar] = tweenedValues;然后像这样制作对象let obj = {count, foo, bar}
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答