おみくじプログラムのコードを分かりやすくしてみた


# <i class="fa fa-check-circle-o"></i> newとコンストラクタ関数で書き直し

@chocolamintさんのフィードバックから、コードを書き直してみた。

```html:html
<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <title>おみくじ</title>
</head>

<body>
  <h1>おみくじ</h1>
  <input type="button" value="あなたの運勢は？" id="jsButtom">
  <p>あなたの運勢は...
    <img id="jsResultImage"></img>
    <p>文字にすると&nbsp;<span id="jsResultComment"></span></p>
    <p>ラッキーアイテムは&nbsp;<span id="jsResultItem"></span></p>
  </p>
  <script src="js/version7.js" async defer></script>
</body>

</html>
```

```JavaScript:JavaScript
var jsButtom = document.getElementById('jsButtom'); //ボタンをIDでgetしてキャッシュ
var imgFolder = "img/"; //フォルダパスをキャッシュ
var fileExtension = ".png"; //ファイル拡張子をキャッシュ

jsButtom.onclick = function() { //ボタンがonclickされた時に起きる処理
  var omikujiList = [
    new Omikuji("daikichi", "大吉でした", "大斧！"),
    new Omikuji("chukichi", "中吉でした", "中華包丁！"),
    new Omikuji("shokichi", "小吉でした", "小麦粉！"),
    new Omikuji("suekichi", "末吉でした", "末広がりな８！"),
    new Omikuji("kyo", "凶でした。。。", "凶器はダメです")
  ];

  function Omikuji(fileName, comment, item) {
    this.fileName = fileName;
    this.comment = comment;
    this.item = item;
  }

  var result = Math.floor(Math.random() * omikujiList.length);

  var omikuji = omikujiList[result];

  document.getElementById('jsResultImage').src = imgFolder + omikuji.fileName + fileExtension;
  document.getElementById('jsResultComment').innerHTML = omikuji.comment;
  document.getElementById('jsResultItem').innerHTML = omikuji.item;
};
```

# <i class="fa fa-check-circle-o"></i> 解釈
上から順に、コードの意味を書く。

## <i class="fa fa-check-square-o"></i> 1. newでオブジェクトを作成

```js
var omikujiList = [
  new Omikuji("daikichi", "大吉でした", "大斧！"),
  new Omikuji("chukichi", "中吉でした", "中華包丁！"),
  new Omikuji("shokichi", "小吉でした", "小麦粉！"),
  new Omikuji("suekichi", "末吉でした", "末広がりな８！"),
  new Omikuji("kyo", "凶でした。。。", "凶器はダメです")
];
```
`omikujiList`のなかに、`new Omikuji`で大吉〜凶の結果を作る。
※ 「オブジェクト」という言葉の使い方はあっているのか？

## <i class="fa fa-check-square-o"></i> 2. プロパティ名を振る
```js
function Omikuji(fileName, comment, item) {
  this.fileName = fileName;
  this.comment = comment;
  this.item = item;
}
```
`Omikuji`オブジェクトの配列にプロパティ名を振る。
※ 「配列」「プロパティ名」という言葉はあっているのか？

## <i class="fa fa-check-square-o"></i> 3. 乱数生成
```js
var result = Math.floor(Math.random() * omikujiList.length);
```
`result`変数に乱数生成を代入する。
この時、`omikujiList`の中にある配列の長さを`length`で数えて、その中で乱数を生成するようにする。
この辺は[ドットインストール - JavaScriptで作る「簡単おみくじ」](http://dotinstall.com/lessons/omikuji_js)と同じ。

## <i class="fa fa-check-square-o"></i> 4. 変数に結果を代入する
```js
var omikuji = omikujiList[result];
```
`omikuji`変数に`omikujiList[result]`でランダムに選んだ`Omikuji`プロパティを代入する。

## <i class="fa fa-check-square-o"></i> 5. 結果を表示させる
```js
document.getElementById('jsResultImage').src = imgFolder + omikuji.fileName + fileExtension;
document.getElementById('jsResultComment').innerHTML = omikuji.comment;
document.getElementById('jsResultItem').innerHTML = omikuji.item;
```
画像のsrcを`imgFolder`と`omikuji.fileName`と`fileExtension`から参照して表示する。
結果に対応したコメントを`omikuji.comment`で参照して表示する。
結果に対応したラッキーアイテムを`omikuji.item`で参照して表示する。

ここで大事なのが、`omikuji.`以降のプロパティの使い方。

# <i class="fa fa-check-circle-o"></i> 結果表示のプログラムの流れ
結果表示が`omikuji.fileName`などでどういう流れで表示されるか考えてみた。

----

`omikuji`の変数を探す。

<i class="fa fa-arrow-down"></i>

`var omikuji = omikujiList[result]`から、`omikuji`は`omikujiList`の中から`result`を使ってランダムに選ばれたものが入っていることが分かる。

<i class="fa fa-arrow-down"></i>

`omikuji`には、今回は`new Omikuji("daikichi", "大吉でした", "大斧！")`が代入されていたとする。

<i class="fa fa-arrow-down"></i>

次に、語尾の`.fileName`はなにかを`new Omikuji("daikichi", "大吉でした", "大斧！")`の中から探す。

<i class="fa fa-arrow-down"></i>

```js
function Omikuji(fileName, comment, item) {
  this.fileName = fileName;
  this.comment = comment;
  this.item = item;
}
```

で、`Omikuji`オブジェクトの中は`new Omikuji("fileName", "comment", "item")`と名前が振られている。

<i class="fa fa-arrow-down"></i>

`fileName`は、`Omikuji`の中の一番左（jsだと0番目）にある`daikichi`だと分かる。

----

# <i class="fa fa-check-circle-o"></i> thisの指すもの
`this`が出てきた。
`this`はなにを指すのか。

```js
function Omikuji(fileName, comment, item) {
  this.fileName = fileName;
  this.comment = comment;
  this.item = item;
}
```

`this`は自分自身を指すような意味で、この場合`Omikuji`を指している。
なので、 __大吉__ であった場合、`Omikuji("daikichi", "大吉でした", "大斧！")`を指している。
# <i class="fa fa-check-circle-o"></i> 書きなおした利点
前回は

```js
var omikujiFileName = ["daikichi", "chukichi", "shokichi", "suekichi", "kyo"];
var omikujiComment = ["大吉でした", "中吉でした", "小吉でした", "末吉でした", "凶でした。。。"];
var omikujiItem = ["大斧！", "中華包丁！", "小麦粉！", "末広がりな８！", "凶器はダメです"];
```

などと、欲しい結果に対してそれぞれ変数を作って、その中から`result`で結果をランダムに取り出していた。

今回は`omikujiList`の中に`Omikuji`オブジェクトとしてまとめ、たとえば __大吉__ であった場合の、対応する他の結果を分かりやすく書けるようになった。

# <i class="fa fa-check-circle-o"></i> 他の書き方
```js
var omikujiList = [
    { fileName: "daikichi", comment: "大吉でした", item: "大斧！" },
    { fileName: "chukichi", comment: "中吉でした", item: "中華包丁！" },
    { fileName: "shokichi", comment: "小吉でした", item: "小麦粉！" }
    // 面倒なのであと2つは省略
];
var omikuji = omikujiList[result];
```
でも良いが、
> また、上のコードだと各おみくじでプロパティ名がきちんと同じかどうかの保証がされないので、コンストラクタ関数を使って以下のようにもできます。

とあるように、ミスを防ぐためにもプロパティ名はいっぺんに振った方が良いことが分かった。

# <i class="fa fa-check-circle-o"></i> 総評
結果の要素を増やしたことで、それぞれの要素の連動と、結果の管理がネックになりそうだと思いついて書き直したことがはじまり。
今回できたコードで、感覚で感じた違和感はクリアになった！

また、よく分かってはいないけど結果内容を他の場所（MySQLとかJSONとか？）にした時にも応用が効く気がしている。

# <i class="fa fa-check-circle-o"></i> 次は
クッキーを使って前の結果をキャッシュとか、カレンダーをつけるとか言ってた。
しかし、本質から脱線して新しいことをやろうとしている気がするので、おとなしくもう少しこのコードを掘り下げよう！