Double bitwise NOT (~~) – James Padolsey

コンテンツ

JavaScriptの珍しい謎めいたビット演算子がこんなに役立つとは誰も思っていなかったでしょう。私はThomas FuchsによるJavaScriptパフォーマンスに関するスライドショーでこのトリックを初めて知りました。その「トリック」は次のとおりです。

ビットごとのNOT演算子(~)は、そのオペランドを32ビットの整数に変換し、各ビットを反転させて、各01に、逆も同様になります。

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; // This is ONLY effectively the same... this is // NOT what happens internally!

これは明らかに~~よりもかなり遅いです。

もしオペランドが数値であり、かつNaNInfinityでない場合、~~はその数値をゼロに向かって丸める効果があります(負の数の場合はMath.ceil、正の数の場合はMath.floor)。数値でない場合は、内部のToInt32関数によってゼロに変換されると思います。

これは、その全栄光を持っているダブルビットワイズ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よりも優れた代替手段となります。速くて文字数も少ないです。ただし、読みやすさはそれほどではありませんが、私は~~がJavaScriptの世界で徐々に非常によく知られたテクニックになることを期待しています。そうすれば、誰もが非難を恐れることなくそれを使うことができるでしょう。

通常整数として期待される引数を正規化するのに非常に便利です。サポートしていないブラウザにArray.prototype.indexOfを提供するためのMDCの推奨事項からこの例を見てみましょう。

/Array.prototype.indexOf = function.../ var from = Number(arguments[1]) || 0;
from = (from < 0)
? Math.ceil(from)
: Math.floor(from);

In goes ~~:

要約する
JavaScriptのビット演算子である`~`と`~~`は、数値を32ビット整数に変換し、0を1に、1を0に反転する効果がある。`~~`は数値をゼロに近似するため、`Math.floor`よりも速く、文字数も少ない。これは整数を正規化するのに便利で、非対応ブラウザ向けの`Array.prototype.indexOf`の実装などで利用される。