ejemplos - ¿Qué hace ~~("double tilde") en Javascript?
javascript html (9)
Aquí hay un ejemplo de cómo este operador se puede usar de manera eficiente, donde tiene sentido usarlo:
leftOffset = -(~~$(''html'').css(''padding-left'').replace(''px'', '''') + ~~$(''body'').css(''margin-left'').replace(''px'', '''')),
Fuente:
Estaba revisando una biblioteca de física de juegos en línea hoy y me encontré con el operador ~~. Sé que un solo ~ es un NO de bit a bit, ¿eso haría ~~ un NO de un NO, que devolvería el mismo valor, verdad?
Conversión de cadenas en números
console.log(~~-1); // -1
console.log(~~0); // 0
console.log(~~1); // 1
console.log(~~"-1"); // -1
console.log(~~"0"); // 0
console.log(~~"1"); // 1
console.log(~~true); // 1
console.log(~~false); // 0
~ -1 es 0
if (~someStr.indexOf("a")) {
// Found it
} else {
// Not Found
}
Dado que ~N
es -(N+1)
, ~~N
es entonces -(-(N+1) + 1)
. Lo cual, evidentemente, conduce a un buen truco .
El ~
parece hacer -(N+1)
. Entonces ~2 == -(2 + 1) == -3
Si lo haces de nuevo en -3 lo regresa: ~-3 == -(-3 + 1) == 2
Probablemente solo convierta una cadena en un número en una forma redonda.
Ver este hilo: http://www.sitepoint.com/forums/showthread.php?t=663275
Además, la información más detallada está disponible aquí: http://dreaminginjavascript.wordpress.com/2008/07/04/28/
El primer ~ operador fuerza el operando a un entero (posiblemente después de forzar el valor a una cadena o un booleano), luego invierte los 31 bits más bajos. Oficialmente, los números de ECMAScript son todos de coma flotante, pero algunos números se implementan como enteros de 31 bits en el motor de SpiderMonkey.
Puede usarlo para convertir una matriz de 1 elemento en un número entero. Los puntos flotantes se convierten de acuerdo con la regla C, es decir. truncamiento de la parte fraccional.
El segundo operador ~ entonces invierte los bits hacia atrás, para que sepa que tendrá un número entero. Esto no es lo mismo que forzar un valor a booleano en una declaración de condición, porque un objeto vacío {} se evalúa como verdadero, mientras que ~~ {} se evalúa como falso.
js>~~"yes"
0
js>~~3
3
js>~~"yes"
0
js>~~false
0
js>~~""
0
js>~~true
1
js>~~"3"
3
js>~~{}
0
js>~~{a:2}
0
js>~~[2]
2
js>~~[2,3]
0
js>~~{toString: function() {return 4}}
4
js>~~NaN
0
js>~~[4.5]
4
js>~~5.6
5
js>~~-5.6
-5
Elimina todo después del punto decimal porque los operadores bit a bit convierten implícitamente sus operandos en enteros de 32 bits con signo. Esto funciona si los operandos son números (punto flotante) o cadenas, y el resultado es un número.
En otras palabras, cede:
function(x) {
if(x < 0) return Math.ceil(x);
else return Math.floor(x);
}
solo si x está entre - (2 31 ) y 2 31 - 1. De lo contrario, se producirá un desbordamiento y el número se "ajustará".
Esto se puede considerar útil para convertir el argumento de cadena de una función a un número, pero debido a la posibilidad de desbordamiento y de que es incorrecto para usar con números enteros, no lo usaría de esa forma excepto para "código de golf" ( es decir, cortando inútilmente los bytes del código fuente de tu programa a expensas de la legibilidad y la robustez). Yo usaría +x
o Number(x)
lugar.
Cómo es el NO del NO
El número -43.2, por ejemplo es:
-43.2 10 = 11111111111111111111111111010101 2
como un número binario firmado (complemento de dos) de 32 bits. (JavaScript ignora lo que está después del punto decimal.) Invertir los bits da:
NO -43 10 = 00000000000000000000000000101010 2 = 42 10
Invertir nuevamente da:
NO 42 10 = 11111111111111111111111111010101 2 = -43 10
Esto difiere de Math.floor(-43.2)
en que los números negativos se redondean hacia cero, no lejos de él. (La función de piso, que equivaldría a -44, siempre redondea al siguiente entero más bajo, independientemente de si el número es positivo o negativo).
En ECMAScript 6, el equivalente de ~~
es Math.trunc :
Devuelve la parte integral de un número eliminando los dígitos fraccionarios. No redondea ningún número.
Math.trunc(13.37) // 13
Math.trunc(42.84) // 42
Math.trunc(0.123) // 0
Math.trunc(-0.123) // -0
Math.trunc("-1.123")// -1
Math.trunc(NaN) // NaN
Math.trunc("foo") // NaN
Math.trunc() // NaN
El polyfill:
function trunc(x) {
return x < 0 ? Math.ceil(x) : Math.floor(x);
}
Solo un poco de advertencia. Las otras respuestas aquí me metieron en problemas.
La intención es eliminar cualquier cosa después del punto decimal de un número de punto flotante, pero tiene algunos casos de esquina que lo convierten en un peligro de error. Recomiendo evitar ~~.
Primero, ~~ no funciona en números muy grandes.
~~1000000000000 == -727279968
Como alternativa, use Math.trunc()
(como mencionó Gajus, Math.trunc()
devuelve la parte entera de un número de punto flotante, pero solo está disponible en JavaScript compatible con ECMAScript 6). Siempre puede crear su propio Math.trunc()
para Math.trunc()
que no sean ECMAScript-6 haciendo esto:
if(!Math.trunc){
Math.trunc = function(value){
return Math.sign(value) * Math.floor(Math.abs(value));
}
}
Escribí una publicación de blog sobre esto como referencia: http://bitlords.blogspot.com/2016/08/the-double-tilde-x-technique-in.html
Tilde (~) tiene un algoritmo - (N + 1)
Por ejemplo:
~0 = -(0+1) = -1
~5 = -(5+1) = -6
~-7 = -(-7+1) = 6
Doble tilde es - (- (N + 1) +1)
Por ejemplo:
~~5 = -(-(5+1)+1) = 5
~~-3 = -(-(-3+1)+1) = -3
Triple tilde es - (- (- (N + 1) +1) +1)
Por ejemplo:
~~~2 = -(-(-(2+1)+1)+1) = -3
~~~3 = -(-(-(3+1)+1)+1) = -4