簡體   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