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>
¡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:
-
Una disminución de prefijo (
--
) -
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)