繁体   English   中英

返回数组时对象数组的对象属性发生变化

[英]Object array's object properties changing when returning array

我有一个功能可以操纵和创建对象数组,并向数组中的每个项目添加position键,但是它似乎根本无法正常工作...

我的功能:

var fillQueue = function(choices, currentQueue) {
  var choice, i, positionInQueue, previousTitle, resultQueue;

  resultQueue = [];
  previousTitle = "";

  i = 0;

  while (i < 10) {
    positionInQueue = i + 1;
    console.log('Adding song to position ' + positionInQueue);

    if (currentQueue[i]) {
      previousTitle = currentQueue[i].title;
      currentQueue[i].position = positionInQueue;
      resultQueue.push(currentQueue[i]);
    } else {
      choice = choices[Math.floor(Math.random() * choices.length)];

      if (choice.title !== previousTitle) {
        previousTitle = choice.title;
        choice.position = positionInQueue;
        resultQueue.push(choice);
      } else {
        choice = choices[Math.floor(Math.random() * choices.length)];
        previousTitle = choice.title;
        choice.position = positionInQueue;
        resultQueue.push(choice);
      }
    }

    i++;
  }

  return resultQueue;
};

如果正确调用此函数,将值替换为choicescurrentQueuecurrentQueue也可以是空数组),如下所示,该函数将返回一个预期的数组,但是由于某种原因,需要拧紧其中每个对象的position键。

var test = fillQueue([ {title: '1'}, {title: '2'}, {title: '3'}, {title: '4'} ], [ { title: '5', position: 1 } ]);

上面的变量将包含以下内容:

[ { title: '5', position: 1 },
  { title: '1', position: 9 },
  { title: '3', position: 7 },
  { title: '1', position: 9 },
  { title: '2', position: 10 },
  { title: '2', position: 10 },
  { title: '3', position: 7 },
  { title: '1', position: 9 },
  { title: '1', position: 9 },
  { title: '2', position: 10 } ]

如您所见,它没有将position正确地添加到每个对象中。 返回数组中的每个对象都应具有i + 1position ,但似乎是从1到10的某个随机数-某些对象甚至具有相同的position

我努力了:

  • position重命名为其他名称,以防它已被JavaScript使用
  • 确保正确的position被添加到对象之前和之后.push将其投入的阵列。

这让我真的很困惑。 您的帮助将不胜感激。

小提琴: https : //jsfiddle.net/deansheather/jnw8jdf4/

您正在将引用推入数组,因此每次更新choice.position时 ,对数组中同一选项的所有引用都会获得相同的位置值。

要解决此问题,请复制选择对象,更新其位置并将其推入数组,例如

if (choice.title !== previousTitle) {
        previousTitle = choice.title;
        newChoice = objCopyShallow(choice); // see below for copy function
        newChoice.position = positionInQueue;
        resultQueue.push(newChoice);
}

对于此应用程序,一个简单的复制功能是:

function objCopyShallow(obj) {
  return Object.keys(obj).reduce(function(acc, v) {
      acc[v] = obj[v];
      return acc;
    },{});
}

如果您想要更深入的了解,这里有关于“如何复制对象”的一百万个问题和答案。

就像RobG已经说过的那样,您正在推送对数组的引用。因此创建您选择对象的副本,然后推送到您的数组。 使用clone()创建对象的副本,将您的分配更改为choice = clone(choices[Math.floor(Math.random() * choices.length)]); 你完成了。

function clone(obj) {
    if (null == obj || "object" != typeof obj) return obj;
    var copy = obj.constructor();
    for (var attr in obj) {
        if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
    }
    return copy;
}

我能够提出以下建议。 这可以避免在JS中使用引用为“陷阱”的for / while循环,因此在使用它更新值时需要注意这一点。

 var fillQueue = function(choices, currentQueue) { // concat choices to end of currentQueue // create a new array instance with updated position property using .map // keep 10 elements from new array starting at index 0 return currentQueue.concat(choices).map( (e, i) => { return Object.assign({title:e.title, position:i+1}); }).splice(0, 10) }; 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM