最近よく目にするのが、WEBシステムの経験が浅いメンバーのJavaScriptに奮闘する姿でして。
今回は、Javaなどのオブジェクト指向で作られた言語は書いたことあるけれどJavaScriptは苦手という方向けに、JavaScriptの話をしたいと思います。
JavaScriptも扱うのはオブジェクト!
「ボタン押されたタイミングで、JavaScriptで入力値チェックして、ダメだったらアラートメッセージ出して」
これはJavaScriptで書くことあるあるですが、まず最初に立ちふさがる壁が
「入力値どうやってとるの?」ということかと思います。
まぁ調べればすぐ、document.getElementByIdに調べたいinputタグのidの値を引数に渡して、変数に戻り値代入して、その変数のvalueを使えばチェックできるぞ。等、答えは見つかります。
が、ちょっと待ってください。
document.getElementByIdを、Javaのおまじない?お約束?である、public static void main(String args[]){}と同じように、書いとけば動くおまじないと考えていませんか?
getElementByIdは引数と戻り値を持つメソッドです。
では、 documentは?
そうです。皆様?おなじみのオブジェクトです!
JavaScript が扱うのはDOM。ただしHTML != DOM
オブジェクトです!とたかだかに宣言したところで、わかりにくい。
なぜわかりにくいかといえば、HTMLを書いただけでなぜそれがオブジェクト?
え?別にクラスも作ってないし、ましてやメソッドなんて定義してないしプロパティの定義もしてない。
なんて思う方もいるかもしれません。
これを理解するには、まずHTML をブラウザがどう解釈し、画面に表示するかを知る必要があります。
ブラウザはHTMLを読み込んだ際、まずはそのHTMLをパース(構文解析)をし、
DOM(Document Object Model)というW3Cが定義した作りかたにのっとったオブジェクトを作成します。
そこで作成されたオブジェクトと、CSSで定義されたレイアウトを組み合わせて、画面に表示します。
つまり、ブラウザに表示されているのは単純なHTMLの解析結果ではなく、
HTMLを元にブラウザが作成した DOMというオブジェクトです。
まさにそのオブジェクトを使用するのが、JavaScript です。
余談ではありますが、DOMの実装やCSSの解釈については、各ブラウザに委ねられているため、同じことを書いてもブラウザ間で違うことが起こり得るんですね。
オブジェクトなのは分かったけど、どう実装されているわけ?
DOMは基本的に木構造でオブジェクトを実装しています。
木構造ってなんだ?ってなるかと思いますが、このような構造です。
document
└ html
├ head
│ └ meta
└ body
└ h1
基本情報でもありますよね。2分木とか。
木構造で作られたオブジェクトであるため、各オブジェクトのことをノードと言ったりします。
まぁ、習うより見て覚えたほうが早いので、まずは下記を記載したindex.htmlファイルを用意してください。
<!DOCTYPE html> <html> <head> <title></title> <script type="text/javascript"> window.onload = function(){console.log(window);} </script> </head> <body> </body> </html>
このJavaScriptが何をしているかというと、ウィンドウ表示時にコンソールにJavaScriptのグローバル変数であるwindowを出力しています。
このHTMLをChromeで開き開発者ツールを表示します(F12)。
そしてConsoleタブを選択すると、window変数に格納されたWindowオブジェクトが出力されているのがわかります。
windowの左横にある▶を押下すると、Windowオブジェクトの定義がみれます。
Windowの真下にあるalertメソッドはアラートメッセージを出すためによく使うwindow.alert()です。
また、画像の一番下にあるdocumentもdocument.getElementById()などで使用する Documentオブジェクトを格納しているプロパティです。
windowとdocumentはグローバル変数のため、宣言などしなくても直接使用できます。
また、JavaScriptでグローバルなメソッドや変数を定義した場合、それはWindowオブジェクトのメソッドや変数になります。
試しにこんなのを書いてみると。
<!DOCTYPE html> <html> <head> <title></title> <script type="text/javascript"> var a = "グローバル変数だよ"; // グローバル変数のテスト function aGrobalMethod(){} // グローバルメソッドのテスト window.onload = function(){console.log(window);} </script> </head> <body> </body> </html>
Consoleにはこう出力されます。
そんなことはいいから、要素取ってデザイン変えたいんだけど。
オブジェクトは木構造なので、documentからたどっていけば、要素にはたどり着けますし、そんなことをしなくても、document自体が便利なメソッドを持っています。
例えばこのようなtableの1行目だけ色を変えたいとなった場合、書き方はいくらもあります。
<!DOCTYPE html> <html> <head> <title></title> <script></script> </head> <body> <table border="1" cellspacing="0"> <tr> <th>会社名</th> <th>一言</th> </tr> <tr> <td>株式会社シベスピ</td> <td>仲間募集中!</td> </tr> </table> </body> </html>
例えばscriptタグ内にこのような記述をすると色が変わります。
window.addEventListener("load",loadEvent); function loadEvent() { // 各要素を取得 // ① docmentのプロパティであるbodyのchidrenプロパティ(配列)の1つ目を取得 var element1= document.body.children[0]; console.log(element1.tagName); // ② ①で取得したオブジェクトのchidrenプロパティ(配列)の1つ目を取得 var element2= element1.children[0]; console.log(element2.tagName); // ③ ②で取得したオブジェクトのchidrenプロパティ(配列)の1つ目を取得 var element3= element2.children[0]; console.log(element3.tagName); // 色変更 element3.style = "background:yellow" }
まぁこれも document.body.children[0].children[0].children[0].style = "background:yellow"と一行ではかけるのですが、何が取れているのかを確認するために変数で分けてます。
何が取れているかを見てみるとこうなります。
あれ、tbodyなんて書いてないけど、tbodyってでてると思った方は、JavaScriptが何を扱うのかを思い出してください。
JavaScript が扱うのは DOMなのでHTMLを元にブラウザが作成したオブジェクトです。
ブラウザが DOMを作成する際に、tbodyを追加しているんですね。
※ ちなみにこの書き方は絶対やっちゃだめです。tableの上に何かを追加しただけで、bodyのchildrenプロパティのインデックスが変わることから、htmlを修正するたびに改修しなくてはならないのでメンテナンス性低すぎます。
この場合はおとなしくtableにid振るなりしてgetElementByIdでtableとって1行目の色を変えるなり、1行目だけclass振ってgetElementsByClassNameつかうなり、そもそもこれぐらいだったらCSSでやりなよって話ですね。はい。
最後に
ここで一番言いたかったのは、JavaScriptが扱うのはHTMLではなく、DOMというオブジェクトということです。
同じようにJavaでオブジェクト散々扱っているのに、なぜ苦手なのかなぁと苦しんでいるメンバを見ながら思い、なるほど、DOMがわかっていないんだということに気が付いたので、この記事を書きました。
こういったことは、公式のドキュメントを読めばわかることですが、覚えることがほかにもたくさんある中それは大変かと思います。
なのでまずはConsoleや開発者ツールのSouceタブでデバッグするなどして、いろいろ試してみると面白いと思います。
以上、エンジニア向けJavaScript入門でした。