JavaScript-Objekteigenschaft wird nicht durch neue Nummer ersetzt [Duplikat]

Oct 01 2020

Daher habe ich mich schon seit einiger Zeit mit diesem Thema befasst und kann nicht verstehen, was falsch läuft. Ich versuche das Spiel Yahtzee zu erstellen und habe eine Funktion, die zufällig die 5 Würfel generiert. Diese Funktion wird auch wiederverwendet, wenn der Benutzer erneut rollen möchte. Ich übergebe ein Array von Objekten. Jedes Objekt hat eine Zahleneigenschaft, die darstellt, was der Benutzer gerollt hat. Ich bin auf dieses Problem gestoßen, bei dem die Schleife, in der ich einen neuen Würfelsatz generieren muss, den alten nicht ersetzt. Hier ist mein Funktionscode

function roll(theRoll){
    diceSet = theRoll;

    console.log("before")
    console.log(diceSet)

    for(let i = 0; i < diceSet.length; i++){
        if(diceSet[i].isHeld == false){
            diceSet[i].number = Math.floor((Math.random() * 6) + 1);
        }
        
        document.getElementById("die" + (i + 1) + "Img").src = "img/" + diceSet[i].number + ".png";
    } 
   
    console.log("After")
    console.log(diceSet)
    return theRoll;


}

Jetzt könnte ich mich irren, aber der obige Code sollte gut funktionieren, aber mein "diceSet" hat vor und nach der Schleife die gleichen Zahlen, aber ich habe keine Ahnung, warum sich die Eigenschaften nicht ändern.

Hier ist meine Ausgabe

Jede Hilfe wäre dankbar, danke

Antworten

2 MT0 Oct 01 2020 at 07:32

Die Werte ändern sich; Es ist nur so, dass Sie die Werte in der Konsole protokollieren und die Konsole die aktuellen Werte des Arrays (zum Zeitpunkt der Anzeige) und nicht die Werte im Array zum Zeitpunkt der Protokollierung anzeigt. Wenn Sie die Änderung der Werte sehen möchten, konvertieren Sie das Array in eine Zeichenfolge, anstatt das Array zu protokollieren.

function diceToString(theRoll)
{
  return theRoll.map(roll => roll.number).join(",");
}

function roll(theRoll){
    console.log("before")
    console.log(theRoll)
    console.log(diceToString(theRoll))

    for(let i = 0; i < theRoll.length; i++){
        if(theRoll[i].isHeld == false){
            theRoll[i].number = Math.floor((Math.random() * 6) + 1);
        }
        
        document.getElementById(`die${i + 1}Img`).src = `img/${theRoll[i].number}.png`;
    } 
   
    console.log("After")
    console.log(theRoll)
    console.log(diceToString(theRoll))
    return theRoll;
}

dice = [
  {"isHeld": false, "number": 0},
  {"isHeld": false, "number": 0},
  {"isHeld": false, "number": 0},
  {"isHeld": false, "number": 0},
  {"isHeld": false, "number": 0}
]

roll(dice);
roll(dice);
roll(dice);
roll(dice);
<img id="die1Img" src="" alt="" />
<img id="die2Img" src="" alt="" />
<img id="die3Img" src="" alt="" />
<img id="die4Img" src="" alt="" />
<img id="die5Img" src="" alt="" />

Sie können das Snippet auch ausführen und die Ausgabe (und die sich ändernden Werte) anzeigen und dann mit dem Protokoll in der Browserkonsole vergleichen, um den Unterschied festzustellen.

CommercialSuicide Oct 01 2020 at 08:16

Dies liegt daran , dass Arrays und Objekte in JS veränderbar sind , was bedeutet, dass sie als Referenz kopiert werden . Mit anderen Worten, wenn Sie ein Objekt (oder ein Array) an eine Funktion übergeben (egal, es ist Ihre oder eine Standardfunktion), übergeben Sie tatsächlich die Referenz , keine Kopie.

function addOne(obj) {
  obj.value += 1;
}

function addTwo(obj) {
  obj.value += 2;
}

const testObj = {
  value: 0
}

addOne(testObj);
addTwo(testObj);

console.log(testObj)

testObjwar noch nie neu zugewiesen worden, aber das valueist 3endlich gleich . Beim addTwoAufruf der Funktion wurde bereits ein aktualisierter Wert (gleich 1) angenommen. Das Gleiche passiert, wenn Sie veränderbare Entitäten an die console.logMethode übergeben - sie benötigt eine Referenz und Sie sehen den "tatsächlichen" Status Ihres Objekts, keinen Schnappschuss zum Zeitpunkt des Aufrufs.

Es gibt einen anderen Grund für dieses Verhalten - Zeitlücken. Sie werden in dieser Antwort kurz behandelt (siehe Block " Weitere Details "):https://stackoverflow.com/a/30363526/6053654

Der einfachste Weg, dieses Verhalten zu vermeiden, besteht darin, Ihre Daten in einen unveränderlichen Typ zu konvertieren. Strings sind dafür perfekt geeignet, und Sie können JSON.stringifyIhr Objekt einfach erstellen, bevor Sie es an der Konsole anmelden.