LoginSignup
1
1

More than 3 years have passed since last update.

Javascript 文字列検索 indexOf() のちょっとした罠

Last updated at Posted at 2019-12-19

公開後追記

「JS 文字列 存在確認」 とかで検索すると indexOf() を使う方法がたくさん紹介されてますが、もっといい方法がありました。

@ttatsf さんよりコメントで

可能なら、String.prototype.includes() を使ったらいいですね。

というご指摘をいただきました。

"abcdefg".includes("abc") // true

単純な文字列の有無、存在するかどうかを知りたいときには String.includes() を使う方が、より明確であり適切。

追記おしまい

ちょっとした罠

気軽に文字列検索したいとき、正規表現使ったりするほどでもないなというとき、indexOf()を使いたい。

ただそんなとき、

Var string = "abcdefg";
if( string.indexOf('abc') ){
    // true
    console.log('true')
}else{
    // false
    console.log("false")
}

みたいに書いたとしたら


false

とでてくる。

なんでfalseになるのか?

これはindexOfの返り値は「True/False ではなく ヒットした文字列の出現位置」であり、なおかつ「1文字目は0番目」という仕様が関係している。

つまり、「0番目にヒットした」という意味で string.indexOf('abc') の返り値は 0 となり暗黙変換によって 0 = false として処理されることによる。。

厳密にfalseを取るためには、マッチしなかったときの返り値である -1 と比較してあげないといけない。


Var string = "abcdefg";
if( string.indexOf("abc") !== -1 ){
    // true
    console.log("true");
}else{
    // false
    console.log("false");
}

こうしてあげると正常。
決して条件式をそのまま突っ込んではいけない。

ビット反転演算子 ~ を使うケース

たまにビット否定演算子 ~ を使って


Var string = "abcdefg";
if( ~string.indexOf("abc") ){
    // true
    console.log("true");
}else{
    // false
    console.log("false");
}

としているソースコードがあるが、これは見落としたり直感的・一般的ではないと思うのでよっぽど軽量コーディングを心がけているチームでなければ導入しないほうが無難だと思う。

ちなみにこれが成立する理由は

任意の数値 x のビットごとの NOT 演算は、-(x + 1) を出力します。例えば、~5 で -6 を出力します。

ビット演算子 - JavaScript | MDN

とある通り。つまり以下のような変換を行なっていることになる。

~( -1) => 0  // 暗黙変換によりfalse
~ 2    =>  -3 // 暗黙変換によりtrue 

これはjsにおける「数値において0はfalse、0以外はtrueとする暗黙型変換」を利用したものだが、実質的には T/F で判定しているわけではないため、筆者はちょっと不安を覚えてしまう。

余談にはなりますが、ビット変換がなぜ1ずれるのかは2進数の性質上「正の数の最小値は0」であり、「負の数の最小値が-1」というのが理由。
気になる人は、符号付の2進数について調べてみると良いと思います。

1
1
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1