¿Cómo funciona ~ ~ (no tilde / bang tilde) alterar el resultado de una llamada al método ‘contiene / incluido’?

Si lees los comentarios en la página jQuery inArray aquí , hay una statement interesante:

 !!~jQuery.inArray(elm, arr) 

Ahora, creo que un doble signo de exclamación convertirá el resultado a tipo boolean , con el valor de true . Lo que no entiendo es ¿cuál es el uso del operador tilde ( ~ ) en todo esto?

 var arr = ["one", "two", "three"]; if (jQuery.inArray("one", arr) > -1) { alert("Found"); } 

Refactorizando la statement if :

 if (!!~jQuery.inArray("one", arr)) { alert("Found"); } 

Descompostura:

 jQuery.inArray("one", arr) // 0 ~jQuery.inArray("one", arr) // -1 (why?) !~jQuery.inArray("one", arr) // false !!~jQuery.inArray("one", arr) // true 

También noté que si pongo la tilde al frente, el resultado es -2 .

 ~!!~jQuery.inArray("one", arr) // -2 

No entiendo el propósito de la tilde aquí. ¿Alguien puede explicarlo o señalarme hacia un recurso?

El operador tilde no es realmente parte de jQuery, es un operador NOT bit a bit en JavaScript.

Ver El gran misterio de la tilde (~) .

Obtienen números extraños en sus experimentos porque están realizando una operación lógica en bits en un entero (que, por lo que sé, puede almacenarse como complemento de dos o algo así …)

El complemento a dos explica cómo representar un número en binario. Creo que tenía razón

Hay una razón específica que a veces verá ~ aplicada frente a $.inArray .

Básicamente,

 ~$.inArray("foo", bar) 

es una forma más corta de hacer

 $.inArray("foo", bar) !== -1 

$.inArray devuelve el índice del elemento en la matriz si se encuentra el primer argumento, y devuelve -1 si no se encuentra. Esto significa que si está buscando un booleano de “¿este valor está en la matriz?”, No puede hacer una comparación booleana, ya que -1 es un valor verdadero, y cuando $ .inArray devuelve 0 (un valor falso ), significa que en realidad se encuentra en el primer elemento de la matriz.

Al aplicar el operador bit a bit, -1 convierte en 0 y hace que 0 se convierta en `-1. Por lo tanto, si no se encuentra el valor en la matriz y se aplica NO a nivel de bits, se obtiene un valor falso (0), y todos los demás valores devolverán números que no sean 0 y representarán un resultado verdadero.

 if (~$.inArray("foo", ["foo",2,3])) { // Will run } 

Y funcionará según lo previsto.

!!~expr evalúa a false cuando expr es -1 otra manera true .
Es lo mismo que expr != -1 , solo roto *


Funciona porque las operaciones de bit a bit de JavaScript convierten los operandos en enteros de 32 bits en formato de complemento de dos. !!~-1 Así !!~-1 se evalúa de la siguiente manera:

  -1 = 1111 1111 1111 1111 1111 1111 1111 1111b // two's complement representation of -1 ~-1 = 0000 0000 0000 0000 0000 0000 0000 0000b // ~ is bitwise not (invert all bits) !0 = true // ! is logical not (true for falsy) !true = false // duh 

Un valor distinto de -1 tendrá al menos un bit establecido en cero; invertirlo creará un valor de verdad; aplicando ! operador dos veces a un valor de verdad devuelve booleano verdadero.

Cuando se usa con .indexOf() y solo queremos verificar si el resultado es -1 o no:

 !!~"abc".indexOf("d") // indexOf() returns -1, the expression evaluates to false !!~"abc".indexOf("a") // indexOf() returns 0, the expression evaluates to true !!~"abc".indexOf("b") // indexOf() returns 1, the expression evaluates to true 

* !!~8589934591 evalúa como falso, así que esto abominación no se puede usar confiablemente para probar -1 .

~foo.indexOf(bar) es una taquigrafía común para representar foo.contains(bar) porque la función contains no existe.

Normalmente, el elenco a boolean es innecesario debido al concepto de JavaScript de los valores “falsy”. En este caso, se usa para forzar que la salida de la función sea true o false .

jQuery.inArray() devuelve -1 para “no encontrado”, cuyo complemento ( ~ ) es 0 . Por lo tanto, ~jQuery.inArray() devuelve un valor falso ( 0 ) para “no encontrado”, y un valor de verdad (un entero negativo) para “encontrado”. !! luego formalizará la falsedad / verdad en real booleano false / true . Entonces, !!~jQuery.inArray() dará true para “encontrado” y false para “no encontrado”.

El ~ para todos los 4 bytes int es igual a esta fórmula -(N+1)

ASI QUE

 ~0 = -(0+1) // -1 ~35 = -(35+1) // -36 ~-35 = -(-35+1) //34 

El operador ~ es el operador de complemento bit a bit. El resultado entero de inArray() es -1, cuando el elemento no se encuentra, o algún entero no negativo. El complemento bit a bit de -1 (representado en binario como todos los 1 bits) es cero. El complemento bit a bit de cualquier entero no negativo siempre es distinto de cero.

Por lo tanto, !!~i seré true cuando el entero “i” sea un entero no negativo, y false cuando “i” sea exactamente -1.

Tenga en cuenta que ~ siempre coacciona su operando a entero; es decir, fuerza valores de punto flotante no enteros a enteros, así como valores no numéricos.

Tilde no es bit a bit – invierte cada bit del valor. Como regla general, si usa ~ en un número, su signo se invertirá, luego se restará 1.

Por lo tanto, cuando haces ~0 , obtienes -1 (0 invertido es -0, resta 1 es -1).

Es esencialmente una forma elaborada, súper micro optimizada de obtener un valor que siempre es booleano.

Tiene razón: este código dará como resultado false cuando la llamada indexOf devuelva -1; de lo contrario es true .

Como dices, sería mucho más sensato usar algo como

 return this.modifiedPaths.indexOf(path) !== -1; 

El operador ~ es el operador NOT bit a bit. Lo que esto significa es que toma un número en forma binaria y convierte todos los ceros en unos y unos en ceros.

Por ejemplo, el número 0 en binario es 0000000 , mientras que -1 es 11111111 . Del mismo modo, 1 es 00000001 en binario, mientras que -2 es 11111110 .

Supongo que está ahí porque son unos pocos caracteres más cortos (que los autores de la biblioteca siempre buscan). También utiliza operaciones que solo toman unos pocos ciclos de máquina cuando se comstackn en el código nativo (a diferencia de la comparación con un número).

Estoy de acuerdo con otra respuesta que es una exageración, pero que tal vez tenga sentido en un ciclo cerrado (sin embargo, requiere una estimación de ganancia de rendimiento, de lo contrario puede ser una optimización prematura).

Supongo que, dado que se trata de una operación bitwise, es la forma más rápida (computacionalmente económica) de comprobar si la ruta aparece en modifiedPaths.

As (~(-1)) === 0 , entonces:

 !!(~(-1)) === Boolean(~(-1)) === Boolean(0) === false