wake-up-neo.com

Was macht "! -" in JavaScript?

Ich habe diesen Code (entnommen aus diese Frage ):

var walk = function(dir, done) {
    var results = [];

    fs.readdir(dir, function(err, list) {
        if (err)
            return done(err);

        var pending = list.length;

        if (!pending) 
            return done(null, results);

        list.forEach(function(file) {
            file = path.resolve(dir, file);
            fs.stat(file, function(err, stat) {
                if (stat && stat.isDirectory()) {
                    walk(file, function(err, res) {
                        results = results.concat(res);

                        if (!--pending)
                            done(null, results);
                    });
                } else {
                    results.Push(file);

                    if (!--pending) 
                        done(null, results);
                }
            });
        });
    });
};

Ich versuche, dem zu folgen, und ich glaube, ich verstehe alles, bis auf das Ende, an dem !--pending steht. Was macht dieser Befehl in diesem Zusammenhang?

Edit: Ich freue mich über alle weiteren Kommentare, aber die Frage wurde schon oft beantwortet. Danke trotzdem!

376
Kieran E

! invertiert einen Wert und liefert den entgegengesetzten Booleschen Wert:

!true == false
!false == true
!1 == false
!0 == true

--[value] subtrahiert eins (1) von einer Zahl und gibt dann diese Zahl zurück, mit der gearbeitet werden soll:

var a = 1, b = 2;
--a == 0
--b == 1

Also subtrahiert !--pending eins vom anstehenden Wert und gibt dann das Gegenteil seines wahrheitsgemäßen/falschen Werts zurück (unabhängig davon, ob es 0 ist oder nicht).

pending = 2; !--pending == false 
pending = 1; !--pending == true
pending = 0; !--pending == false

Und ja, folgen Sie dem ProTip. Dies mag in anderen Programmiersprachen eine gebräuchliche Redewendung sein, aber für die meisten deklarativen JavaScript-Programme sieht dies ziemlich fremd aus.

536
TbWill4321

Das ist kein spezieller Operator, es sind 2 Standardoperatoren nacheinander:

  1. Ein Präfix-Dekrement (--)
  2. Ein logisches Nein (!)

Dies führt dazu, dass pending dekrementiert und dann getestet wird, um festzustellen, ob es Null ist.

149
Amit

Eine Reihe von Antworten beschreibt was diesen Befehl, aber nicht warum es wird hier so gemacht.

Ich komme aus der C-Welt und lese !--pending als "Countdown pending und überprüfe, ob es Null ist", ohne wirklich darüber nachzudenken. Es ist eine Redewendung, die Programmierer in ähnlichen Sprachen meines Erachtens kennen sollten.

Die Funktion verwendet readdir, um eine Liste der Dateien und Unterverzeichnisse abzurufen, die ich gemeinsam als "Einträge" bezeichne.

Die Variable pending verfolgt, wie viele davon noch zu verarbeiten sind. Es beginnt mit der Länge der Liste und zählt abwärts gegen Null, wenn jeder Eintrag verarbeitet wird.

Diese Einträge werden möglicherweise nicht in der richtigen Reihenfolge verarbeitet, weshalb ein Countdown erforderlich ist, anstatt nur eine einfache Schleife zu verwenden. Wenn alle die Einträge verarbeitet wurden, wird der Rückruf done aufgerufen, um den ursprünglichen Anrufer über diese Tatsache zu informieren.

Beim ersten Aufruf von done wird return vorangestellt, nicht weil ein Wert zurückgegeben werden soll, sondern nur, um die Ausführung der Funktion an diesem Punkt anzuhalten. Es wäre sauberer Code gewesen, das return zu löschen und die Alternative in ein else zu setzen.

108
Stig Hemmer

Es ist eine Kurzschrift.

! ist "nicht".

-- dekrementiert einen Wert.

So prüft !--, ob der Wert, der durch Negieren des Ergebnisses des Dekrementierens eines Werts erhalten wird, falsch ist.

Versuche dies:

var x = 2;
console.log(!--x);
console.log(!--x);

Der erste ist falsch, da der Wert von x 1 ist, der zweite ist wahr, da der Wert von x 0 ist.

Randnotiz: !x-- würde zuerst prüfen, ob x falsch ist, und es dann dekrementieren.

35
Lucas

! ist der JavaScript-Operator NOT

-- ist ein Vordekrementierungsoperator. Damit,

x = 1;
if (!x) // false
if (!--x) // becomes 0 and then uses the NOT operator,
          // which makes the condition to be true
31
Sterling Archer
if(!--pending)

meint

if(0 == --pending)

meint

pending = pending - 1;
if(0 == pending)
23
james turner

Es ist der Nicht-Operator, gefolgt vom Vor-Dekrementierer an Ort und Stelle.

Also, wenn pending eine ganze Zahl mit einem Wert von 1 war:

val = 1;
--val; // val is 0 here
!val // evaluates to true
13
Brendan Abel

Erläuterung

Dies sind 2 Operatoren, ein ! und ein --

!--x 

Das verschlechtert also x um 1 und prüft, ob es sich um einen Booleschen Wert handelt.

Wenn Sie es lesbarer machen möchten, können Sie:

var x = 1
x = x - 1   
if(!x){ //=> true
    console.log("I understand `!--` now!") 
}
x //=> 0

Versuch es:

/* This is an example of the above, you can read this, but it is not needed for !-- */function interactive(a){$("span.code").keydown(function(e){if(13==(e.keyCode||e.which)){var t=$(this);t.clone().html("code").insertAfter(t.next().next()).show().focus().after(template.clone().removeClass("result-template").show()).next().after("<br>"),interactive(),e.preventDefault()}}).keyup(function(e){13!=(e.keyCode||e.which)&&run()})}var template=$(".result-template").hide(),code=$("span.code");code.attr("contenteditable","true").each(function(e,t){template.clone().removeClass("result-template").insertAfter(t)}),interactive(),$.fn.reduce=[].reduce;function run(){var b=!1,context={};$("span.code").each(function(){var a=$(this),res=a.next().show().removeClass("error");try{with(context)res.html(b?"":"  //=> "+eval(a.text()))}catch(e){b=e,res.html("  Error: "+b.message).addClass("error")}})};run();
/* This is an example of the above, you can read this, but it is not needed for !-- */span.result.error{display:block;color:red}.code{min-width:10px}body{font-family:Helvetica,sans-serif}
<!-- This is an example of the above, you can read this, but it is not needed for `!--` --><span class="result result-template"> //=> unknown </span> <h2>Edit This Code:</h2><code><span class="code">x = 1</span><br><span class="code">!--x</span><br><span class="code"> x </span><br></code> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Fiddle (Code ausprobieren)

12
Ben Aubin

Es verringert pending lediglich um eins und erhält sein logisches Komplement (Negation). Das logische Komplement einer von 0 verschiedenen Zahl ist false, für 0 ist es true.

11
MinusFour

Das eigentliche Problem hierbei ist das Fehlen eines Leerzeichens zwischen den beiden Operatoren ! und --.

Ich weiß nicht, warum die Leute es in den Kopf bekommen, dass Sie niemals ein Leerzeichen nach dem Operator ! verwenden können. Ich denke, es kommt von der rigiden Anwendung mechanischer Whitespace-Regeln anstelle von gesundem Menschenverstand. Fast jeder Codierungsstandard, den ich gesehen habe, verbietet Leerzeichen nach allen unären Operatoren, aber warum?

Wenn es jemals einen Fall gab, in dem Sie diesen Raum eindeutig benötigen , dann ist dies einer.

Betrachten Sie dieses Stück Code:

if (!--pending)
    done(null, results);

! und -- sind nicht nur zusammengeknallt, du hast auch diesen ( gegen sie geworfen. Kein Wunder, dass es schwer ist zu sagen, was mit was verbunden ist.

Ein bisschen mehr Leerzeichen machen den Code viel klarer:

if( ! --pending )
    done( null, results );

Sicher, wenn Sie an mechanische Regeln wie "kein Leerzeichen innerhalb von Parens" und "kein Leerzeichen nach einem unären Operator" gewöhnt sind, kann dies ein bisschen fremd erscheinen.

Schauen Sie sich aber an, wie das zusätzliche Leerzeichen die verschiedenen Teile der if -Anweisung und des Ausdrucks gruppiert und trennt: Sie haben --pending, daher ist -- eindeutig ein eigener Operator und eng verknüpft zu pending. (Es dekrementiert pending und gibt das dekrementierte Ergebnis zurück.) Dann haben Sie den ! davon getrennt, sodass es sich offensichtlich um einen eindeutigen Operator handelt, der das Ergebnis negiert. Schließlich haben Sie if( und ), die den gesamten Ausdruck umgeben, um ihn zu einer if -Anweisung zu machen.

Und ja, ich habe das Leerzeichen zwischen if und ( entfernt, weil das ( zum if gehört . Dieser ( ist nicht Teil einer (!-- -Syntax, wie es im Original zu sein scheint, dem (, wenn er Teil der Syntax der if -Anweisung selbst ist.

Das Leerzeichen dient hier dazu, die - Bedeutung zu kommunizieren, anstatt einem mechanischen Kodierungsstandard zu folgen.

8
Michael Geary