はじめに
検証は2014年8末頃に行いましたが、私の手元にはもうiOS7.0.xの端末が無いのでもう追加検証することはできません。
(何故検証した時に投稿していないのかというと、そこ頃は私がQiitaをやっていなかった、それだけの理由です。)
iOS7.0.3とiOS7.0.4で確認しました。iOS7.1では直ってます。
このバグについて
iOS7.0.xで、『if文の条件式内の論理値と論理積を含む条件式との比較が正しく判定されないバグ』があります。
何を言っているか分からないと思うので、検証コードをご覧ください。
if (false !== (null && 'hoge')) {
alert('success');
} else {
alert('error'); // iOS7.0.4だとelse文が実行される
}
この条件式は、(null && 'hoge')
はnull
なので、false
との厳密等価比較結果は偽です。なのでelse分には入りませんね。しかし、iOS7.0.xはelse文に入ります。嘘でしょ? と思いますよね。でも本当なんです。
null
や 'hoge'
のように値を書いたせいで分かりにくくなっているかもしれませんが、変数でも同じです。例えば、引数指定無しなら何もしないけど、引数にfalseが明示的に指定されているかつ何かのフラグがfalseならチョメチョメするみたいな場合にこの地雷パターンのコードが出てくると思います。
回避方法
この地雷パターンですが、if文の条件式でないなら何も問題ないです。
if文の条件式に、論理値と論理積を含む条件式を書かなければよいだけです。
以下のように回避できます。
var val = null && 'hoge';
if(false !== val){
} else {
// iOS7.0.xでもここには入らない。
}
このようにしてif文の外で問題となる条件式を評価するようにすれば簡単に地雷回避できます。
簡単に回避できるならよかった…?
と、思いますよね。。。
しかし、Closure Compiler等を使ってソースコードをminifyしている場合には簡単には回避できないでしょう。
オリジナルコードで回避しても、minifyしたら値がif文の条件式に突っ込まれてしまうからです。さらに言えば、
元々この地雷パターンで書いていなくてもminifyしたら地雷パターンを踏んでしまう。
↓
minifyするまで気づかない!
ということもあります。むしろこのパターンが一番多いと思います。
(そもそもiOS7.0.xで検証してなくて気づかないパターンが一番多いと思いますが。。)
minify後のコードがこの地雷を踏まないようになんとかするしかありません。Closure Compilerは賢いのでちょっとやそっとオリジナルを変えただけでminify結果はなかなか変わりません。
フラグを適当なオブジェクトに持たせるとかすれば、if文条件式に突っ込まれるようなことは無くなると思いますが、そんな意味のない無駄な処理は書きたくないですよね。どうしてもダメならそうするとして、minify結果が変わるまで色々試行錯誤してコードを変えてみるのが最善かなと思います。
最後に
このバグについての情報が探しても見つからなすぎるので、ここで自分で調べたことを纏めさせていただきましたが、他にこの問題を調べた人(気づいた人)っているんですかね…。
もしそういう人を見つけた方はコメント等で教えて下されば幸いです。