我有一个函数可以操作和创建一个对象数组,并为数组中的每个项添加一个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
添加到每个对象中。返回数组中的每个对象都应该有position
i + 1
,但它似乎是1到10之间的一些随机数 - 有些对象甚至具有相同的position
。< / p>
我尝试过:
position
重命名为其他内容,以防它已被JavaScript使用position
之前和之后将正确的.push
添加到对象中。这让我很困惑。感谢您的帮助。
答案 0 :(得分:1)
您正在将引用推送到数组中,因此每次更新 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;
},{});
}
这里有一百万个问题和答案关于&#34;如何复制一个对象&#34;如果你想要更深层次的东西。
答案 1 :(得分:1)
正如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;
}
答案 2 :(得分:0)
我能够想出以下内容。这是因为我避免使用for / while循环,这些循环有参考&#34;陷阱&#34;在JS中,您需要注意何时使用它来更新值。
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)
};
&#13;