【JS】文字列をbool値に変換したいなら二重否定(!!)を使おう
動機
React の開発を進めている際、あるコンポーネントに props として文字列が存在するかどうかを真偽値として渡すシチュエーションがありました。
以下はその際の簡略化されたコードです。
<FavoriteButton
hasFavorite={favoriteResult !== ""} // ⇦ 文字列が含まれていれば`true`、そうでなければ`false`
addToFavorite={addToFavorite}
removeFromFavorite={removeToFavorite}
/>
このコードの意図としては、favoriteResult
に文字列が存在すれば hasFavorite
に true
を、存在しなければ false
を渡すというものです。
最初のアプローチでは favoriteResult !== ""
という式を使用して、文字列が空でない場合に true
を返すようにしていました。しかし、この表現をよりシンプルにできないかと思い、調査したところ二重否定(!!)
を使う方法が見つかりました。この記事では、その手法について簡単に解説します。
二重否定(!!)とは?
JavaScript における!
は、論理否定の演算子として機能します。
この演算子は真偽値を反転させる役割を持ちます。具体的には、真 (true) は偽 (false) に、偽は真に反転されます。
以下がその例になります。
console.log(!true); // false
console.log(!false); // true
console.log(!0); // true
console.log(!1); // false
console.log(!""); // true
console.log(!"Hello"); // false
console.log(!null); // true
console.log(!undefined); // true
本題である二重否定(!!)についてですが、これは論理否定の!
を 2 回続けて使用する表現です。
これにより、ある値を強制的に真偽値に変換することができます。
イメージがつきやすいように、以下にそのプロセスを書いていきます。
const text = "hello";
// 1回目の反転
const hasTextFirst = !text;
console.log(hasTextFirst); // false
// 2回目の反転
const hasTextSecond = !hasTextFirst;
console.log(hasTextSecond); // true
1 回目の反転で、text
が文字列を持っているため、!
により真偽値がtrue
からfalse
に反転されます。
次に、2 回目の反転で、1 回目で得られたhasTextFirst
の真偽値を再度反転させて、false
からtrue
にします。
この 2 回の操作を 1 行で表現したものが、以下のように!!
を使ったコードになります。
const text = "hello";
const hasText = !!text;
console.log(hasText); // true
この方法により、2 つのステップを 1 行で簡潔に書くことができ、文字列から真偽値を効率的に得ることができました。
まとめ
二重否定(!!)は、文字列などの値を真偽値に変換する際に役立ちます。
もちろん、当初の動機で触れたように、favoriteResult !== ""
という表現で「空文字ではない場合は true」と判定することも可能ですが、二重否定を使って、!!favoriteResult
と書いた方がコードがよりシンプルになり読みやすいかと思います。
<FavoriteButton
hasFavorite={!!favoriteResult} // ⇦ 文字列が含まれていれば`true`、そうでなければ`false`
addToFavorite={addToFavorite}
removeFromFavorite={removeToFavorite}
/>
今後も積極的に二重否定を活用していきたいと考えていますが、過度な使用により読みにくくなることや、チームメンバーの理解度を考慮しながら、適切な場面で使用するよう心掛けたいと思います。
Discussion
JSだと、True属性/False属性を判定に用いるのは基本ご法度なので、!!でBooleanに変換するのはやめたほうがいいです。
TypeScriptで文字列と確定している変数ならともかく、JSの場合はバッドパターンですわ。
可読性を考えるとBoolean(value1)とするのがギリギリですが、それよりもvalue1 !== "" で、空文字判定する方が「シンプル」です。
打鍵数が少ないほうがよりシンプルだと考えるのはまずい考え方です。
変数に空文字が入っているつもりのプログラムなのに、数値の0やundefinedやNaNが入っていて空文字と同じだと判定されて不具合になってしまう、というプログラムを嫌ってほどみてきて苦労したので、False属性のような曖昧な条件判断はするべきじゃないです。