JSのif文で二重否定が出てきた。
二重否定なんだから元に戻って意味なくね?って思ったけど、もっと便利なものだった。
結論、オブジェクトの有無をboolean型にすることができる。
状況
vueファイルの中でこんな感じにいらっしゃった。
:class = "{'hoge': !!fuga}"
これの意味するところはfugaの真偽に応じてhogeというclassを適用するかどうかということ。
つまり、動的にスタイリングできるようになる。
これ下記のような感じだったら何も不思議じゃないんだよな
:class = "{'hoge': !isFuga}"
つまりisFugaがfalseだったらhogeが適用される。
単純に否定形にしてるだけだから。
でもこれが二重否定になったら否定して否定するから元どおり。
そもそも”!!”って付けなくてよくね?ってなる。
オブジェクトをboolean型にできる
もちろん必要だからこのような記述があったわけだ。
それが、オブジェクトの有無をboolean型にできるというもの。
見た方が早い。
const obj = {name: "suna"}
console.log(obj) //objの中身
console.log(!obj) //false
console.log(!!obj) //true
オブジェクトを否定するとfalseになるので、もう一度否定するとtrueにできるというわけだ。
これでただのオブジェクトがboolean型に変換された。
中々うまくできている。
これが活躍するのはundefinedの時。
//objは定義されてない
console.log(obj) //undefined
console.log(!obj) //true
console.log(!!obj) //false
定義されていない場合、そのままだとundefinedになるので、falseとは異なる。
undefinedを否定するとtrueになるので、もう一度否定するとfalseになる。
そう、undefinedを二重否定するとundefinedではなくfalseになるのだ。
これでundefinedをfalseとして使えるようになった。
中々うまくできている。(2回目)
そもそもundefinedはfalseとして処理される?
undefinedの二重否定がfalseになって条件判定に使えるー!とは思ったものの、実際にundefinedのまま以下のようにすると普通にfalseとして扱われてた。
// fugaはundefined
if (fuga) {
console.log("fugaあるよ!");
} else {
console.log("fugaないよ!"); // 出力される
}
え、じゃあ結局undefinedのままでもいいんだったらやっぱり二重否定しなくてもいいの?って感じ
おそらくだけど、これだと二重等号(==)で比較してるからあんまりよろしくないんだろうなと思っている。
つまり以下と等価なんだろうなと。
if (fuga == true) {
console.log("fugaあるよ!");
} else {
console.log("fugaないよ!");
}
JSではできるだけ三重等号(===)を使うべきなので厳密さに欠ける。
その点二重否定した後だとちゃんとboolean型になるから三重等号で評価できるようになる。
あと、これは想像で確かめてはいないんだけど、単純なif文じゃなくてReactとかVueのインラインで条件分岐する時に重要なのかもしれない。
最初に出てきたこの文。
:class = "{'hoge': !!fuga}"
この「!!fuga」の部分て真偽値が入らなきゃいけないからオブジェクトそのまま突っ込んでも評価されないのではないかと思っている。
boolean型のtrue or falseが入らなきゃいけないんじゃないかなと。
確かめてはいないから、違うかもしれない。
まぁオブジェクトの有無をboolean型で表現できるようになったということが分かったので今回はよしとする。
ただしデメリットも。
オブジェクトは定義さえされていれば中身が空でもtrueになるので注意。
あと数字の1はtrueだが0はfalseなど。
何がtrueで何がfalseなのかはちゃんと把握した上で使わないと逆の条件になってしまいそうだから注意。