¿Qué hace una tilde cuando precede a una expresión?

Resuelto wwaawaw asked hace 12 años • 5 respuestas
var attr = ~'input,textarea'.indexOf( target.tagName.toLowerCase() )
           ? 'value'
           : 'innerHTML'

Lo vi en una respuesta y nunca lo había visto antes.

¿Qué significa?

wwaawaw avatar Sep 06 '12 19:09 wwaawaw
Aceptado

~es un operador bit a bit que invierte todos los bits de su operando.

Por ejemplo, si su número fuera 1, su representación binaria del flotante IEEE 754 (cómo JavaScript trata los números) sería...

0011 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

Entonces ~convierte su operando a un entero de 32 bits (los operadores bit a bit en JavaScript hacen eso)...

0000 0000 0000 0000 0000 0000 0000 0001

Si fuera un número negativo, se almacenaría en complemento a 2: se invierten todos los bits y se suma 1.

...y luego voltea todos sus bits...

1111 1111 1111 1111 1111 1111 1111 1110

Entonces, ¿de qué sirve? ¿Cuándo se podría utilizar alguna vez?

Tiene bastantes usos. Si estás escribiendo cosas de bajo nivel, es útil. Si perfiló su aplicación y encontró un cuello de botella, podría mejorar su rendimiento mediante el uso de trucos bit a bit (como una posible herramienta en una bolsa mucho más grande).

También es un truco (generalmente) poco claro convertir indexOf()el valor de retorno encontrado en verdadero (mientras no se encuentra como falso ) y la gente a menudo lo usa por su efecto secundario de truncar números a 32 bits (y eliminar su decimal duplicándolo, efectivamente lo mismo que Math.floor()para los números positivos).

Digo poco claro porque no es inmediatamente obvio para qué se utiliza. Generalmente, desea que su código se comunique claramente con otras personas que lo lean. Si bien su uso ~puede parecer interesante , generalmente es demasiado inteligente para su propio bien. :)

También es menos relevante ahora que JavaScript tiene Array.prototype.includes()y String.prototype.includes(). Estos devuelven un valor booleano. Si su plataforma de destino lo admite, debería preferir esto para probar la existencia de un valor en una cadena o matriz.

alex avatar Sep 06 '2012 12:09 alex

Usarlo antes de una indexOf()expresión efectivamente le brinda un resultado verdadero/falso en lugar del índice numérico que se devuelve directamente.

Si el valor de retorno es -1, entonces ~-1se 0debe a que -1es una cadena de 1 bits. Cualquier valor mayor o igual a cero dará un resultado distinto de cero. De este modo,

if (~someString.indexOf(something)) {
}

hará que el ifcódigo se ejecute cuando "algo" esté en "alguna cadena". Si intenta utilizarlo .indexOf()como booleano directamente, no funcionará porque a veces devuelve cero (cuando "algo" está al principio de la cadena).

Por supuesto, esto también funciona:

if (someString.indexOf(something) >= 0) {
}

y es considerablemente menos misterioso.

A veces también verás esto:

var i = ~~something;

Usar el ~operador dos veces así es una forma rápida de convertir una cadena en un entero de 32 bits. El primero ~realiza la conversión y el segundo ~invierte los bits. Por supuesto, si el operador se aplica a algo que no se puede convertir en un número, se obtiene NaNun resultado. ( editar : en realidad, es el segundo ~el que se aplica primero, pero ya entiendes la idea).

Pointy avatar Sep 06 '2012 12:09 Pointy

El operador NOT bit a bit es ~más o menos lo mismo que . Es más fácil de entender, más o menos. Entonces:~x-(x+1)

~2;    // -(2+1) ==> -3

Considerar -(x+1). -1puede realizar esa operación para producir un 0.

En otras palabras, ~si se usa con un rango de valores numéricos, se producirá un valor falso (forzado a partir falsede 0) solo para el -1valor de entrada; de lo contrario, cualquier otro valor verdadero.

Como sabemos, -1comúnmente se le llama valor centinela . Se utiliza para muchas funciones que devuelven >= 0valores de éxito y fracaso -1en lenguaje C. Que es la misma regla de valor de retorno en JavaScript.indexOf()

Es común comprobar la presencia/ausencia de una subcadena en otra cadena de esta manera

var a = "Hello Baby";

if (a.indexOf("Ba") >= 0) {
    // found it
}
if (a.indexOf("Ba") != -1) { 
    // found it
}

if (a.indexOf("aB") < 0) { 
    // not found
}
if (a.indexOf( "aB" ) == -1) { 
    // not found
}

Sin embargo, sería más fácil hacerlo ~como se muestra a continuación.

var a = "Hello Baby";

~a.indexOf("Ba");         // -7   -> truthy
if (~a.indexOf("Ba")) {   // true
    // found it
}

~a.indexOf("aB");         // 0    -> falsy
!~a.indexOf("aB");        // true
if (!~a.indexOf( "aB" )) {  // true
    // not found
}

No conoces JS: tipos y gramática por Kyle Simpson

zangw avatar Jan 11 '2016 05:01 zangw

~indexOf(item)aparece con bastante frecuencia, y las respuestas aquí son excelentes, pero tal vez algunas personas simplemente necesiten saber cómo usarlo y "saltarse" la teoría:

   if (~list.indexOf(item)) {
     // item in list
   } else {
     // item *not* in list
   }
j-- avatar Feb 27 '2015 03:02 j--