String.prototype.indexOf() - JavaScript | MDNは、Stringの中の文字があったら、その文字の開始位置を返して、ない場合は「-1」を返します。
配列に対しても同様のメソッドがあり(Array.prototype.indexOf() - JavaScript | MDN)、配列の中の要素と、与えた値がマッチするか(===で比較する)どうかを調べて、マッチしたら配列のindexを返して、ない場合は「-1」を返します。
たとえば、indexOfを使って、対象の文字列もしくは配列に、渡した値が存在するかどうかを確かめる場合、
1 | var a = 'foobar'; |
とする(RegExp.prototype.test() - JavaScript | MDNもあるけど)。
ビット演算子(Bitwise operators - JavaScript | MDN)は、ビットを扱う演算子。その中で「~」はNOTの扱う演算子で(~ (Bitwise NOT))、それぞれのbitを反転した値を返す。
Javascriptのビット演算子はSigned 32-bit integer に変換される、というMDNの記述を下記に引用する(ECMAScriptの仕様は確認してない…)。
The operands of all bitwise operators are converted to signed 32-bit integers in two’s complement format. Two’s complement format means that a number’s negative counterpart (e.g. 5 vs. -5) is all the number’s bits inverted (bitwise NOT of the number, a.k.a. ones’ complement of the number) plus one. For example, the following encodes the integer 314:
日本語の情報もあったので、該当箇所もあわせて引用。
すべてのビット演算でオペランドは符号付き 32 ビット演算に、ビッグエンディアンおよび 2 の補数形式で変換されます。ビッグエンディアン形式とは、32 ビットを水平方向に並べたとき最上位ビット (最大値のビット位置) が左端にある形式です。2 の補数形式とは、ある値に対する負数 (例えば 5 と -5) は、正数のビットをすべて反転 (正数の NOT ビット演算、1 の補数として知られています) して 1 を加えたものです。例えば以下は、整数値 314 (10 進数) を表しています:
つまり、32bitにおける-1(base 10)は以下のようなbitになる。
1 | -1 (base 10) = 11111111111111111111111111111111 (base 2) |
それを~のビット演算子で反転させると「00000000000000000000000000000000」というビットになる。これは10進数に数値にすると「0」になる。
Javascriptにおいて、数値の「0」はfalsyとして扱われ、それ以外はtruthyとなるので、上の方のindexOfの例を下記のように書き換えることができる。
1 | var a = 'foobar'; |
a.indexOfでマッチしなかった場合のみ「-1」となり、-1を~のビット演算子で反転させた場合「0」となる。マッチしたときは「-1」以外になり、その場合ビット演算子で反転させた値も「0」以外となるので、truthyとなる。
なので、!== -1 で比較しても、~を使って比較しても、結果としては同じになる。
気分的に「~」を使う方が「!== -1」を使うより洗練されててエレガントな感じがある。どこかで使いたい。でも「!== -1」の方が直接的だし読みやすいよねえ、、と思って、結局いつも「!== -1」で比較している。
というメモ。