第1章 JavaScript導入ガイド

JavaScriptの基礎

2009年8月4日

文と式

プログラミング言語でのは命令を実行する単位です。後の章で紹介する if 文、for 文、while 文、ブロックといったものが文になります。は論理式や代入式など値を返すもので、主に文の一部として使われます。

// 代入式
var v = 1;
// if文
if ( v == 1 ){
console.log(v);
}

文はセミコロン( ; )によって区切られ、上から順番に処理されます。上記の例では、代入式、if 文の順番に処理されます。
if 文のかっこで囲まれた v == 1 は、v の値が 1 であれば true という値を返します。値を返すので、この部分は式になります。== は比較演算子、true は真偽値と呼ばれるもので、あとの章で詳しく説明します。

文の区切り

JavaScriptの文はセミコロン( ; )によって区切られます。

console.log("test");

セミコロンで区切れば、1行に複数の文を記述できます。

a = 1; b = 2; 

1行に1文しか記述しない時はセミコロンを省略できますが、明示的に終了のセミコロンを入れことをおすすめします。

ステートメントは単一行に記述することがほとんどですが、複数行に記述することもできます。

console.log(
"There is nothing either good or bad, but thinking makes it so."
);
var text =
"A fool thinks himself to be wise, but a wise man knows himself to be a fool.";

長い文になる際などに有効です。

コード行の分割

文字列を複数行にしたい場合、バックスラッシュ( \ )を末尾に追加します。バックスラッシュ( \ )の後は改行以外の文字があると構文エラーになります。

console.log("Hello \
World!");
Hello World!

コメントアウト

コメントアウトとは、命令文として解釈されたくない行、文字を無効化することです。JavaScript には一行コメントアウトと複数行コメントアウトの2種類が用意されています。

一行コメントアウト

一行コメントアウトは、コメントアウトしたい文字の前にスラッシュ2つ( // )を挿入します。次の行はコメントアウトされているので、実行されません。

// console.log("test");

命令文の後にコメントアウトを追加することもできます。
次の行はセミコロンまでの命令文が実行され、// 以降の文字列はコメントアウトとして扱われます。

console.log("test"); // コメント

複数行コメントアウト

複数行のコメントは /* で始まり */ で終ります。

/*
console.log("test");
*/

複数行コメント内に複数行コメントがあると、構文エラーが発生するので注意してください。埋め込まれた複数行コメントの終わりを示す */ が、複数行コメント全体の終わりとして解釈されてしまうからです。

/*
console.log("hello");
/*console.log("world");*/
*/

ブラウザの機能

ブラウザはユーザのリクエスト(要求)をサーバに送信し、サーバが返すレスポンス(応答)を解析してWebページとして表示します。

ブラウザを構成する主な要素としてユーザ・インタフェース(UI)レイヤー、ネットワークレイヤー、レンダリングエンジン、JavaScriptエンジンがあります。この4つのコンポーネント(部品)の役割をみてみましょう。

ユーザ・インタフェース(UI)
ユーザ・インタフェース(UI)は、主にプログラムとユーザとの間を取り持ち、ユーザの指示をプログラムに伝え、プログラムから出力結果を返します。操作性、快適性といったユーザビリティに大きな影響を与えます。
コンポーネント(部品) 説明
ユーザ・インタフェース(UI)レイヤー アドレスバーや戻る・進むボタン、メニューなどのインタフェースです。
ネットワークレイヤー サーバと通信してリソース(資源)をダウンロードし、レンダリングエンジンに渡します。
レンダリングエンジン HTMLやCSSの構文を解析し、DOM要素に変換、コンテンツを表示します。解析中にSCRIPTタグがあった場合、JavaScriptインタプリタに渡します。
JavaScriptエンジン JavaScriptを解析し、実行します。
DOM
DOM(Document Object Model)はHTMLドキュメントを操作するためのAPIです。DOMではHTMLドキュメントの構造をツリー状の集合として扱います。

ブラウザのコンポーネントはそれぞれ連携しながら、リソースの要求からレンダリングまでの処理を行っていきます。その処理の流れを少し詳しく追っていきましょう。
ブラウザはユーザからリクエストを受けると、HTTP/HTTPSプロトコルを使ってサーバにHTMLファイルや画像などのリソースを要求します。サーバ側は指定されたリソースを取得し、ブラウザに送信します。

ネットワークレイヤーはサーバから受け取ったリソースをレンダリングエンジンに渡します。レンダリングエンジンはHTMLドキュメントの上から順番に解析し、DOMノードで構成されたレンダーツリーを作成します。レンダーツリーを使ってレイアウト処理に進むと、各ノードに座標が割り当てられ、線画されます。

ここまでの処理は段階的に行われるのではなく、ある程度解析が済むとその分を線画し、さらに解析、線画が逐次的に繰り返されます。こうすることにより、白い何もない画面が表示される時間を最小にし、ユーザの体感速度を高めることができます。

次に、JavaScriptの解析と実行を追ってみましょう。レンダリングエンジンはHTMLの解析時にSCRIPTタグに到達すると、SRC属性がなければJavaScriptエンジンにSCRIPTタグ内のコードを渡します。SRC属性に値がある場合はネットワークレイヤにダウンロードの指示を渡し、読み終えたリソースはJavaScriptエンジンに渡されます。このとき、通常はリソースのダウンロードが終わりJavaScriptが解析されるまで、HTMLの解析は一時的に停止されます。

後述しますが、SCRIPTタグの属性指定でJavaScriptの解析とHTMLの解析を並行して進めさせる事ができます。

SCRIPTタグ

HTMLにJavaScriptのスクリプトを記述するには、SCRIPTタグを使います。SCRIPTタグはスクリプトを記述したり、外部スクリプトファイルを読み込んで実行することができます。

SCRIPT要素内にスクリプトを記述する例
<script>
// ここにスクリプトを記述する
console.log( 1 );
</script>
外部スクリプトを読み込む例
<script src="js/main.js"></script>

SCRIPTタグの属性

SCRIPTタグの属性のほとんどは外部スクリプトを読み込む際に使います。

SRC
外部スクリプトのURIを指定し、実行します。
ASYNC
この属性を指定すると、非同期でスクリプトを読み込み、実行します。非同期のため、ページのレンダリングは中断することなく進められます。
ASYNC指定のあるSCRIPTタグが複数ある場合、タグを書いた順番に関係なく読み込みが終了したものから実行されます。

ASYNCを指定する例
<script src="外部スクリプトのURL" async></script>
DEFER
この属性を指定すると、非同期でスクリプトを読み込みます。スクリプトの実行はHTMLの解析終了後です。
DEFER指定のあるSCRIPTタグが複数ある場合、タグを書いた順番に実行されます。

DEFERを指定する例
<script src="外部スクリプトのURL" defer></script>
CHARSET
CHARSET属性は、外部スクリプトファイルの文字コードを指定する際に使用します。
指定しなくてもほとんど問題ありませんが、呼び出し元のHTMLファイルと外部JavaScriptファイルで文字コードが違う場合にはエラーの原因となることがあります。その際は外部JavaScriptファイルの文字コード指定が必要になります。

CHARSETを指定する例
<script src="***" charset="UTF-8">

SCRIPTタグを記述

SCRIPT タグは JavaScript のコードを直接記述したり、外部のJavaScriptファイルを読み込むようにURLを指定することもできます。それでは早速、JavaScriptを実行するHTMLを作成してみましょう。HTMLを保存したら、ブラウザで表示確認してみてください。「Hello world」という文字が表示されれば成功です。

BODY要素内にJavaScriptを宣言する方法
<html>
<body>
<script>
document.write("Hello world");
</script>
</body>
</html>

複数の SCRIPTタグを記述

SCRIPT タグは書かれている順番に実行されます。変数も SCRIPT タグ内にとどまらず、別の SCRIPT タグからも参照可能です。

1つ目の SCRIPT タグで変数 x の値を設定し、2つ目の SCRIPT タグから変数 x を参照しています。変数は SCRIPT タグを超えて参照可能なので、document.write() により変数 x の値の 10 がブラウザに表示されます。

<html>
<body>
<script>
var x = 10;
</script>
<script>
document.write( x );
</script>
</body>
</html>

外部スクリプトファイル

SCRIPTタグは外部のJavaScriptファイルを読み込むこともできます。外部スクリプトを読み込む場合は SRC 属性を使ってファイルの URL を指定します。

これから、外部 JavaScript ファイルを作成し、SCRIPTタグからそのファイルを指定するまでの手順を説明します。まず、拡張子が .js のファイルを作成し、そのファイルにスクリプトを記述します。外部ファイルに記述する場合は SCRIPT タグで囲む必要はありません。
ここでは、ファイル名を print_msg.js とします。

function printMsg() {
alert("Hello!");
}

外部ファイルは SCRIPT タグの SRC 属性にファイルの URL を指定することで読み込むことができます。
下記の HTML ファイルを作成し、ブラウザで表示してみてください。HTML ファイルと同階層にprint_msg.jsファイルがあれば、アラートが表示されるはずです。

<html>
<body>
<script src="print_msg.js"></script>
<input type="button" value="OK" onclick="printMsg()">
</body>
</html>

スクリプトの実行のタイミング

外部スクリプトファイルを読み込んだ場合、読み込まれたその行に記述されたのと同じように処理されます。
たとえば下記のように複数の外部スクリプトファイルを指定した場合、先に書いたfile1.jsが先に実行されることが保証されます。

<script src="file1.js"></script>
<script src="file2.js"></script>

これは外部スクリプトファイル、インライン(テキスト内)のスクリプトを問いません。

ブラウザが HTML の上から順番に解析していく際、SCRIPT タグで外部ファイルが指定されていれば、レンダリングを中断し、指定されたファイルを読み込みます。そのため、HEAD 要素内で外部スクリプトの指定があった場合、何もレンダリングされていない状態で処理がストップしてしまい、ユーザはしばらく白い画面を見ることになります。その上、JavaScript の実行はレンダリングより優先されるわけでもありません。
ユーザの体感速度を高めることを考えると、外部スクリプトファイルを読み込む SCRIPT タグは、HEAD 要素内ではなく、閉じ BODY タグの上に置いたほうが良いでしょう。

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

JavaScript の読み込みは、SCRIPT タグの属性を使ってHTMLの解析と並行して進めることができます。たとえば、SCRIPT タグの ASYNC 属性や DEFER 属性を使った場合、外部スクリプトは非同期に読み込まれることになります。次の例では、ASYNC 属性が指定してあるため、HTML の解析と平行して console_log01.js と console_log02.js が読み込まれます。console_log01.js が先に記述されていますが、実行されるタイミングは先になるか後になるかはわかりません。console_log01.js が実行されると 01 、console_log02.js が実行されると 02 がコンソールに出力されます。
何度も再読込すると、console_log01.jsが先に実行されたり、console_log02.jsが先に実行されたりすることがわかると思います。

async.html
<html>
<body>
<script src="console_log01.js" async></script>
<script src="console_log02.js" async></script>
</body>
</html>
console_log01.js
console.log("01");
console_log02.js
console.log("02");

DEFER 属性を使った場合、非同期で読み込まれつつ、書いた順番通りに実行されます。defer.html を作成し、console_log01.js と console_log02.js を読み込むように SCRIPT タグを記述します。 async.html と違う点は、ASYNC属性の代わりに DEFER 属性を指定している点です。これで console_log01.js と console_log02.js は非同期で読み込まれ、記載した順番通りに実行されます。
defer.html を作成したら、ブラウザで読み込んでみてください。何度再読込しても、console_log01.jsが先に実行され出力結果は 01、02 の順番になります。

defer.html
<html>
<body>
<script src="console_log01.js" defer></script>
<script src="console_log02.js" defer></script>
</body>
</html>

非同期で読み込みつつ、順番関係なくなるべく早く実行したい場合は ASYNC 属性、順番通りに実行したい場合は DEFER 属性を使うと良いでしょう。

HTML5.0での簡略化

HTML5.0では様々な記述が簡素化されています。JavaSciptも例外ではなく、ここで紹介する書き方はHTML5.0で使うには不適切で、古いブラウザ向けとなっています。 今後使う機会は少ないと思いますが、まだHTML5.0に対応していないサイトが多くあるので、知識として知っておいた方が良いでしょう。

TYPE属性

HTML5以前ではTYPE属性が必須属性として定義されました。値には text/javascript を指定します。

<script type="text/javascript">
document.write("Welcome to Smart!!");
</script>

HTML5.0ではTYPE属性の初期値がtext/javascriptですので、JavaScriptの場合は属性の指定は不要になりました。

<script>
document.write("Welcome to Smart!!");
</script>

JavaScriptに対応していないブラウザ

JavaScriptに対応していないブラウザでJavaScriptのスクリプトファイルを読み込むと、SCRIPT要素の中身が画面に表示されてしまいます。
この問題を回避するために、スクリプト部分をHTMLコメント内に記述しておくことが出来ます。これで、JavaScriptに対応しているブラウザは通常通りスクリプトが実行され、JavaScriptに対応してないブラウザはコメントアウトとして処理します。

<script>
<!---コメントの始まり
document.write("Hello,JavaScript!!")
コメントの終わり //--->
</script>

Content-Script-Type

スクリプトの言語を指定するため、HTML5以前では、HTMLのヘッダ部に、下記のようなMETA記述を行うことを推奨していました。
HTML5.0では不要です。

<html>
<head>
<meta http-equiv="Content-Script-Type" content="text/javascript">
</head>
<body>
<input type="button" value="OK" onclick="~">
</body>
</html>

Comment

コメントを残す

メールアドレスが公開されることはありません。

関連記事

リズムファクトリーはホームページの制作会社です。
ホームページ制作に関するご要望・ご相談はこちらからどうぞ。