ESLint の eqeqeq 兼 unit test 通してないなら慎重になぁ

いつかやると思ってたわい。

eqeqeq

意味は生半可には知ってたつもりだったが、これに関する「本物のミス」をやらかして、初めて本当の意味がわかった。そして「eqeqeq に従って闇雲に」直してぶっ壊す、という、初心者みたいなことをやらかした。きゃー恥ずかしくって穴があったら○○たい。

一応これでも「少しくらいはまとも」なつもりなので、node.js + mocha してる部分とそうでない部分の ESLint は頭の中ではきちんと区別して、mocha してないとこは「どんな些細な変更でも動作確認」とする「心意気」だけは持ってたのに、「魔がさして」サボったばっかりに…。なんとなく「== を === に、!= を !== に変えるくらいなら多分大丈夫だろ」と油断してしまった。

要するに(初めて正確な理解をしたが)「==」「!=」は、「暗黙の型変換に頼った比較」をするんだよね。だから、ワタシのケースでは、

 1 <fieldset>
 2 Main/Supporting: <select
 3  class="cynodes-filters"
 4  id="chara-ms">
 5   <option value="Both" selected>Both</option>
 6   <option value="1">Main</option>
 7   <option value="2">Supporting</option>
 8 </select>
 9 <!-- ...-->
10 <script>
11 // ...
12 function _cycharnode_vis_filter(amalid, ms, cv, ch) {
13     var sel_ms = $("#chara-ms").val();
14     // ms は本当に「数値」型、sel_ms は文字列…。
15     if (sel_ms !== "Both" && ms !== sel_ms) {
16         return false;
17     }
18     // ...
19 }
20 //...
21 </script>

無論もともとは「!=」だった箇所。eqeqeq に従いつつも正しくするには:

1 function _cycharnode_vis_filter(amalid, ms, cv, ch) {
2     var sel_ms = $("#chara-ms").val();
3     // ms は本当に「数値」型、sel_ms は文字列…。
4     if (sel_ms !== "Both" && ms !== parseInt(sel_ms)) {
5         return false;
6     }
7     // ...
8 }

とかかいね。

実は随分前から「===」「!==」の存在は知っていたし、「そっちが推奨されてるらしい」みたいな聞きかじりはしてたし、なので「eqeqeq」の言うことというのは「何となく根拠なく絶対視」してしまっていたんだけれど、ただねぇ、今こうして初めて意味がちゃんとわかってみると、「=== が絶対だ!」てのもちょっとヘンなんじゃないか、て気がしてきた。

id の話で書いた通り、javascript の言語仕様上、「暗黙の(かなり乱暴な)型変換」というのは、結構乱暴な考えをするワタシでさえ「まぁ結構ほかの言語と較べてもとりわけ危ういかもしらんなぁ」とは思うよ、思うけど、でも一方では「便利だ」とも思うんだよねぇ。なんでも「わかりにくい、危ない」という理由だけで非難するってのもどうなんだろうか、と。

現実に「型も込みでの厳密な比較をする方が安全でわかりやすい」には決まってる、という意見にはもちろん同意はするけれど(だって、「C/C++ プログラマ」だよ、ワタシは)、でもワタシがハマったケースなんてのは、まさに「型」ではなく「意味」で比較出来ていたわけなんだから、別に「わかりにくくて万死に値する!」てほどのもんなんかいな、と。(結構 SQL での coalesce の使い方でもこういう議論はありそうな気がするけど要するにそういうこと。)

まぁ「(===、!== が良いと)受け容れる」よ、その方が行儀がいい理由なんてちゃんとわかるから。そして本当の問題は無論そんなことではなく、見出しにした通り、「スタイルチェッカがその方が正しいと言ったから、というだけでテストしなおしもせずにコードを変えるなや」という当たり前の話