読めないコード
※Reactを学習したい人は「Reactチュートリアル」で学習してみてください。このブログはこのチュートリアルで感じたことや自分のメモを記述していきます。
前回、勝者判定のコードが読めずに終了してしまった。今回はこのコードをじっくりと見ていきたい。いやー、もはやReactの学習というよりJavaScriptの学習になってしまったが、さすがに読めないではすませれない。
この関数を呼び出すと勝者がいる場合はその記号(O or X)、いない場合はnullが返ってくる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
function calculateWinner(squares) { const lines = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6], ]; for (let i = 0; i < lines.length; i++) { const [a, b, c] = lines[i]; if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) { return squares[a]; } } return null; } |
配列データ
まず二次元配列のlinesだがこれは1行の数値(例:0,1,2)がそれぞれマス目に対応する。これらに同じ記号は入っていたなら勝利とするためのデータだ。
かなり力技のやり方だがチュートリアルでかつ三目並べなら妥当なのだろう。これが十目並べならやってられない。
転送命令
次に13行目のコードだ。見慣れない感じだ。
13 |
const [a, b, c] = lines[i]; |
前後のソースから推測すると配列linesの1行の数値を変数a、b、cに代入しているようだ。こんな書き方ができるんだ・・・。
なぞのコード
さて本命は次のコードだ。
14 |
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) { |
どーも論理積「&&」は左右がtrueの時にtrueを返すと思っていたが違うようだ。JavaScriptのドキュメントを読んでみる。
「論理 AND(&&) expr1 && expr2 expr1 を false と見ることができる場合は、expr1 を返します。そうでない場合は、expr2 を返します。したがって、真偽値と共に使われた場合、 演算対象の両方が true ならば、&& は、true を返し、そうでなければ、false を返します。」
うーん…よくわからない。こうなればチェック用のプログラムを作り試すしかない。変数a,bにO、X、nullを設定し全組合せa&&bを行ってみた。
a | b | a&&b |
---|---|---|
O | O | O |
O | X | X |
O | null | null |
X | O | O |
X | X | X |
X | null | null |
null | O | null |
null | X | null |
null | null | null |
なるほど左側(a)がfalseと判断される場合は左側の値が返ってきて、それ以外は右側の値が返ってくるようだ。
もうひとつ大きな勘違いをしていた。判断の優先度だ。「===(型まで含めて等価か判断)」より&&の方が優先度が高いと思っていたが、逆で「===」の方が優先度が高いらしい。これから次の順番で判断される。
論理積(&&)と判断の優先度を整理できた。あらためて見ると、このif文で3つのマス目が同じ記号の時に真になるようだ。しかし、それでもわかりにくいなぁ、という感想だ。自分が記述すると、こんな感じだ。
1 |
if ( (squares[a] != null) && (squares[a] === squares[b]) && (squares[a] === squares[c]) ){ |
でもチュートリアルのif文と比較すると判断が1回多くなるので、効率的とはいえないようだ。まぁここは読めるようになったので良しとしよう。