Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

newとコンストラクタ関数で書き直し

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

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
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", "末吉でした", "末広がりな8!"),
    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;
};

解釈

上から順に、コードの意味を書く。

1. newでオブジェクトを作成

var omikujiList = [
  new Omikuji("daikichi", "大吉でした", "大斧!"),
  new Omikuji("chukichi", "中吉でした", "中華包丁!"),
  new Omikuji("shokichi", "小吉でした", "小麦粉!"),
  new Omikuji("suekichi", "末吉でした", "末広がりな8!"),
  new Omikuji("kyo", "凶でした。。。", "凶器はダメです")
];

omikujiListのなかに、new Omikujiで大吉〜凶の結果を作る。
※ 「オブジェクト」という言葉の使い方はあっているのか?

2. プロパティ名を振る

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

Omikujiオブジェクトの配列にプロパティ名を振る。
※ 「配列」「プロパティ名」という言葉はあっているのか?

3. 乱数生成

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

result変数に乱数生成を代入する。
この時、omikujiListの中にある配列の長さをlengthで数えて、その中で乱数を生成するようにする。
この辺はドットインストール - JavaScriptで作る「簡単おみくじ」と同じ。

4. 変数に結果を代入する

var omikuji = omikujiList[result];

omikuji変数にomikujiList[result]でランダムに選んだOmikujiプロパティを代入する。

5. 結果を表示させる

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

画像のsrcをimgFolderomikuji.fileNamefileExtensionから参照して表示する。
結果に対応したコメントをomikuji.commentで参照して表示する。
結果に対応したラッキーアイテムをomikuji.itemで参照して表示する。

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

結果表示のプログラムの流れ

結果表示がomikuji.fileNameなどでどういう流れで表示されるか考えてみた。


omikujiの変数を探す。

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

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

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

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

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

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


thisの指すもの

thisが出てきた。
thisはなにを指すのか。

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

thisは自分自身を指すような意味で、この場合Omikujiを指している。
なので、 大吉 であった場合、Omikuji("daikichi", "大吉でした", "大斧!")を指している。

書きなおした利点

前回は

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

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

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

他の書き方

var omikujiList = [
    { fileName: "daikichi", comment: "大吉でした", item: "大斧!" },
    { fileName: "chukichi", comment: "中吉でした", item: "中華包丁!" },
    { fileName: "shokichi", comment: "小吉でした", item: "小麦粉!" }
    // 面倒なのであと2つは省略
];
var omikuji = omikujiList[result];

でも良いが、

また、上のコードだと各おみくじでプロパティ名がきちんと同じかどうかの保証がされないので、コンストラクタ関数を使って以下のようにもできます。

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

総評

結果の要素を増やしたことで、それぞれの要素の連動と、結果の管理がネックになりそうだと思いついて書き直したことがはじまり。
今回できたコードで、感覚で感じた違和感はクリアになった!

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

次は

クッキーを使って前の結果をキャッシュとか、カレンダーをつけるとか言ってた。
しかし、本質から脱線して新しいことをやろうとしている気がするので、おとなしくもう少しこのコードを掘り下げよう!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away