web-dev-qa-db-fra.com

Que fait "! -" en JavaScript?

J'ai ce morceau de code (pris de cette question ):

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);
                }
            });
        });
    });
};

J'essaie de le suivre et je pense tout comprendre sauf la fin où il est dit !--pending. Dans ce contexte, que fait cette commande?

Edit: J'apprécie tous les autres commentaires, mais la question a été répondue à plusieurs reprises. Merci quand même!

376
Kieran E

! inverse une valeur et vous donne le booléen opposé:

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

--[value] soustrait un (1) à un nombre, puis renvoie ce nombre avec lequel travailler:

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

Ainsi, !--pending soustrait un élément de l'attente, puis renvoie l'opposé de sa valeur vérité/fausseté (que ce soit ou non 0).

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

Et oui, suivez les conseils. Cela peut être un langage courant dans d’autres langages de programmation, mais pour la plupart des programmes JavaScript déclaratifs, cela semble assez étrange.

536
TbWill4321

Ce n'est pas un opérateur spécial, c'est 2 opérateurs standard l'un après l'autre:

  1. Un préfixe décrémente (--)
  2. Un pas logique (!)

Cela provoque la décrémentation de pending, puis son test pour voir s'il est nul.

149
Amit

Un certain nombre de réponses décrit quoi cette commande le fait, mais pas pourquoi c'est ce qui se passe ici.

Je viens du monde C et je lis !--pending comme "décompte pending et vérifie s'il est égal à zéro" sans vraiment y penser. C’est un idiome que les programmeurs de langages similaires devraient connaître.

La fonction utilise readdir pour obtenir une liste de fichiers et de sous-répertoires, que j'appellerai collectivement "entrées".

La variable pending garde une trace du nombre de ces restes à traiter. Il commence par la longueur de la liste et compte à rebours vers zéro à mesure que chaque entrée est traitée.

Ces entrées peuvent être traitées dans le désordre, c'est pourquoi il est nécessaire de compter à rebours plutôt que d'utiliser une simple boucle. Lorsque toutes les entrées ont été traitées, le rappel done est appelé pour informer l'appelant initial de ce fait.

Dans le premier appel à done est précédé de return, non pas parce que nous voulons renvoyer une valeur, mais simplement pour que la fonction cesse de s'exécuter à ce moment-là. Il aurait été plus propre de laisser tomber le return et de placer l’alternative dans un else.

108
Stig Hemmer

C'est un raccourci.

! n'est "pas".

-- décrémente une valeur.

Donc, !-- vérifie si la valeur obtenue en annulant le résultat de la décrémentation d'une valeur est fausse.

Essaye ça:

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

Le premier est faux, puisque la valeur de x est 1, le second est vrai, puisque la valeur de x est 0.

Note latérale: !x-- vérifierait si x est faux en premier, puis le décrémente.

35
Lucas

! est l'opérateur JavaScript NOT

-- est un opérateur de pré-décrémentation. Alors,

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)

veux dire

if(0 == --pending)

veux dire

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

C'est l'opérateur not suivi du pré-décrémenteur en place.

Donc, si pending était un entier valant 1:

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

Explication

Ceci est 2 opérateurs, un ! et un --

!--x 

Donc, cela nuit x par 1 et vérifie si c'est un booléen.

Si vous voulez le rendre plus lisible, vous pouvez:

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

Essaye le:

/* 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>

violon (code d'essai)

12
Ben Aubin

Elle diminue simplement pending de un et obtient son complément logique (négation). Le complément logique de tout nombre différent de 0 est false, pour 0, il est true.

11
MinusFour

Le vrai problème ici est le manque d'espace entre les deux opérateurs ! et --.

Je ne sais pas pourquoi les gens comprennent qu'il est impossible d'utiliser un espace après l'opérateur !. Je pense que cela vient d'une application rigide de règles mécaniques d'espaces au lieu du bon sens. Presque toutes les normes de codage que j'ai vues interdisent les espaces après tous les opérateurs unaires, mais pourquoi?

S'il y a déjà eu un cas où vous avez clairement besoin cet espace, c'est le cas.

Considérez ce morceau de code:

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

Non seulement ! et -- sont-ils écrasés, vous avez également ( critiqués. Pas étonnant qu'il soit difficile de dire ce qui est connecté à quoi.

Un peu plus d'espaces rend le code beaucoup plus clair:

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

Bien sûr, si vous êtes habitué à des règles mécaniques telles que "pas d'espace à l'intérieur" et "pas d'espace après un opérateur unaire", cela peut sembler un peu étranger.

Mais regardez comment les espaces blancs supplémentaires séparent les différentes parties de l'instruction et de l'expression if: vous avez --pending, le -- est donc clairement son propre opérateur et est étroitement lié. à pending. (Il décrémente pending et renvoie le résultat décrémenté.) Ensuite, vous avez le ! séparé de celui-ci; il est donc évident qu'un opérateur distinct annule le résultat. Enfin, vous avez if( et ) entourant l'expression entière pour en faire une instruction if.

Et oui, j'ai supprimé l'espace entre if et (, car le (appartient au if. Ce ( ne fait pas partie d'une sorte de syntaxe de (!-- telle qu'elle apparaît dans l'original, le ( s'il fait partie de la syntaxe de l'instruction if elle-même.

Les espaces servent ici à communiquer le signification, au lieu de suivre certaines normes de codage mécanique.

8
Michael Geary