【JavaScript】オブジェクト指向を使いこなすと、条件分岐やfor文は要らなくなる

らしいです。最低限は必要だけど、かなり減るとか。

最近、javaとかCとか、Javascriptよりもお堅いオブジェクト指向言語の記事をかじり読みしては、こうするとメンテが楽なんだなあ、とイメージしてます。キーワードは「ポリモーフィズム」「Stateパターン」「条件分岐をなくす」など。
言語が違うので、例示されてるコードはあんまり読めないんですけどね。理屈は分かる気がしてます。
 

私は、オブジェクトを使いこなすまでは至っていませんが、条件分岐とループをなくすことはできました。
というわけで、ド初心者のコードと、初心者脱出したコードを並べてみます。

(偉そうに書いてますが、完全独学の趣味レベルですのでご了承を)
(でもタイピングサイトに組み込んで動くコード(の簡略化)です。動くは正義)

スポンサーリンク

例示するコードについて

Javascriptで親指シフト入力を疑似体験できるサイトのコードです。(簡略化しています)
キーボードからの入力を元に、文字キーとシフト状態の組み合わせ表(=配列/オブジェクト)から、入力された文字を判別します。

ちなみに元のコードはこんなです。
今見ると、え?え?何やってんの? ってなります。
(ちなみに変数名も、もっと分かりにくいのが付いてたんですが、分かりにくい&恥ずかしいので直しました)

//元の配列:[通し番号] = [キーコード、シフトなし、左シフト、右シフト]
var keyMap = new Array();
keyMap[0]=[65,"う","を","ヴ"];
keyMap[1]=[66,"へ","ぃ","べ"];
keyMap[2]=[67,"す","ろ","ず"];
keyMap[3]=[68,"て","な","で"];
keyMap[4]=[69,"た","り","だ"];

//入力されたキーコードが、keyMap配列の何番目か得る
var kc=event.keyCode;
var n;
for ( n = 0; n < keyMap.length; n++){
  if( kc == keyMap[n][0] ) break;
}
if (isLeft == 0 && isRight == 0){	//親指が押されていない時
  charX = keyMap[n][1];
} else if (isLeft != isRight){	//片方の親指が押されている時
  if (isLeft == 1){
    charX = keyMap[n][2];
  } else{
    charX = keyMap[n][3];
  }
}

直します

上記のコードを、今の私の知識と感覚で直していきます。ビフォーアフターです。

for文が消えた!

まずは、入力された文字キーを、判定できる状態に準備する部分です。

★ビフォア
当初は、for文で回して、しらみつぶしに探していました。
配列において、連番の数字以外をキーに使うことを、理解できなかったんです。

//元の配列:[通し番号] = [キーコード、シフトなし、左シフト、右シフト]
var keyMap = new Array();
keyMap[0]=[65,"う","を","ヴ"];
keyMap[1]=[66,"へ","ぃ","べ"];
keyMap[2]=[67,"す","ろ","ず"];
keyMap[3]=[68,"て","な","で"];
keyMap[4]=[69,"た","り","だ"];

//入力されたキーコードが、keyMap配列の何番目か得る
var kc=event.keyCode
var n;
for ( n = 0; n < keyMap.length; n++){
  if( kc == keyMap[n][0] ) break;
}

★アフター
for文を使わず、キーで直接値を取るようにしました。
こうすることで、keyに関しては、特別な下準備が不要になりました。
コードが分かりやすくなったため、コメントも要らなくなりました。

//元の配列:実際は、もっと単純な文字列をもとに、スクリプトで生成
var kanaMap = {
  a: {noshift: "う", left: "を", right: "ヴ"},
  b: {noshift: "へ", left: "ぃ", right: "べ"},
  c: {noshift: "す", left: "ろ", right: "ず"},
  d: {noshift: "て", left: "な", right: "で"},
  e: {noshift: "た", left: "り", right: "だ"},
}

//入力されたkey
var key = event.key;

※キーコード(数字)からキー(文字列)に変えましたが、キーコード(数字)でも同じ事ができます。でも、現在キーコードは非推奨になっているので、やらない方がいいです

条件分岐が消えた!

続いて、シフト状態を元に、入力されたかなを取得する部分。

★ビフォア
左右どちらがシフトしてるか/あるいはしてないかを、一々if文で判定してます。

//続き
kc
n  //キーコードの配列要素番号

var charX;
//入力されたキーコードと、その時のシフト状態を元に文字を得る
if (isLeft == 0 && isRight == 0){	//親指が押されていない時
  charX = keyMap[n][1];
} else if (isLeft != isRight){	//片方の親指が押されている時
  if (isLeft == 1){
    charX = keyMap[n][2];
  } else{
    charX = keyMap[n][3];
  }
}

★アフター
先に、シフト状態を表す文字列を生成。
この文字列を当てはめると、一発で文字が出ます。
また、シフト状態を先に取ることで、照合中にシフト状態が万一変わっても問題ないです。(そんな事はないはずだけど)

条件に合わないときは、さっさとreturnすることも覚えました。

//続き
key

var charX;

//入力されたkeyと、その時のシフト状態を元に文字を得る
var L = thumbL_isShift;  //boolean
var R = thumbR_isShift;  //boolean
if(L && R) return;
var shift = L? "left": R? "right": "noshift";

var charX = kanaMap[key][shift];

ちなみにここも、シフト状態を”noshift””left””right”の3スイッチにできれば、直接値を突っ込むだけで済みます。
が、左右のシフトは独立してon/offするので、ちょっと難しいと思いました。

直したコードの全容

スッキリしたし、for文がなくなった分、動作(速度)も安定しました。

var kanaMap = {
  a: {noshift: "う", left: "を", right: "ヴ"},
  b: {noshift: "へ", left: "ぃ", right: "べ"},
  c: {noshift: "す", left: "ろ", right: "ず"},
  d: {noshift: "て", left: "な", right: "で"},
  e: {noshift: "た", left: "り", right: "だ"},
}

//入力されたkeyと、その時のシフト状態を元に文字を得る
var key = event.key;

var L = thumbL_isShift;
var R = thumbR_isShift;
if(L && R) return;
var shift = L? "left": R? "right": "noshift";
var charX = kanaMap[key][shift];

どこかで分岐はしている

以上、見ていて思ったかもしれませんが、全く分岐がなくなったわけではないです。
オブジェクトのプロパティにうまいキー名を付けたり、変数の下処理をしたり、とどこかで分岐する準備をしています。

そうすると、動作の中心となるコードでは、ごくシンプルに記述できます。
追加や変更にも対応しやすくなります。

うまくすると、変更があったときに肝のコードは全く変えず、オブジェクトを変えるだけですむらしいです。
うちのサイトはそこまで出来てないですが。

ゆくゆくは、もっと扱いやすいコードを書きたいものです。
終わります。

コメント

スポンサーリンク