Double bitwise NOT (~~) double bitwise NOT (~~) - James Padolsey

콘텐츠

JavaScript의 드문하고 신비한 비트 연산자가 이렇게 유용할 줄이야? 나는 처음에 Thomas Fuchs의 JavaScript 성능에 관한 슬라이드쇼에서 이 트릭을 발견했다. 이 '트릭'은 다음과 같다.

비트 NOT 연산자(~)는 피연산자를 32비트 정수로 변환한 후 각 비트를 반전하여 각 01로, 10으로 변환합니다.

00000000000000000000000000001001 ...becomes 11111111111111111111111111110110

이 경우, 표현식 ~foo의 효과는 -(foo + 1)입니다. 이중 비트 NOT 연산(~~foo)은 따라서 -(-(foo + 1) + 1)의 결과를 얻을 것입니다. 하지만 이는 정수에 대해서만 유효하며, 모든 가능한 피연산자를 고려할 때, ~~의 실제 등가 표현식은 아마도 다음과 같을 것입니다:

typeof foo === 'number' && !isNaN(foo) && foo !== Infinity ? foo > 0 ? Math.floor(foo) : Math.ceil(foo) : 0; // 이것은 효과적으로 동일합니다... 내부에서 일어나는 것은 아닙니다!

이것은 분명히 ~~보다 느립니다.

피연산자가 숫자이고 NaN 또는 Infinity가 아니라면 ~~는 해당 숫자를 0에 가깝게 반올림하는 효과가 있습니다(음수에 대해 Math.ceil, 양수에 대해 Math.floor). 숫자가 아닌 경우 내부 ToInt32 함수가 0으로 변환된다고 생각합니다.

다음은 이중 비트 NOT 연산의 모든 영광을 담은 몇 가지 예시입니다:

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

~~의 바닥재 기능은 Math.floor보다 더 나은 대안이 됩니다. 양수를 다루고 있다는 것을 알고 있다면 더 빠르고 문자 수도 적게 차지합니다. 하지만 가독성은 조금 떨어집니다. 그래도 나는 ~~가 JS 분야에서 점차 매우 잘 알려진 기술이 되어서 우리가 모두 두려움 없이 사용할 수 있기를 희망합니다.

일반적으로 정수로 예상되는 인수를 정규화하는 데 매우 유용합니다. 지원하지 않는 브라우저에 Array.prototype.indexOf를 제공하기 위해 MDC에서 권장하는 내용에서 다음 예제를 살펴보세요.

요약하다
자바스크립트의 비트 연산자인 ~는 피연산자를 32비트 정수로 변환하고 각 비트를 반전시킵니다. 이를 이용해 숫자를 소수점을 버리고 정수로 변환할 수 있으며, Math.floor와 비교해 빠르고 간결하다. ~~를 사용하면 인자를 정규화하는 데 유용하며, MDC에서 추천하는 Array.prototype.indexOf의 예제도 간결해진다.