[英]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;
};
如果正确调用此函数,将值替换为choices
和currentQueue
( currentQueue
也可以是空数组),如下所示,该函数将返回一个预期的数组,但是由于某种原因,需要拧紧其中每个对象的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 + 1
的position
,但似乎是从1到10的某个随机数-某些对象甚至具有相同的position
。
我努力了:
position
重命名为其他名称,以防它已被JavaScript使用 position
被添加到对象之前和之后.push
将其投入的阵列。 这让我真的很困惑。 您的帮助将不胜感激。
您正在将引用推入数组,因此每次更新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.