HTML Living Standard  第3部 Javascript 1 Javascript とは


 

1 Javascript とは

Javascript について説明します。

1.1  Javascript とは

Javascript はいろいろなブラウザで動作する、オブジェクト指向のスクリプト言語です。ブラウザ内では、HTML 要素に Javascript を結びつけ、それらを制御することができます。Javascript には、Array、Date、そして Math といったオブジェクトからなる基本的なライブラリ、そして演算子、制御構造、文といったプログラミング言語の要素からなる主要な機能が含まれています。

Javascript は Java といくつかの点では似ていますが、その他の点では全くの別物です。Javascript は Java のようなデータ型を持っていません。また、オブジェクト指向ではありますが、一般的なクラスベースのオブジェクモデルではなく、プロトタイプベースのオブジェクトモデルを持っています。メソッドが public か private か、あるいは protected かどうかを気に掛けることも、インターフェイスを実装する必要もありません。変数、引数、そして型を返す関数は厳密に型付けされていません。

Javascript は国際的なプログラミング言語を提供できるように Ecma International(情報通信システムの分野における国際的な標準化団体) によって標準化されています 。この標準化された Javascript のバージョンは ECMAScript と呼ばれ、この標準をサポートするアプリケーションはすべて同じ動作になります。なお、ECMAScript 仕様には、World Wide Web Consortium (W3C) によって標準化されている、スクリプトから利用できる HTML のオブジェクト・モデル(DOM)に関しては記載されていません。

1.2  script 要素

スクリプトを記述します。<script> から </script> の間にスクリプトを記述します。

script 要素は、head 要素の中に配置することが多いですが、body 要素の中に配置しても問題ありません。

script 要素

スクリプトを記述する。

src 属性でスクリプトを記述したファイルを読み込むこともできる。

属性

属性名属性値説明必須
srcURL外部スクリプトファイルのURLを指定×
typeMIMEタイプスクリプトのMIMEタイプ(規定値 text/javascript)
MIME タイプ一覧
×
charset文字エンコーディングUTF-8、Shift_JIS、EUC-JP など×
defer文書の読み込みが完了した時点でそのスクリプトを実行する×
async文書の読み込み中にそのスクリプトが利用可能になった時点で実行する×

記述例
<script src="example.js"></script>      <!-- スクリプトを example.js から読み込む -->
<script>
// スクリプトを記述
</script>

スクリプトを利用できない環境のときに表示したいことは <noscript> から </noscript> の間に記述します。

noscript 要素

スクリプトを利用できないときに表示したいことを記述する。

属性

なし

記述例
<noscript>
<p>Javascript を利用できません。</p>
</noscript>

1.3  基本構文

1.3.1 基本的な記述

Javascript を記述していく上で基本的なルールは次の通りです。

  • 大文字と小文字は区別される
  • スクリプト内の空白と改行は無視される
  • 文の区切りにはセミコロンを付ける

大文字と小文字

Javascript においては大文字と小文字は明確に区別されます。変数などに名前を付ける時や、または既に定義されている予約語を使う場合には大文字小文字も正確に記述する必要があります。

var num = 10;
document.body.insertAdjacentHTML("beforeend", "<p>num = " + Num + "</p>");

変数「num」ではなく「Num」を参照しているため、実行時にエラーになります。

文の目的は、何をするのかブラウザに命令することです。

文の中で空白やタブなどの空白文字と改行は自由に挿入できます。よって、文の先頭に空白やタブを挿入し字下げして記述したり、長い文を途中で改行することも可能です。

また、通常各文の終りにセミコロンを付けます。しかし、文の区切りについて Javascript では実際には必要ない場合があります。どこからどこまでが1つの文なのかある程度は Javascript が判断し自動で区切り文字のセミコロン(;)があるものとして処理してくれるからです。

var num1 =   10
var num2 = 
    20

したがって、上記はいずれもエラーとはならず正常に処理が行われます。

ただ Javascript に文の区切りの判断を任せた場合、意図しない位置で文が区切られてしまう場合もあり分かりにくいエラーの原因となります。またスクリプトを見たときにもどこからどこまでが1つの文なのか分かりにくくなります。その為、文の区切りにはセミコロン(;)を用いて明示的に文の区切りを表すようにします。

var num1 =   10;
var num2 = 
    20;

またセミコロンを記述すれば1つの行の中に複数の文を記述することも可能です。

var num1 = 10;var num2 = 20;

ブロック

文は、ブロックの中にまとめ、グループ化できます。ブロックは "{" で始まり、"}" で終ります。

ブロック文は一般に制御フロー文(例えば if、for、while など)で用いられます。次のような場合、if 文の条件が true のとき、ブロック内のすべての文が実行されます。

if (cond) {
  num1 = 10;
  num2 = 20;
}

1.3.2 実行タイミング

ブラウザはスクリプトが記述された HTML ファイルを読み込み順に解析しながらブラウザに表示していきます。その途中に <script> 要素が現れると HTML などの解析を一時中断し記述されたスクリプトが実行されるのを待ちます。そしてスクリプトの実行が終了すると改めて HTML 文の解析を続行していきます。

<p>HTML文の解析</p>

<script>
var str = "javascript の実行";
</script>

<p>HTML文の解析を続行</p>

スクリプトが見つかるとスクリプトの実行が終了するまでブラウザ上への HTML 文などの出力がいったん停止します。したがって、あまり重い処理をスクリプトで行うとスクリプトが終了するまで残りの HTML 文がブラウザに表示されませんので注意が必要です。

1.3.3 分散記述

スクリプトは HTML ファイル内の複数の箇所に記述することが出来ます。

<p>HTML文</p>

<script>
var num = 10;
</script>

<p>HTML文</p>

<script>
document.body.insertAdjacentHTML("beforeend", "<p>num = " + num + "</p>");
</script>

<p>HTML文</p>

それぞれのスクリプトは <srcipt> 要素が読み込まれた時点で都度実行されることになりますが、スクリプトは <srcipt> 要素の単位で完結しているわけではなくスクリプトが記述されている HTML ページ単位でまとめて扱われます。つまり、ページ内の複数の箇所にスクリプトが分散していたとしても、それぞれのスクリプトは1つにまとめて記述されたかのように実行されます。

1.4  コメント

コメントは次のように記述します。

<script>
// 1行コメント

/* 1行コメント */

/*
  複数行に渡る
  コメント
*/
</script>

<!-- HTML コメント -->

// の場合は、// から行末までがコメントとして扱われ実行時には無視されます。

/* の場合は、*/ が現れるまでの改行を含めたすべての文字がコメントとして扱われ実行時には無視されます。

HTMLのコメントとは異なりますので間違えないようにして下さい。

1.5  予約語

以下は予約語であり、変数、関数、メソッド、あるいはオブジェクトの識別子として用いることはできません。以下は ECMAScript の仕様で既存のキーワードとして予約されているものです。

awaitbreakcasecatchclassconstcontinuedebuggerdefaultdelete
doelseenumexportextendsfalsefinallyforfunctionif
importimplementsininstanceofinterfaceletnewnullpackageprivate
protectedpublicreturnstaticsuperswitchthisthrowtruetry
typeofvarvoidwhilewithyield    

また、将来予約語となる可能性のある単語は以下の通りです。

abstractasbooleanbytechardoublefinalfloatgotoimplements
intinterfaceislongnamespacenativeshortsynchronizedtransientuse
volatile         

予約語ではありませんが、グローバル変数やグローバル関数としてすでに使用されている名前があります。これらは識別子として使用できない場合もあります。

argumentsArrayBooleanDatedecodeURIdecodeURIComponentencodeURIencodeURIComponent
ErrorescapeevalEvalErrorFunctionInfinityisFiniteisNaN
MathNaNNumberObjectparseFloatparseIntRangeErrorReferenceError
RegExpURIErrorStringSyntaxErrorTypeErrorundefinedunescape  

注意

予約語とされていなくても、ブラウザによっては、変数、関数、メソッド、あるいはオブジェクトの識別子として用いることができないものもあります。


1.6  ドキュメントオブジェクトモデル

DOM は Document Object Model の略で、HTML で記述された各要素を取り扱うための標準インタフェースとして 1998 年に W3C によって勧告されました。

DOM は HTML を Javascript などから利用するための API です。Javascript によるユーザーインターフェースの構築やレスポンスの表示など、インタラクティブな部分はほとんどが DOM 操作によるものです。

DOM ツリー

html ドキュメントをツリー構造として表現したものです。

HTML5 以前は、html ドキュメントを階層構造を持ったオブジェクトに変換するルールが規定されておらず、ブラウザごとに違いが生じていました。しかし、HTML5 では、どのように解釈しそれをどのようにして DOM ツリーにするべきなのかが厳密に規定されました。

記述例
<html>
 <head>
  <meta charset="UTF-8">
  <title>タイトル</title>
 </head>
 <body>
  <h1>見出し</h1>
  <p><strong>強調強調</strong>本文本文 ... 本文</p>
  <p>本文本文 ... 本文</p>
 </body>
</html>
DOM ツリー

DOMツリー内の各要素(四角)を「ノード」といいます。HTML で「エレメント(要素)」といっていたものと同じです。

Document はブラウザに読み込まれた Web ページを表し、Web ページのコンテンツである DOM ツリー (<body> や <p> などの要素を含みます) へのエントリポイントとして提供されます。これはドキュメント内の要素を参照したり、ドキュメントに新たな要素を作成するなど、ドキュメント全体に関わる機能を提供します。

Javascript からは、これら document の要素を取り出して、内容を参照したり変更したりすることができます。

記述例
  <div id="kore" style="color:yellow;">AAAAA</div>
  <script>
    let elm = document.getElementById("kore");     // id="kore" というエレメントを取り出す
    elm.style.color = "blue";                      // そのエレメントの文字色を青にする
    elm.textContent = "BBBBB";                     // そのエレメントの内容を BBBBB にする
  </script>
表示例

また、次のように Javascript でプログラムを組めば、body 要素内のすべての要素を表示することができます。

記述例
<html>
 <head>
  <meta charset="UTF-8">
  <title>タイトル</title>
  <style>
  h1, p { display: none; }
  </style>
  <script>
  function dispNode(node, ind) {
   let s = ind + node.nodeName + "(" + node.innerText + ")<br>";
   for (let i = 0 ; i < node.children.length ; i++) {
    s += dispNode(node.children[i], ind + "&nbsp;&nbsp;");
   }
   return s;
  }
 </script>
 </head>
 <body onload="document.getElementById('el').innerHTML = dispNode(document.body, ''));">
  <h1>見出し</h1>
  <p><strong>強調強調</strong>本文本文 ... 本文</p>
  <p>本文本文 ... 本文</p>
  <section id="el"></section>
 </body>
</html>

表示例

1.7  イベントハンドラ

ブラウザは script タグで指定された Javascript を解釈して実行します。その時、関数などを定義するだけにして、実際にその処理が行われるのはユーザーがボタンをクリックした時や、何かを入力した時など、ユーザーの何らかのアクションに関連付けて Javascript を実行させることができます。さらには、ユーザーのアクションだけでなく、ページの読み込みや通信処理の完了後など、ブラウザ上で起こるあらゆるイベントについて処理を行うのが Javascript の特徴です。このようにイベントを中心としたプログラミングをイベントドリブン(イベント駆動型)プログラミングと呼びます。

イベントを扱うにあたって、大きく2つの方法があります。1つは HTML4.01 などで定義されている、HTML の各要素に onXXXXX(XXXXX はイベント名)を記述する方式で、もう1つは DOM Level 2 Events で定義された高機能で抽象化された方法(DOM 方式)です。

1.7.1 onXXXXX 方式

(1) インラインイベントハンドラ

onXXXXX は HTML の タグの中に書くことができます。JavaScript は onXXXXX に続く = の右辺に文字列として記述します。この例では、onload(ページ全体の読み込み完了)時 "Javascript の実行"が表示されます。

記述例
  <body onload="document.getElementById('d1').style.color='black';">
    <div id="d1" style="color:lightgrey;">Javascript の実行</div>
  </body>
表示例

(2) Javascript

また、Javascript で、onXXXXX を設定することもできます。この例でも、onload 時 "Javascript の実行" が濃く(黒く)表示されます。

記述例
  <body>
    <script>
      window.onload = function() {
        document.getElementById("d1").style.color="black";
      };
    </script>
    <div id="d1" style="color:lightgrey;">Javascript の実行</div>
  </body>
表示例

ただし、この onXXXXX 方式には問題があります。ある要素のあるアクションに対して1つの処理しか登録できないという点です。つまり、上記の2つのコードを組み合わせたとき、HTML上に書かれた onload と Javascript で設定された onload が重複してしまいます。どちらが有効になるかは Javascript が実行されるタイミング、この場合 script タグを記述する場所に左右されます。

例えば、script 要素が body タグの前の head 要素の中に記述した場合は body 要素の onload が呼ばれ、"body onload=... の実行" が濃く表示されます。

記述例
<html>
  <head>
    <script>
      window.onload = function() {
        document.getElementById("d2").style.color="black";
      };
    </script>
  </head>
  <body onload="document.getElementById('d1').style.color='black';">    <!-- こちらが実行される -->
    <div id="d1" style="color:lightgrey;">body onload=... の実行</div>
    <div id="d2" style="color:lightgrey;">window.onload=... の実行</div>
  </body>
</html>
表示例

古い では window.onload で定義した処理も実行されることがあるようです。


また、script 要素が body タグの中に記述されていた場合は window.onload で定義した処理が実行され、"window.onload=... の実行" が濃く表示されます。

記述例
<html>
  <body onload="document.getElementById('d1').style.color='black';">
    <script>
      window.onload = function() {
        document.getElementById("d2").style.color="black";    // こちらが実行される
      };
    </script>
    <div id="d1" style="color:lightgrey;">body onload=... の実行</div>
    <div id="d2" style="color:lightgrey;">window.onload=... の実行</div>
  </body>
</html>
表示例

1.7.2 DOM 方式

DOM Level 3 Events ではイベント登録用メソッドとして addEventListener が定義されています。登録した処理を削除するのはremoveEventListener です。

addEventListener を使えば、ある要素のあるアクションに対して、いくつもの処理を登録できます。

記述例
<html>
  <body>
    <script>
      window.addEventListener("load", function() {
        document.getElementById("d1").style.color="black";              // こちらが先に実行される
      }, false);
    </script>
    <div id="d1" style="color:lightgrey;">1つ目の load の実行</div>
    <div id="d2" style="color:lightgrey;">2つ目の load の実行</div>
    <script>
      window.addEventListener("load", function() {
        document.getElementById("d2").style.color="black";              // こちらが後に実行される
      }, false);
    </script>
  </body>
</html>
表示例