Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

  1. トップページ
  2. JavaScript実践編 - 超詳細解説 デジタル時計を作ってみよう(3)

超詳細解説 デジタル時計を作ってみよう(3)

みなさまどうも。続きましてデジタル時計のJS部分をバシバシ書いていきましょう。

では前の記事で用意した以下のJSを開いて下さい。『;』がポツンと置いてあるやつですね。

;

まず「冒頭にちょいと説明を置いてくれ」って事を取引先から良く言われるので以下のようにちょいと解説を置いてあげましょう。

;/*
	共通のJSはこちらへ。
	body要素の閉じタグの直前で読み込まれます。
*/

そしたらJSでオススメしたいお作法の1つとして「『即時関数』で処理ごとにラップする』というものを紹介しておきます。こんな感じになりますね。

;/*
	共通のJSはこちらへ。
	body要素の閉じタグの直前で読み込まれます。
*/

/* デジタル時計の処理 start */
(function(){
	// ここにデジタル時計の処理を書きます。
})();
/* デジタル時計の処理 end */

即時関数についてはこちらへ。

『即時関数』を使うと「グローバルの名前を全く潰さずローカルのスコープを作り出しそのまま処理を実行することができる」ってわけですので処理ごとにラップしてしまうと色々と捗ります。

あと『即時関数』にあたる『(function(){})();』に包まれた部分が大体存在しておりソースコードに法則性が生まれて読みやすくなるメリットもあるのではないかと考えております。

まあこれは好みが多少別れるとこなんで『著者はこうやっている』って感じの紹介になっちゃうかもですがご参考になれば幸いです。コメントなんかも皆様のお好きなようにして頂ければ幸いでございます。

では続いてHTML要素の確認をしていきましょう。再度確認となりますが以下のHTMLソースで

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>JS de デジタル時計</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>

<div class="js-digital_clock"></div>

<script src="./common.js"></script>
</body>
</html>

『.js-digital_clock』なdiv要素にJSでデジタル時計を組み込みするわけですのでまず『.js-digital_clock』をJSで取得する必要があります。

んでここで注意点なのですが上記の処理は『即時関数』を使っているわけですのでその名の通り問答無用で即実行される関数(処理)となっています。「関数を実行する」という部分が無いんですね。

これはどういうことかというと通常の関数を使った場合は以下のように

var f = function(){
	alert("初音ミク");
};

と書いたところでアラートが実行される事はありません。上記は関数を定義しただけの状態です。

アラートを出したい場合はこうします。

var f = function(){
	alert("初音ミク");
};

f(); // ここに注目です。ここで実行しています。

上記のように『f();』って書いてはじめて実行されるわけですね。

ではそれを比べて以下のように『即時関数』を使うとどうでしょう。

(function(){
	alert("初音ミク");
})();

もうおわかりかと思いますがこれはアラートが問答無用で実行されます。

つまり『即時関数』は『関数の定義』と『関数の実行』が同時に行われる構文という事になります。

んでこれがなーぜ注意点になるかというと以下のようなパターンをちょいと考えてみましょう。

(function(){
	var a = document.getElementById("test");

	a.innerHTML = "初音ミク";
})();

上記のやつは『#test』なHTML要素の中身を『初音ミク』に書き換えるといった簡単な処理です。

HTMLソースコードの中に『#test』なHTML要素が居れば問題ないのですがもしHTML要素が居なければどうなるかというと以下のようになります。コメントを書いてみました。

(function(){
	var a = document.getElementById("test"); // 『#test』が見つからない場合はnullとなる。

	a.innerHTML = "初音ミク"; // そうすると『null.innerHTML』という構文になってしまいエラーになる。
})();

バシッとエラーになっていますね。じゃあどうすれば良いのかというとまず以下のようなパターンが思い浮かぶと思います。

var f = function(){
	var a = document.getElementById("test");

	a.innerHTML = "初音ミク";
};

f(); // 『#test』が居るHTMLページでこれを実行させてね!じゃないとエラーになるよ!(・ω<)テヘペロ

「『#test』が居るHTMLページで関数を実行させてね!」ってパターンにしてしまった感じです。もちろんこれでも間違いでは無いのですがいちいち『f();』を書いてもらう、っていうもの少々手間だし取引先とかにも嫌がられてしまいそうですよね。

しかも上記のような処理を書く場合は「『#test』が存在していれば問答無用で中身を『初音ミク』にする」って目的のもと構築することが多いです。

なのでグローバル関数『f』と定義する必要も無かったりするんですよね。どうせ『#test』が存在していれば問答無用で実行させますし関数『f』を再度実行させることも多分ありません。

そして上記の場合は『f』という名前が使われてしまった為、今後は『f』という名前のグローバルな関数も変数も使えなくなってしまいました。意味の無いグローバル汚染っていうのはまさにこれかもでございますね。

じゃあどうするのかというとそこで登場するのがやっぱり『即時関数』になります。なのでこう書き換えましょう。

(function(){
	var a = document.getElementById("test");

	a.innerHTML = "初音ミク";
})();

しかし先程も解説した通りこの処理は即実行されてしまいます。なので『#test』が存在していれば問答無用でエラーになります。

じゃあエラーを出さないようにするにはどうするのか、というとこうします。

(function(){
	var a = document.getElementById("test");

	if(a){
		a.innerHTML = "初音ミク";
	}
})();

『if文』に注目ですね。『if文』の条件式の部分に『a』が指定されているため『a』がnullなどのfalse扱いされる値じゃ無かった場合のみ『a.innerHTML = "初音ミク";』が実行される形になります。

これで「『#test』が存在していれば実行される」という目的を達成する事が出来ましたね。グローバル汚染もしていませんしまさに完璧と言わざるを得ません。

ちょいと長々と説明してしまって申し訳ないのですが『即時関数』は他の言語と比べてもかなり珍しい構文なのでこのエスケープパターンを是非覚えて頂きたいと思います。

んでもういっちょ改正版として以下のように構築するパターンもぜひ覚えておいて下さい。

(function(){
	var a = document.getElementById("test");

	if(!a) return; // ここに注目して下さい。

	a.innerHTML = "初音ミク";
})();

これは先程のパターンと似たような感じですが『if文』の書き方に少し違いがありますね。

『if文』の条件式部分に注目してみましょう。今度は『a』じゃなくて『!a』となっています。

『!』を使うと真偽値(trueとfalse)として評価されたものを反転する事が出来ますので、つまりこの『if文』は「aがnullとかだった場合にtrueとなって実行される」という処理になります。

そんでもって『即時関数』は関数の1つなので中身の部分は全て普通の関数と同じ仕組みになっています。つまり『return』を使うとその関数内部の処理を抜ける事が出来ます。

なのでまとめると「aがnullとかだった場合にtrueとなってreturnが実行され処理を抜ける事が出来る」といった感じになりますね。

先程の『if(a){}』を使った場合と結果は同じなのですが、なーぜこのようなパターンにするかというとこういう事です。

(function(){
	var a = document.getElementById("test");

	if(a){
		// ここから先すごーく長い処理が書いてあるとします。
		// ...
		// ...
		// ...
		// ...
		// ...
		// ...
		// ...
		// ...
		// ...
		// ...
		// ...
		// ...
		// ...
		// ...
		// ...
		// ...
	}
})();

こんな感じで処理が長くなると『if文』の『{}』の入れ子状態がずっと続いちゃって少し読みづらくなりがちなんですよね。

JavaScriptはC言語の構文を蹂躙しており『{}』が沢山出てくる感じになるので「なるべく『{}』の個数を少なくしたいぜー」って方には『if(!a) return;』みたいな記法がおすすめです。

まあこれも好みによりけりなとこなんですがよく使われる『即時関数』のパターンの1つなのでぜひ覚えておいて下さい。

さてちょいと長くなったんで一旦ここで切りますね。次の記事では『.js-digital_clock』を取得するとこあたりからやっていきたいと思います。ではまたお会いしましょう。

この記事は桜舞が執筆致しました。

著者が愛する小型哺乳類

桜舞 春人 Sakurama Haruto

ISDN時代から様々なコンテンツを制作しているちょっと髪の毛が心配な東京在住のプログラマー。生粋のロングスリーパーで、10時間以上睡眠を取らないと基本的に体調が悪い。好きなだけ寝れる生活を送るのが夢。ゲームとスポーツと音楽が大好き。誰か髪の毛を分けて下さい。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。