繁体   English   中英

.forEach方法将更新应用于数组中的所有项而不是单个项

[英].forEach method applying update to all items in array instead of individual item

我正在为我的一些学生做一个小练习,我正在自动化一种10针保龄球游戏,我把它放到了JsBin这里https://jsbin.com/qilizo/edit?html,js,output 我不知道我是否累,愚蠢还是因为我正在全国性的假期工作,但有些事让我感到困惑。 当我开始游戏时,我提示用户设置一些所需的玩家。 这会自动生成一个玩家对象数组,如下所示:

[{score: Array[10], spareCount: 0, strikeCount: 0, username: "Player 1"}, ...]

现在稍后我允许用户播放我们阵列中的每个玩家有两次投掷的帧...我收集得分并将其添加到特定玩家的得分数组。 但是当我尝试使用.forEach方法执行此操作时,我生成的分数将应用于我的Players数组中的所有项目(玩游戏并查看)。 我把我的代码放在一个jsBin中,问题出在第109行: a.score[currentFrame - 1] = playFrame();

我试图修改我的代码,但我无法弄清楚为什么当前(或最后)帧分数应用于所有Player对象! 如果你能理解我的语法错误并解释为什么我会非常感激。 玩游戏(只需在设置玩家编号后点击按钮),你就会明白我的意思......

片段:

 var players, currentFrame = 0, currentThrow = 0; // helper functions // Accurate isNumber function... Thank you Crockford (see JavaScript: The Good Parts) function isNumber(value) { return typeof(value === 'number') && isFinite(value); } function frameStyle(k) { var returnCssClass, k = k + 1; if (k < currentFrame) { returnCssClass = 'played-frame'; } else if (k === currentFrame) { returnCssClass = 'current-frame'; } else { returnCssClass = null; } return returnCssClass; } function setUpPlayers(num) { var tempArray = [], tempName = 'Player ', emptyScores = Array(10).fill([-1, -1]); // set default to -1 as a rubbish player may hit no pins! for (var i = 0; i < num; i++) { tempArray.push({ username: tempName + (i + 1), score: emptyScores, strikeCount: 0, spareCount: 0 }); // the way I have named the tempName is technically an antipattern! } return tempArray; } function getTotals(scores) { var totalScore = scores.reduce(function(a, b) { return a + b.reduce(function(c, d) { return (c + (c + ((d > 0) ? d : 0))); }, 0); }, 0); return totalScore; } function displayScore(score) { // toDo reformat! var formatScore = score.map(function(a, b) { if (a === -1) { a = '-'; } else if (a === 10) { a = 'X'; } return a; }); return formatScore; } function createGrid() { // If only I was using ES6 I could have multi line support! var playerLen = players.length, scoresLen = players[0].score.length; boards = '<div class="score-board">' + '<!-- one row for each player -->'; // need to loop this through the players... for (var i = 0; i < playerLen; i++) { boards += '<div class="row">' + '<!-- first cell is the name -->' + '<div class="name">' + players[i].username + '</div>'; // need to loop this with the users scores for (var k = 0; k < scoresLen; k++) { boards += '<div class="game ' + frameStyle(k) + ' ">' + displayScore(players[i].score[k]) + '</div>'; } // don't forget the total boards += '<div class="player-total">' + getTotals(players[i].score) + '</div>'; boards += '</div>'; } boards += '</div>'; boards += '<div>Current Frame: ' + currentFrame + '</div>'; boards += '<button type="button" onclick="startGame()">Start Game</button>'; // fill the holder.... document.getElementById('boardHolder').innerHTML = boards; } function startGame() { if (currentFrame >= 10) { announceWinner(); } else { currentFrame++; // do the throws for Each Player! players.forEach(function(a, b) { a.score[currentFrame - 1] = playFrame(); }); // update the grid createGrid(); // recurrrrrrsion.... //startGame(); } } function throwBall(pinsStanding) { // i know it isn't a ball return Math.floor(Math.random() * (pinsStanding + 1)); } function playFrame() { // here we just create the array and determine if we have a strike or a spare! var pinsStanding = 10, frameScore = [], frameThrows = 2, pinsDown; for(var i = 0; i < frameThrows; i++) { pinsDown = throwBall(pinsStanding); pinsStanding = pinsStanding - pinsDown; // if it is the pinsStanding = 0 and it is the first throw - a strike! if(pinsStanding === 0 && i === 1) { pinsStanding = 10; frameThrows = 3; } // what if it is a spare? frameScore.push(pinsDown); } return frameScore; } function announceWinner() { } // kick it all off!!! window.onload = function() { // lets get some users.... players = prompt('Please enter the NUMBER of players?', 2); // check we have a number... if (isNumber(players)) { players = setUpPlayers(players); createGrid(); } }; 
 body { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } /* classes */ .score-board { border: 1px solid #000; } .row { display: block; border-bottom: 1px solid #000; } .row:last-child { border-bottom: none; } .row > div { display: inline-block; padding: 5px; } .game { border-right: 1px solid #000; } .name { background-color: #f5f5f5; border-right: 1px solid #000; } .player-total { text-align: right; background-color: #d5eabb; } .played-frame { background-color: #aee1e8; } .current-frame { background-color: #ffc0cb; } 
 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>JS Bin</title> </head> <body> <h1>Let's go bowling!</h1> <div id="boardHolder"> </div> </body> </html> 

这是垃圾桶! https://jsbin.com/qilizo/edit?html,js,output

你需要在for循环中调用Array(10).fill([-1, -1]) ,否则所有对象将共享相同的得分数组:

function setUpPlayers(num) {

    var tempArray = [],
        tempName = 'Player '; 

    for (var i = 0; i < num; i++) {
        tempArray.push({
            username: tempName + (i + 1),
            score: Array(10).fill([-1, -1]),// set default to -1 as a rubbish player may hit no pins!
            strikeCount: 0,
            spareCount: 0
        }); // the way I have named the tempName is technically an antipattern!
    }

    return tempArray;
}

https://jsbin.com/yeyupiteyu/1/edit?html,js,output

在JavaScript中,对象通过引用传递,并且由于数组是一个对象,如果在循环外声明emptyScores然后将其分配给数组的每个元素,则所有元素将共享相同的score数组。

你为每个元素创建了新的emptyScores数组,所以你必须在循环中声明它:

var tempArray = [],
    tempName = 'Player ';

for (var i = 0; i < num; i++) {
    var emptyScores = Array(10).fill([-1, -1]);
    tempArray.push({
        username: tempName + (i + 1),
        score: emptyScores,
        strikeCount: 0,
        spareCount: 0
    });
}

暂无
暂无

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

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