Ich habe eine "Aufzählung" wie folgt deklariert:

var PlaceType = {
        PASSABLE_TERRAIN: 1,
        IMPASSABLE_TERRAIN: 0,
        SOMEWHAT_PASSABLE_TERRAIN: 2,
        PATH: 3
    };

Und eine so deklarierte Funktion:

setPlaceType(placeType) {
        this.clear = false;
        this.placeType = placeType;

        alert("before switch "+(PlaceType.SOMEWHAT_PASSABLE_TERRAIN==this.placeType));
        switch(this.placeType) {
        case PlaceType.PASSABLE_TERRAIN: {
            alert("Case PASSABLE");
            break;
        }
        case PlaceType.IMPASSABLE_TERRAIN: {
            alert("Case IMPASSABLE");
            break;
        }
        case PlaceType.SOMEWHAT_PASSABLE_TERRAIN: {
            alert("Case SOMEWHAT_PASSABLE");
            break;
        }
        case PlaceType.PATH: {
            alert("Case PATH");
            break;
        }
        default: {
            alert("case default");
        }
        }
    }

Wenn ich es so nenne:

setPlaceType(1);

Ich erhalte die folgenden Warnungen: "before switch true", "case default"

Wenn ich es so nenne:

setPlaceType(2);

Ich erhalte die folgenden Warnungen: "before switch false", "case default"

Mit anderen Worten, die Funktion wird mit dem richtigen Argument aufgerufen, das beim Ausführen (wie es mir scheint) den gleichen Vergleich wie der Schalter durchführt, aber über "==" erhalte ich das richtige Verhalten, aber der Schalter stimmt nie mit den Werten überein auf den entsprechenden Fall. Weiß jemand warum?

7
Shivan Dragon 8 Okt. 2012 im 18:18

5 Antworten

Beste Antwort

Der Vergleichsoperator wandelt beide Operanden in Zeichenfolgen um, wenn einer der Operatoren eine Zeichenfolge ist. Wenn Sie eine Zeichenfolge übergeben, vergleichen Sie string == number, wodurch die Zahl in eine Zeichenfolge umgewandelt wird. Wenn Sie die Zeichenfolge '2' übergeben, ist dies der Fall.

Der Switch-Case-Vergleich verwendet den Identitätsoperator === und schlägt fehl, wenn die Operanden nicht vom gleichen Typ sind.

Kurz gesagt, stellen Sie sicher, dass Sie immer eine Nummer übergeben, wenn Ihre Fälle mit Zahlen verglichen werden. Sie können dies wie folgt überprüfen:

setPlaceType(placeType) {
    if (typeof placeType !== 'number') {
        throw new Error('You must pass a number to setPlaceType!');
    }
    ...
}

Außerdem sollten Sie Ihre Funktion folgendermaßen aufrufen:

setPlaceType(PlaceType.PASSABLE_TERRAIN);

Ansonsten macht es keinen Sinn, das Objekt "Aufzählung" (ich benutze diesen Begriff locker) zu verwenden.

6
Eliran Malka 8 Okt. 2012 im 14:59

Der Übereinstimmungsfall wird mithilfe von dem Identitätsoperator === und nicht dem Gleichheitsoperator == ermittelt. Die Ausdrücke müssen ohne Typkonvertierung übereinstimmen. Es würde fehlschlagen, wenn Sie eine Zeichenfolge und keine Ganzzahl übergeben.

setPlaceType(1);  //"Case PASSABLE"
setPlaceType("1");  //"case default"

Beispiel für die Ausführung Ihres Codes mit den obigen Zeilen: jsFiddle

Wenn Sie also sagen, dass dies fehlschlägt, vergleichen Sie wahrscheinlich eine Zeichenfolge mit einer Zahl. Verwenden Sie parseInt.

this.placeType = parseint(placeType,10);
1
Community 23 Mai 2017 im 10:27

Verweis darauf => Groß- / Kleinschreibung für Zeichenfolgen in Javascript funktioniert nicht wie erwartet

Switch führt ein === aus, während if ein == ausführt.

Ich hoffe das hilft! Einen schönen Tag noch

1
Community 23 Mai 2017 im 12:34

Wenn Sie den Vergleich mit == durchführen, verwendet js type-coercion, um die beiden Operanden in einen Zwischentyp umzuwandeln, in diesem Fall eine Zeichenfolge, und sie somit erfolgreich zu vergleichen.

Damit der Effekt mit Ihrer switch-Anweisung funktioniert, müssen Sie ihn als solchen umwandeln

this.placeType = parseint(placeType);

Was Sie hier auch lernen müssen, ist, dass es nicht wirklich eine ideale Praxis ist, 2 Werte in Javascript mit dem Operator == zu vergleichen, sondern stattdessen den Operator ===, der auch prüft, ob die Typen gleich sind . Also in deinem Fall,

alert("before switch "+(PlaceType.SOMEWHAT_PASSABLE_TERRAIN==this.placeType));

Wäre fehlgeschlagen, wenn Sie beim Vergleich von int und string === verwendet hätten

Arbeitsdemo hier: http://jsfiddle.net/pratik136/ATx8c/

0
bPratik 8 Okt. 2012 im 14:38

Eine andere Möglichkeit, enum für den Schalterfall zu verwenden:

   const PlaceType = Object.freeze({
            PASSABLE_TERRAIN: 1,
            IMPASSABLE_TERRAIN: 0,
            SOMEWHAT_PASSABLE_TERRAIN: 2,
            PATH: 3
        });

   function setPlaceType(placeType){
      return({
              0:"Case IMPASSABLE_TERRAIN",
              1:"Case PASSABLE_TERRAIN",
              2:"Case SOMEWHAT_PASSABLE_TERRAIN",
              3:"PATH"      
              }[placeType]);
     }
0
Wei 13 Sept. 2019 im 17:51