Variable zuweisen in ob Bedingungsanweisung, gute Praxis oder nicht? [geschlossen]


111

Ich bin vor einem Jahr von klassischen OO-Sprachen wie Java zu JavaScript gewechselt. Der folgende Code wird in Java definitiv nicht empfohlen (oder sogar nicht korrekt):

if(dayNumber = getClickedDayNumber(dayInfo))
{
    alert("day number found : " + dayNumber);
}
function getClickedDayNumber(dayInfo)
{
    dayNumber = dayInfo.indexOf("fc-day");
    if(dayNumber != -1) //substring found
    {
        //normally any calendar month consists of "40" days, so this will definitely pick up its day number.
        return parseInt(dayInfo.substring(dayNumber+6, dayNumber+8));
    }
    else return false;
}

Grundsätzlich habe ich gerade herausgefunden, dass ich einem Wert in einer if-Bedingungsanweisung eine Variable zuweisen und den zugewiesenen Wert sofort überprüfen kann, als ob er boolesch wäre.

Für eine sicherere Wette trenne ich das normalerweise in zwei Codezeilen, weise es zuerst zu und überprüfe dann die Variable. Jetzt, wo ich das gefunden habe, frage ich mich nur, ob es in den Augen erfahrener JavaScript-Entwickler eine gute Praxis ist oder nicht.


"The following code is definitely not recommended (or event not correct) in Java..."Ist es überhaupt richtig in JavaScript? Denn soweit ich sehen kann, geben Sie eine Ganzzahl ( return parseInt(...)) zurück, wenn sie dayNumber != -1wahr ist, aber eine Boolesche Zahl , wenn sie falsch ist.
Daniel Kvist

Antworten:


117

Ich würde es nicht empfehlen. Das Problem ist, dass es wie ein häufiger Fehler aussieht, bei dem Sie versuchen, Werte zu vergleichen, aber einen einzelnen =anstelle von ==oder verwenden ===. Zum Beispiel, wenn Sie dies sehen:

if (value = someFunction()) {
    ...
}

Sie wissen nicht, ob sie das wollten oder ob sie das schreiben wollten:

if (value == someFunction()) {
    ...
}

Wenn Sie die Aufgabe wirklich an Ort und Stelle ausführen möchten, würde ich auch einen expliziten Vergleich empfehlen:

if ((value = someFunction()) === <whatever truthy value you are expecting>) {
    ...
}

1
@ Matthew Crumley: Dies beantwortet meine Frage auf klare Weise. Ich überprüfe nicht durch Zuweisen, sondern ob der Wert nach der Zuweisung ausgewertet wird. Ist dieses Verständnis richtig?
Michael Mao

1
@ Michael: Ja, das ist richtig. Das Hinzufügen des Vergleichs macht Ihre Absichten im Grunde nur klarer.
Matthew Crumley

4
Das letzte Beispiel funktioniert jedoch nicht, wenn Sie auf Fehler / Erfolg einer Funktion testen, die einen Booleschen Wert zurückgibt. Mit anderen Worten, während es if (resultArr = myNeedle.exec(myHaystack)) {...}funktioniert, if ((resultArr = myNeedle.exec(myHaystack)) === true) {...}nicht, weil die Zuordnung zu resultArr immer wahr ist, auch wenn das Funktionsergebnis nicht wahr ist. Wenn jemand dieses Konstrukt verwendet, denken Sie daran, zuerst die Ergebnisvariable zu deklarieren. 'var' ist in der if-Bedingungsanweisung nicht zulässig.
Ville

3
Sie können verwendet werden if (!!(value = someFunction())), aber wie Sie gesagt haben , das Problem ist , dass Sie nicht verwenden können , varinnerhalb ifso dass Sie entweder eine globale am Ende zu schaffen, oder nichts erreichen , wie Sie zu erklären haben valueohnehin in einer separaten Zeile. Schade, diese Konstruktion in C ++ hat mir sehr gut gefallen.
Riv

1
@ Riv, du hast recht; Falls die Funktion einen Booleschen Wert zurückgibt - wie ich in meinem obigen Kommentar gesagt habe -, funktioniert die Bedingung wie erwartet. Wenn die Funktion jedoch einen Booleschen Wert zurückgibt (wie in meinem Beispiel), ist das gesamte Konstrukt irgendwie unsinnig. Offensichtlich war meine Denkweise - nach dem Beispiel zu urteilen -, dass die Funktion ein Array zurückgeben würde. Ein schneller Test zeigt an, dass die Bedingung truenur dann ausgewertet wird, wenn die Funktion zurückgegeben truewird, in allen anderen Fällen (einschließlich der Rückgabe eines Arrays, einer Zeichenfolge, einer Zahl oder einer Null) false.
Ville

27

Ich sehe keinen Beweis dafür, dass es keine gute Praxis ist. Ja, es mag wie ein Fehler aussehen, aber das kann leicht durch vernünftige Kommentare behoben werden. Nimm zum Beispiel:

if (x = processorIntensiveFunction()) { // declaration inside if intended
    alert(x);
}

Warum sollte diese Funktion ein zweites Mal ausgeführt werden dürfen mit:

alert(processorIntensiveFunction());

Weil die erste Version schlecht aussieht? Ich kann dieser Logik nicht zustimmen.


32
Einen alten Kommentar nicht ausgraben, aber ich stimme Ihren Argumenten nicht zu. Lesbarer Code sollte sich ohne Kommentar erklären - das Hinzufügen eines Kommentars zu verwirrendem Code ist keine Abhilfe. Was den zweiten Teil betrifft, der besagt, dass die Alternative darin besteht, die Funktion erneut aufzurufen, glaube ich nicht, dass jemand beabsichtigt, dies zu tun. Stattdessen würden Sie tunx = processorItensiveFunction(); if(x) { alert(x); }
Maksim

8
@maksim: Ich mag lesbaren Code, aber das bedeutet nicht unbedingt, dass der Code heruntergekommen oder zu ausführlich sein sollte. Das Verteilen von Dingen über mehrere Zeilen und das Jonglieren von Werten zwischen Variablen kann tatsächlich zu schlechterem Code führen. Eingefügter Code kann in einer schwach typisierten / flexiblen Sprache wie JS unvorhergesehene Nebenwirkungen haben. Die Zuweisung in einer bedingten Anweisung ist in Javascript gültig, da Sie nur fragen: "Wenn die Zuweisung gültig ist, tun Sie etwas, das möglicherweise das Ergebnis der Zuweisung enthält". In der Tat ist die Zuweisung vor der Bedingung auch gültig, nicht zu ausführlich und wird häufiger verwendet.
Okdewit

1
@maksim warum denkst du if ( ! x = anyFunction() )ist nicht lesbar? Es braucht überhaupt keine Kommentare.
JDrake

Wenn Sie OPC reparieren, mit anderen Entwicklern unterschiedlicher Fähigkeiten arbeiten (mit anderen Worten, Sie sind ein Profi), werden Sie es hassen, dass dies überhaupt möglich ist.
Davidjmcclelland

2
@maksim - auch Ihre Lösung wäre in einer if-elseSituation sehr unpraktisch . Bedenken Sie: if (condition) {...} else if (x = processorIntensiveFunction()) {alert(x)} Ihr Prior x = processorIntensiveFunction();wäre eine vergebliche Anstrengung, sollte die Initiale conditionwahr sein.
Adrian Bartholomew

16

Ich habe es oft gemacht. Um die JavaScript-Warnung zu umgehen, füge ich zwei Parens hinzu:

if ((result = get_something())) { }

Sie sollten es vermeiden, wenn Sie es wirklich verwenden möchten, schreiben Sie einen Kommentar darüber und sagen Sie, was Sie tun.


1
@ SHiNKiROU: Wie kann ich Javascript-Warnungen sehen? Gibt es einen Javascript-Compiler? oder wird der Dolmetscher eine Art Warnung generieren? Ich verwende die Firefox-Konsole wie beim Debuggen von Javascript die ganze Zeit, sehe aber nie ähnliche Ausgaben. Entschuldigung für meine begrenzte Erfahrung.
Michael Mao

5
@Michael: JSLint ( jslint.com ) ist ein beliebtes Programm / eine beliebte Bibliothek, die JavaScript-Programme auf mögliche Fehler oder fehlerhaften Code überprüft.
Matthew Crumley

Verwenden Sie Mozilla Firefox mit Firebug und / oder Web Developer-Erweiterung, um Warnungen zu überprüfen.
Ming-Tang

Ich habe es nur mit versucht, if ((a = [1, 2]).length > 0) { console.log(a); }wo anoch nirgends initialisiert wurde, und es hat tatsächlich funktioniert (schön! Erleichtert die Verwendung von Regex erheblich). Ist das richtig, dass ich hier nichts brauche var|const|let? Weißt du zufällig, wo ich mehr über diesen Trick lesen kann ?
t3chb0t

4

Sie können dies auch in Java tun. Und nein, es ist keine gute Praxis. :) :)

(Und verwenden Sie das ===in Javascript für typisierte Gleichheit. Lesen Sie Crockfords The Good Parts-Buch über JS.)


@quixoto: Könnte ich diesen Trick in Java machen? Ich frage mich ... Ich habe kein JDK von Hand atm, daher kann ich keinen Beispielcode in Java erhalten. Aus meinem schlechten Speicher wird Java nur dann einen Laufzeitfehler anzeigen, wenn der Rückgabewert etwas auswertet, das nicht boolesch ist, wie in einer bedingten Anweisung, oder?
Michael Mao

1
Ah, ja, in Java wird typgeprüft, um ein boolescher Typ zu sein. Aber Sie können tunif (foo = getSomeBoolValue()) { }
Ben Zotto

ja das ist richtig. Eine boolesche Variable zum Testen, ob etwas erfolgreich war, und eine andere Variable zum Speichern des zurückgegebenen Werts. So macht Java seinen Job, ich bin damit zu vertraut, daher fühle ich mich seltsam zu sehen, dass Javascript zwei Dinge in einer einzigen Zeile erledigen kann :)
Michael Mao

@ BenZotto es ist keine gute Praxis warum? "Um einen versehentlichen Missbrauch einer Variablen zu vermeiden, ist es normalerweise eine gute Idee, die Variable in den kleinstmöglichen Bereich einzuführen. Insbesondere ist es normalerweise am besten, die Definition einer Variablen zu verzögern, bis man ihr einen Anfangswert geben kann ... Eine der elegantesten Anwendungen dieser beiden Prinzipien besteht darin, eine Variable in einer Bedingung zu deklarieren. " - Stroustrup, "Die C ++ - Programmiersprache".
JDrake

1
Hallo, ich bin als Javascript-Benutzer von node.j hierher gekommen. Warum gibt es in einem Fall keine gute Praxis, mit der ich Schmerzen hatte: if (myvar = 'nur ein Test') Erstellt eine GLOBAL-Variable von node.js myvar ( nodejs.org/docs/latest-v12.x/api/globals.html) #globals_global ). Wenn Sie also wie ich sind und diese Variable bei der Bearbeitung von Serveranforderungen verwendet haben (und nach einigen Sekunden darauf zurückkommen, wenn andere Anforderungen eingegangen sind), können Sie überrascht sein, welche Ergebnisse Sie erhalten. Die Empfehlung lautet also: Beachten Sie, dass dieses Muster eine globale Variable in node.js erstellt.
pein-consulting.de

4

Es gibt einen Fall, in dem Sie dies tun, mit while-loops.
Wenn Sie Dateien lesen, gehen Sie normalerweise folgendermaßen vor:

void readFile(String pathToFile) {
    // Create a FileInputStream object
    FileInputStream fileIn = null;
    try {
        // Create the FileInputStream
        fileIn = new FileInputStream(pathToFile);
        // Create a variable to store the current line's text in
        String currentLine;
        // While the file has lines left, read the next line,
        // store it in the variable and do whatever is in the loop
        while((currentLine = in.readLine()) != null) {
            // Print out the current line in the console
            // (you can do whatever you want with the line. this is just an example)
            System.out.println(currentLine);
        }
    } catch(IOException e) {
        // Handle exception
    } finally {
        try {
            // Close the FileInputStream
            fileIn.close();
        } catch(IOException e) {
            // Handle exception
        }
    }
}

Schauen Sie sich die whileSchleife in Zeile 9 an. Dort wird eine neue Zeile gelesen und in einer Variablen gespeichert, und dann wird der Inhalt der Schleife ausgeführt. Ich weiß, dass dies keine ifAussage ist, aber ich denke, eine while-Schleife kann auch in Ihre Frage aufgenommen werden.

Der Grund dafür ist, dass bei Verwendung von a FileInputStreambei jedem Aufruf FileInputStream.readLine()die nächste Zeile in der Datei gelesen wird. Wenn Sie sie also aus der Schleife aufgerufen hätten, fileIn.readLine() != nullohne die Variable zuzuweisen, anstatt sie aufzurufen (currentLine = fileIn.readLine()) != null, und dann von Auch innerhalb der Schleife würden Sie nur jede zweite Zeile erhalten.

Hoffe du verstehst und viel Glück!


3

Sie können Zuweisungen auch innerhalb von if-Anweisungen in Java ausführen. Ein gutes Beispiel wäre, etwas einzulesen und aufzuschreiben:

http://www.exampledepot.com/egs/java.io/CopyFile.html?l=new

Der Code:

// Copies src file to dst file.
// If the dst file does not exist, it is created
void copy(File src, File dst) throws IOException 
{
    InputStream in = new FileInputStream(src);
    OutputStream out = new FileOutputStream(dst);

    // Transfer bytes from in to out
    byte[] buf = new byte[1024];
    int len;
    while ((len = in.read(buf)) > 0) {
        out.write(buf, 0, len);
    }
    in.close();
    out.close();
}

@ Nitrodist: Danke für dieses Beispiel. Ich bin wirklich kein Profi in Java oder Javascript ... Es ist gut zu wissen, dass dieser Ansatz auch in Java machbar ist :)
Michael Mao

Ich verstehe den Sinn davon nicht. Sie können dies in Java, PHP und vielen anderen Sprachen tun. Die Frage betraf Javascript.
pmrotule

Nein, das ist nicht unbedingt so. Sie müssen die Frage sorgfältig durchlesen.
Nitrodist

3

Wenn Sie sich auf Martin Fowlers Buch Refactoring beziehen, das das Design des vorhandenen Codes verbessert ! Dann gibt es mehrere Fälle, in denen es eine gute Praxis wäre, z. lange komplexe Bedingungen, um einen Funktions- oder Methodenaufruf zu verwenden, um Ihren Fall zu bestätigen:

"Motivation

Einer der häufigsten Komplexitätsbereiche in einem Programm liegt in der komplexen bedingten Logik. Wenn Sie Code schreiben, um Bedingungen zu testen und abhängig von verschiedenen Bedingungen verschiedene Dinge zu tun, erhalten Sie schnell eine ziemlich lange Methode. Die Länge einer Methode ist an sich ein Faktor, der das Lesen erschwert, aber die Bedingungen erhöhen die Schwierigkeit. Das Problem liegt normalerweise in der Tatsache, dass der Code sowohl in den Bedingungsprüfungen als auch in den Aktionen Ihnen sagt, was passiert, aber leicht verdecken kann, warum es passiert.

Wie bei jedem großen Codeblock können Sie Ihre Absicht klarer machen, indem Sie sie zerlegen und Codestücke durch einen Methodenaufruf ersetzen, der nach der Absicht dieses Codeblocks benannt ist. > Mit Bedingungen können Sie weitere Vorteile erhalten, indem Sie dies für den bedingten Teil und jede der Alternativen tun. Auf diese Weise markieren Sie die Bedingung und machen deutlich, worauf Sie verzweigen. Sie markieren auch den Grund für die Verzweigung. "

Und ja, seine Antwort gilt auch für Java-Implementierungen. In den Beispielen wird die bedingte Funktion jedoch keiner Variablen zugewiesen.


1

Es ist keine gute Praxis. Sie werden bald verwirrt sein. Es sieht einem häufigen Fehler ähnlich: Missbrauch der Operatoren "=" und "==".

Sie sollten es in 2 Codezeilen aufteilen. Dies hilft nicht nur, den Code klarer zu gestalten, sondern lässt sich auch in Zukunft leicht umgestalten. Stellen Sie sich vor, Sie ändern die IF-Bedingung? Sie können die Zeile versehentlich entfernen und Ihre Variable erhält nicht mehr den ihr zugewiesenen Wert.


@thethanghn: genau davor habe ich angst. Wenn ich älter und faul werde, möchte ich einfach nicht mehr in den Code eingeben, wenn weniger Tastenanschläge ausreichen :)
Michael Mao

1
Nein, ich werde nicht verwirrt und mache es die ganze Zeit. Das hat Vorteile.
JDrake

Es kommt aber wirklich darauf an, nicht wahr? Wenn Sie einen C-Hintergrund haben (und andere auf C basierende Sprachen), ist das Konstrukt sehr vertraut und die Alternativen sind sehr umständlich. IMO, es ist etwas, das einmal gelernt wird und dann weißt du es. Es ist nicht etwas, über das Sie mehr als einmal stolpern werden.
Max Waterman

0

Ich würde dies eher als C-Stil der alten Schule betrachten. Es ist keine wirklich gute Praxis in JavaScript, daher sollten Sie es vermeiden.


8
Ich halte es auch in C nicht für eine gute Praxis.
Matthew Crumley

1
Ich halte es für eine gute Praxis in vielen Sprachen.
JDrake

Nur "nicht gute Praxis" zu sagen, reicht nicht aus, imo. Es geht wirklich nur um Bildung - es wird einmal gelernt und das war's.
Max Waterman

0

Sie könnten so etwas tun:

if (value = /* sic */ some_function()){
  use_value(value)
}

0

Ich bin aus Golang hierher gekommen, wo es üblich ist, so etwas zu sehen

if (err := doSomething(); err != nil) {
    return nil, err
}

In dem errist nur auf diesen ifBlock beschränkt. Als solches mache ich Folgendes in es6, was ziemlich hässlich erscheint, aber meine ziemlich strengen Eslint-Regeln nicht durcheinander bringt und dasselbe erreicht.

{
  const err = doSomething()
  if (err != null) {
    return (null, err)
  }
}

Die zusätzlichen Klammern definieren einen neuen, "lexikalischen Bereich"? Das heißt, ich kann verwenden constund errsteht dem äußeren Block nicht zur Verfügung.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.