tag style div attribute javascript decrement prefix-operator not-operator

style - ¿Qué hace "!-" en JavaScript?



title tag html5 (10)

Tengo este fragmento de código (tomado de esta pregunta ):

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

Estoy tratando de seguirlo, y creo que entiendo todo, ¡excepto cerca del final donde dice !--pending . En este contexto, ¿qué hace ese comando?

Editar: agradezco todos los comentarios adicionales, pero la pregunta ha sido respondida muchas veces. ¡Gracias de cualquier manera!


Explicación

Esto es 2 operadores, a ! y un --

!--x

Entonces, esto perjudica x por 1, y verifica si es booleano.

Si desea que sea más legible, puede:

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

Pruébalo:

/* 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 (código de prueba)


¡El verdadero problema aquí es la falta de espacio entre los dos operadores ! y -- .

¡No sé por qué las personas piensan que no se puede usar un espacio después del ! operador. Creo que proviene de la aplicación rígida de las reglas mecánicas de espacios en blanco en lugar del sentido común. Casi todos los estándares de codificación que he visto prohíben espacios después de todos los operadores unarios, pero ¿por qué?

Si alguna vez hubo un caso en el que claramente necesita ese espacio, este es uno.

Considere este bit de código:

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

No solo lo son ! y -- combinados, lo tienes ( golpeado contra ellos también. No es de extrañar que sea difícil saber qué está conectado a qué.

Un poco más de espacio en blanco hace que el código sea mucho más claro:

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

Claro, si está acostumbrado a las reglas mecánicas como "sin espacio dentro de parens" y "sin espacio después de un operador unario", esto puede parecer un poco extraño.

Pero observe cómo el espacio en blanco adicional agrupa y separa las diversas partes de la declaración y expresión if : Usted tiene --pending , por lo --pending claramente es su propio operador y está estrechamente vinculado a pending . (Decrementa pending y devuelve el resultado decrementado.) ¡Entonces tienes el ! separado de eso, por lo que obviamente es un operador distinto, que niega el resultado. Finalmente, tienes if( y ) alrededor de toda la expresión para que sea una declaración if .

Y sí, eliminé el espacio entre if y ( porque el ( pertenece al if . This ( no es parte de algún tipo de sintaxis (!-- como parece estar en el original, el ( if es parte del sintaxis de la declaración if sí.

El espacio en blanco aquí sirve para comunicar el significado , en lugar de seguir algún estándar de codificación mecánica.


Es el operador no seguido por el pre-decrementador en el lugar.

Entonces, si pending era un entero con un valor de 1:

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


Es una taquigrafía.

! no es".

-- disminuye un valor.

!-- Entonces !-- comprueba si el valor obtenido al negar el resultado de disminuir un valor es falso.

Prueba esto:

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

El primero es falso, ya que el valor de x es 1, el segundo es verdadero, ya que el valor de x es 0.

Nota al !x-- verificaría primero si x es falso y luego lo disminuiría.


Ese no es un operador especial, son 2 operadores estándar uno tras otro:

  1. Una disminución de prefijo ( -- )
  2. Un lógico no ( ! )

Esto hace que el pending sea ​​decrementado y luego probado para ver si es cero.


Simplemente disminuye pending en uno y obtiene su complemento lógico (negación). El complemento lógico de cualquier número diferente de 0 es false , para 0 es true .


Varias respuestas describen lo que hace este comando, pero no por qué se hace así aquí.

¡Vengo del mundo C, y leí !--pending como "cuenta regresiva pending y verifique si es cero" sin realmente pensarlo. Es un idioma que creo que los programadores en lenguajes similares deberían saber.

La función utiliza readdir para obtener una lista de archivos y subdirectorios, que colectivamente llamaré "entradas".

La variable pending realiza un seguimiento de cuántos de estos quedan por procesar. Comienza como la longitud de la lista y cuenta hacia abajo hacia cero a medida que se procesa cada entrada.

Estas entradas pueden procesarse fuera de servicio, por lo que es necesario realizar una cuenta regresiva en lugar de simplemente usar un bucle simple. Cuando se han procesado todas las entradas, se llama a la devolución de llamada done para notificar al llamador original de este hecho.

En la primera llamada a done se antepone a return , no porque queramos devolver un valor, sino simplemente para que la función deje de ejecutarse en ese punto. Hubiera sido un código más limpio dejar caer la return y poner la alternativa en otra else .


! es el operador JavaScript NOT

-- es un operador de pre-decremento. Asi que,

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


! invierte un valor y le da el booleano opuesto:

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

--[value] resta uno (1) de un número, y luego devuelve ese número para trabajarlo:

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

Entonces,! !--pending resta uno de pendiente, y luego devuelve lo contrario de su valor verdadero / falso (sea o no 0 ).

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

Y sí, sigue la ProTip. Esto puede ser un idioma común en otros lenguajes de programación, pero para la mayoría de la programación declarativa de JavaScript parece bastante extraño.


if(!--pending)

medio

if(0 == --pending)

medio

pending = pending - 1; if(0 == pending)