wake-up-neo.com

Ausdruck in der switch case-Anweisung

Ich versuche, eine switch-Anweisung zu erstellen, kann aber anscheinend keinen Ausdruck verwenden, der ausgewertet wird (und nicht eine Zeichenfolge/ganze Zahl). Ich kann dies leicht mit if-Anweisungen machen, aber der Fall sollte hoffentlich schneller sein.

Ich versuche folgendes

function reward(amount) {
    var $reward = $("#reward");
    switch (amount) {
        case (amount >= 7500 && amount < 10000):
            $reward.text("Play Station 3");
            break;
        case (amount >= 10000 && amount < 15000):
            $reward.text("XBOX 360");
            break;
        case (amount >= 15000):
            $reward.text("iMac");
            break;
        default:
            $reward.text("No reward");
            break;
    }
}

Fehlt mir etwas offensichtliches oder ist das nicht möglich? Google war in diesem Fall nicht freundlich.

Jede Hilfe/Hinweise geschätzt

M

27
Marko

Du könntest es immer tun

switch (true) {
  case (amount >= 7500 && amount < 10000):
    //code
    break;
  case (amount >= 10000 && amount < 15000):
    //code
    break;

  //etc...

Es funktioniert, weil true eine Konstante ist. Daher wird der Code unter der ersten case-Anweisung mit einem Ausdruck, der den Wert true ergibt, ausgeführt.

Es ist irgendwie "knifflig", denke ich, aber ich sehe nichts Falsches daran. Eine einfache if/else-Anweisung wäre wahrscheinlich prägnanter, und Sie müssen sich keine Sorgen um zufällige Fälle machen. Aber da ist es trotzdem.

97
MooGoo

So funktioniert ein switch-Block nicht. Die Variable case wird verwendet, um einen einzelnen Wert zu speichern, der dem Wert in der Zeile switch entspricht. if-else-Anweisungen werden Ihnen gute Dienste leisten.

Hier finden Sie einige Informationen zum switch-Block.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch

10
Daniel A. White

@ MooGoo's switch (true) gibt Ihnen einen Weird condition-Fehler in jsLint , also lassen Sie uns ein wenig kreativer werden, falls dies ein Problem ist, und, denke ich, die Lesbarkeit einer Berührung verbessern.

Wir prüfen also nicht, ob casetrue oder false ist. Wir vergleichen, ob der Wert von case gleich unserem Ausdruck switch ist. Lassen Sie uns dies nutzen, indem Sie in unsere if-Anweisung eine Abkürzung case einfügen und unseren ursprünglichen switch-Ausdruck zurückgeben, wenn die Bedingung wahr ist.

Ich füge auch eine Art reales Beispiel hinzu, bei dem Sie zwei "Standardwerte" haben möchten - einen, wenn Ihr Begriff außerhalb Ihres "wichtigen" Bereichs in der positiven Richtung liegt, und einen anderen, falls Sie im negativen Bereich sind Richtung.

Schlüsselsatz: case (x > 0 ? x : null):

"Wenn mein Ausdruck x größer als Null ist, geben Sie x zurück, damit x === x und ich den Fallzweig übernehmen."

http://jsfiddle.net/rufwork/upGH6/1/

/*global document*/
/*jslint evil:true*/
var x = 10;

switch (x) {
    case (x > 0 ? x : null):
        document.write('ha ha ha!  I fooled switch AND jsLint!  Muhahahahaha!');
        break;
    case 0:
        document.write('zero is nothing.');
        break;
    case -1:
        document.write('low');
        break;
    case -2:
        document.write('lower');
        break;
    case -3: 
        document.write('lowest I care about');
        break;
    default: // anything lower than -3.
        document.write('TOO LOW!!!! (unless you cheated and didn\'t use an int)');
}
document.write('<br>done.');
9
ruffin

Erstens funktioniert switch nicht so. Sie müssen Konstanten für jede case angeben. Diese Konstanten werden mit dem Ausdruck in Klammern verglichen (in Ihrem Fall amount). So funktioniert switch, Punkt.

Zweitens ist der Switch nicht schneller als mehrere ifs

Und drittens sollten Sie sich nicht wirklich um minimale Leistungsoptimierungen kümmern, wenn Sie mit Javascript arbeiten.

2
Fyodor Soikin

Nun, Sie können Ausdrücke in der case-Anweisung haben, weshalb Ihr Switch kein Syntaxfehler ist. Sie müssen jedoch verstehen, dass die Case Clause mit === (strenger Vergleich) verglichen wird. Wenn Sie dies verstanden haben, muss der Wert genau mit dem Ausdruckswert in Ihrer switch(expression) übereinstimmen, den Sie in js nach Ausdrücken durchsuchen können.

Funktionsaufrufe sind Ausdrücke, also versuchen wir es mit ihnen:

function xbox(amount) { return amount >= 10000 && amount < 15000 && amount; }

function reward(amount) {
  var ps3 = function(amount) { return amount >= 7500 && amount < 10000 && amount; }

  function iMac(amount) { return amount >= 15000 && amount; }

  var $reward = $("#reward");
  switch (amount) {
    case ps3(amount):
      $reward.text("Play Station 3");
      break;
    case xbox(amount):
      $reward.text("XBOX 360");
      break;
    case iMac(amount):
      $reward.text("iMac");
      break;
    default:
      $reward.text("No reward");
      break;
  }
}
reward(8200)// -> Play Station 3
reward(11000)// -> XBOX 360
reward(20000)// -> iMac

Wie Sie sehen, können Sie sowohl Funktionsausdrücke als auch Funktionsdefinitionen verwenden. Es spielt keine Rolle Nur der Ausdruck in der case-Klausel ist ein auszuwertender Ausdruck. Das ist das Gleiche wie Sie, nur Sie haben keinen Wert zurückgegeben, der dem Betrag entspricht, sondern ein wahrer oder falscher Wert. In meinem Beispiel gebe ich den genauen Betrag zurück, wenn meine Bedingung erfüllt ist.

Hier ist dein fester Code:

function reward(amount) {
    var $reward = $("#reward");
    switch (amount) {
        case (amount >= 7500 && amount < 10000 && amount):
            $reward.text("Play Station 3");
            break;
        case (amount >= 10000 && amount < 15000 && amount):
            $reward.text("XBOX 360");
            break;
        case (amount >= 15000 && amount):
            $reward.text("iMac");
            break;
        default:
            $reward.text("No reward");
            break;
    }
}

Hier ist die Spezifikation: https://tc39.github.io/ecma262/#sec-switch-statement .__ Der Link ist zu es2016, weil er einfacher zu finden ist als die alte es3-PDF von 1999. Aber es hat immer so gearbeitet, aber es ist eine wenig bekannte Tatsache.

Ich bezweifle jedoch, dass dies schneller ist als if-Anweisungen. Wenn Sie möchten, dass Ihr Lauf schnell abläuft, berühren Sie nicht das DOM.

1
dotnetCarpenter

Sie können auch eine meiner Lieblingskonstruktionen ausprobieren:

function reward(amount) {
    var $reward = $("#reward");
    $reward.text(
        (amount >= 7500 && amount < 10000) ?    "Play Station 3" :
        (amount >= 10000 && amount < 15000)?    "XBOX 360" :
        (amount >= 15000) ?                     "iMac" :
                                                "No reward"
    );
}
1
robert

Das Problem ist, dass der Schalterausdruck niemals den Fallausdrücken entsprechen kann, da der Fallausdruck als wahr oder falsch ausgewertet wird, der Schalterausdruck jedoch eine Zahl ist.

Die Lösung, bei der der switch-Ausdruck auf true gesetzt ist, funktioniert nicht, weil true eine Konstante ist, sondern weil eine Übereinstimmung mit den case-Ausdrücken tatsächlich möglich ist. 

Es ist nicht wahr, dass Sie Konstanten für jeden Fallausdruck angeben müssen. 

Weitere Informationen finden Sie unter Douglas Crockford, Javascript The Good Parts (2008), Seite 12:

Die switch-Anweisung führt eine Mehrfachverzweigung aus. Es vergleicht den Ausdruck für Gleichheit mit allen ausgewählten Fällen. Wenn eine exakte Übereinstimmung gefunden wird, werden die Anweisungen der übereinstimmenden case-Klausel ausgeführt. Eine case-Klausel enthält einen oder mehrere case-Ausdrücke. Die Case-Ausdrücke müssen keine Konstanten sein.

1
Jon Lyles

Meine 2 Cent:

Im Idealfall sollte switch (prinzipiell) zu einem einzelnen Fallzweig ausgewertet werden, wodurch eine Leistung von O(1) erzielt wird, und (anders als Fallfälle) können die Fallanweisungen beliebig neu angeordnet werden, ohne die Verzweigungsstrategie des Compilers zu ändern.

Wenn Ausdrücke verwendet werden (vorausgesetzt, die Sprache erlaubt es), dann kann sie theoretisch mehr als nur einem Zweig folgen.

Der Compiler (abgesehen von denjenigen, die intelligent sagen können, was der Entwickler versucht), wird die Verzweigungsstrategie nicht statisch optimieren können und im Idealfall seine Wirksamkeit verlieren.

Beispiel:

var x = 6, factors = [];

switch(x){

    case (x%2 == 0): factors.Push(2);
    break;

    case (x%3 == 0): factors.Push(3);
    break;
    ....
 }

{Erwarten Sie Kommentare zu schlechtem Code}

Im obigen Beispiel gibt es keine praktische Möglichkeit für den Compiler, statisch zu optimieren. Dadurch wird kein Leistungsvorteil gegenüber if else erzielt.

Der einzige Aspekt ist, dass er für den Entwickler "möglicherweise" sauberer aussieht, jedoch bei zusätzlichen Bedingungen zu Störungen führen kann.

0
GNM