そのJavaScriptちょっと待った~




■JavaScriptでページを書き換えようとしたらエラーになる???

皆さんこんにちは、プロクラスの野間です。
今日は最近気になっている「JavaScriptの書き方」についてお話ししたいと思います。
なんだか「JavaScriptはHTMLの下の方に記述すべし」みたいな説明をしている紹介がありますが、プログラム的にはあまりよろしくない書き方だなぁってお話です。
下に書くことがダメなのではなく、理由?に問題ありなので、ちょっとお付き合いください。

■HTMLの下の方にJavaScriptを記述している理由

JavaScriptの多くは状況によって「HTMLを書き換える」ことに良く使われます。
例えば・・・
——————————————————————————–
——————————————————————————–
<html>
<head>
</head>
<body>
<input type=”text” id=”inp”>
</body>
</html>
——————————————————————————–
こんな感じで、<input>に自動で値を入れたいな~って感じに使うとします。
(「最初から入れとけよ」は気にしないでください。あくまでサンプルです)
この際、JavaScriptでは「HTMLの管理に対して<input>ちょ~だい」とお願いして<input>をもらって、それを書き換えます。
具体的には「document.getElementById(“inp”)」で取得できます。
これは「idがinpのものをちょうだい」って命令です。
よく見ると<input>に id=”inp” と書いてありますね。だからこれで<input>がもらえます。
ちょっとHTMLの上部に初期値を入れるプログラムを書き足してみます。
——————————————————————————–
<html>
<head>
<script type=”text/javascript”>
    document.getElementById(“inp”).value = “Sample Text”;
</script>
</head>
<body>
<input type=”text” id=”inp“>
</body>
</html>
——————————————————————————–
ここでHTML独自の問題が発生します。
ブラウザのエラーを確認して見ると・・・
何やらエラーが出ているようです。
HTMLはインターネットから通信で取得しますが、必ずしも1度の通信で全てを取得できるとは限りません。
となると、例えば次のようなタイミングが存在する「かも」しれません。
——————————————————————————–
<html>
<head>
<script type=”text/javascript”>
    document.getElementById(“inp”).value = “Sample Text”;
</script>
</hea・・・ここから後ろはまだ読み込んでいる途中・・・
——————————————————————————–
まだ読み込んでいる途中なのですが、どうやら読み込んだところから処理されるようなのです。
ですので、このタイミングでプログラムが動いたとすると、
「idがinpのものをちょうだい」と言っても、まだ相手は読み込まれていませんので「無い」ですよね?
となるとエラーになってしまうわけです。
(「そんなもんないよ」と言われてしまいます)
まぁ、当然ですよね。
エラーの原因を文章にすると・・・
「まだ読み込まれていないHTMLの値にアクセスしようとした」となります。
って事はその対処として「じゃぁアクセスする相手が読み込まれていたら良いんだよね」って事で「JavaScriptがHTMLの下の方に書いてあれば解決!」と考えたのだと思われます。

——————————————————————————–
今度はエラーなく表示されているようです

——————————————————————————–

<html>
<head>
</head>
<body>
<input type=”text” id=”inp“>
<script type=”text/javascript”>
    document.getElementById(“inp”).value = “Sample Text”;
</script>
</body>
</html>
——————————————————————————–
こう書いてあれば、JavaScriptが動くときには必ず<input>は存在します。
確かにその通りなのですが・・・ちょっとお行儀の悪いプログラムに感じます。
仕事でプログラムを組んでいると、仕方なくシステムの穴を突くような行儀の悪いプログラムを組むこともありますが、それはあくまで最後の手段であって最初にとる手段ではありません。
じゃぁお行儀の良いプログラムってどうするの?って事ですが・・・
根本原因に対処します。
「まだ読み込まれていないHTMLの値にアクセスしようとした」
に対して、タイミングよく「先に読み込まれているように書く」ではなく、「全部読み込まれてからJavaScriptが動くようにする」がお行儀の良いプログラムになります。
だって本来そうなってほしいんですよね?
何故これが行儀の良いプログラムになるかと言うと、JavaScriptにはこのための仕組み(全部読み込まれてからJavaScriptが動く)があるからです。
用意してあるってことは「これ使えよ?」って事ですよね。
全部読み込んでから動くのであれば、HTMLのどこに書いてあっても良いことがわかります。
じゃぁどうすれば良いのかと言うと、(同じものですが)書き方は何種類か存在します。
恐らくもっとも単純なものは次のようになります。
——————————————————————————–
<html>
<head>
<script type=”text/javascript”>
    function onloadFunc() {
        document.getElementById(“inp”).value = “Sample Text”;
    }
</script>
</head>
<body onload=”onloadFunc()”>
<input type=”text” id=”inp”>
</body>
</html>
——————————————————————————–
ポイントは2つ
①処理を関数にする
②「読み込み完了時に」関数を呼び出す
です。
HTMLを見ると、
①JavaScriptが「function onloadFunc(){}」の中に書いてあります。
この function が「関数」です。そして「onload」が関数名です。(名前で識別します)
この関数は誰かが「呼び出さないと処理が動きません」。
書いてあるだけでは処理が動かないのです。
つまり、「読み込まれたから」と言って「処理が動き出すことがない」のです。
じゃぁ誰が呼び出しているのかと言えば、<body>タグに書かれている「onload」になります。
この「onload」は名前の通り、「読み終わった時」に指定されているものを呼び出すようになっています。
ここでは「onloadFunc()」となっていますので、「読み終わった時」に「onloadFunc()を動かす」って指示になります。
onloadFunc() の中身は{}の中に書かれているプログラムになります。
※何行書いてもOKです。
※「onloadFunc」は適当に付けた好きな名前でOKです。(意味が分かる名前にしましょう)
この手法には1つわかりやすい欠点があります。
それは「読み込み完了時に処理される関数が1つしかない」点です。
<body>タグに直接「読み込みが終わったら●●実行ね」と書きますので1つしか書けません。
(複数書けそうな気もしますが割愛します)
自分一人で作成する場合は1つの関数で困る事は無いですが、複数人で開発する場合は非常に困ります。
他の人が使っていたら自分は独自で使えない(一緒の関数を複数人で書き換える必要が出てくる)。
外部スクリプトにして使う場合、取り合いになる。
等、色々作ると不便が出てきます。(使用するのに条件が出てくる)
ですので、汎用的に作る場合は次の手法を取っておくと良いでしょう。
所謂、万能型ですね。
——————————————————————————–
<html>
<head>
<script type=”text/javascript”>
    window.addEventListener(“load”, onloadFunc);
    function onloadFunc() {
        document.getElementById(“inp”).value = “Sample Text”;
    }
</script>
</head>
<body>
<input type=”text” id=”inp”>
</body>
</html>
——————————————————————————–
御覧の通り<body>タグは何もしていません。
やらないといけない事は何も変わっていません。
①処理を関数にする
②「読み込み完了時に」関数を呼び出す
①はそのまま残っています。
これは②の方法を変更しました。
ここでのポイントは
window.addEventListener(“load”, onloadFunc);
になります。
「addEventListener」は「●の時〇を実行する」と処理を予約する時に使います。
良く使うのは「クリックされた時」とかですね。
「●の時」は「”load”」なので「ロードされた時」になります。(流石に種類は決まっています)
そして「〇を実行する」は「onloadFunc」と書いてあるので、纏めると
「ロードされた時onloadFuncを実行する」となります。
これは「幾つ登録」しても「それぞれを実行」してくれますので「他の人が使ってないか?」等を気にする事なく使えます。
JavaScriptを外部ファイルとして独立して作成する場合に非常に重宝します。
皆さんも上手に使っていってください。