Dupla negação bit a bit (~~) - James Padolsey

contente

Quem poderia imaginar que os raros e misteriosos operadores bit a bit do JavaScript poderiam ser tão úteis? Descobri esse truque pela primeira vez há algum tempo em uma apresentação sobre desempenho do JavaScript, por Thomas Fuchs. O "truque" é o seguinte:

O operador NOT bit a bit (~) irá pegar seu operando, convertê-lo para um inteiro de 32 bits, e inverterá cada bit de forma que cada 0 se torne um 1 e vice-versa.

00000000000000000000000000001001 ...torna-se 11111111111111111111111111110110

O efeito disso, dado a expressão ~foo é -(foo + 1). Uma operação dupla de NÃO bit a bit (~~foo) resultará portanto em -(-(foo + 1) + 1). Isso só permanece verdadeiro para inteiros; dado todos os possíveis operandos, a expressão equivalente real para ~~ provavelmente é algo como:

typeof foo === 'number' && !isNaN(foo) && foo !== Infinity ? foo > 0 ? Math.floor(foo) : Math.ceil(foo) : 0; // Isso é APENAS efetivamente o mesmo... isso NÃO é o que acontece internamente!

Isso é obviamente um pouco mais lento do que ~~.

Se o operando for um número e não for NaN ou Infinity, então ~~ terá o efeito de arredondá-lo em direção a zero (Math.ceil para negativo, Math.floor para positivo). Se não for um número, então acredito que a função interna ToInt32 o converte para zero.

Aqui estão alguns exemplos da operação de NÃO bit a bit duplo em todo o seu esplendor:

~~null; // => 0 ~~undefined; // => 0 ~~0; // => 0 ~~{}; // => 0 ~~[]; // => 0 ~~(1/0); // => 0 ~~false; // => 0 ~~true; // => 1 ~~1.2543; // => 1 ~~4.9; // => 4 ~~(-2.999); // => -2

As capacidades de arredondamento de '~~' tornam-no uma alternativa melhor para 'Math.floor' se você souber que está lidando com números positivos - é mais rápido e ocupa menos caracteres. No entanto, não é tão legível, mas espero que '~~' se torne lentamente uma técnica muito conhecida na arena do JS, para que todos possamos usá-la sem temer acusações.

É bastante útil para normalizar argumentos que você espera que sejam inteiros também. Pegue este exemplo do que o MDC recomenda para fornecer Array.prototype.indexOf para navegadores que não oferecem suporte:

Resumir
O artigo explora o uso dos operadores bitwise em JavaScript, destacando o operador bitwise NOT (~) e sua capacidade de arredondar números para zero. O autor demonstra como ~~foo pode ser usado para arredondar um número para zero de forma mais eficiente do que Math.floor, e fornece exemplos de uso. Ele também sugere que ~~foo pode ser útil para normalizar argumentos esperados como inteiros. O autor encoraja o uso desse truque e espera que se torne uma técnica bem conhecida na comunidade JavaScript.