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