目標
ここでは、簡単なオブジェクトおよび一次元配列、JavaScriptからHTMLの要素を扱う方法について学ぶ。
- 一次元配列の概念について理解する。また、一次元配列の参照ができるようになる。
- getElementsByTagName()が使えるようになる。
- getElementById()が使えるようになる。
- getElementsByClassName()が使えるようになる。
- JavaScriptによるDOMの操作ができるようになる。
- getElementById()やgetElementsByClassName()等が返す値の構造を理解する。
オブジェクト
オブジェクトは値の集合である。
例えば、名前というオブジェクトは、日本の場合は「姓」と「名」で出来ている。
また、位置というオブジェクトは「緯度」と「経度」で出来ているかもしれない。
更には、人を表すオブジェクトは、先に出てきた「名前」というオブジェクト、つまり「姓」と「名」を含むオブジェクトと「年齢」「性別」と表現することができる。
オブジェクトリテラル
JavaScriptにおいて、実際の値を使ってオブジェクトを表現するためにはオブジェクトリテラルが用いられる。
オブジェクトリテラルは次のような書式を持つ。
{プロパティ名: 値, プロパティ名: 値, ...}
プロパティ名というのは、オブジェクトの中に存在する個々の値につけられた名前である。
例えば先ほどの名前をオブジェクトリテラルで書くと次のように書く事ができる。
ここで「”慶應”」「”太郎”」のように値がダブルクォートで囲まれているのは値が文字列だからである。
{familyName: "慶應", firstName: "太郎"}
プロパティ名は空白を含む任意の文字列を利用する事ができる。
空白を含む場合にはプロパティ名をクォートやダブルクォートで囲む必要がある。
しかし、後に述べるオブジェクトの参照、つまり値の使い方の際に制限がでるので、空白や「-」などの利用は避けておいた方が無難である。
漢字やひらがなを使う事も出来るが、止めておいた方がよいだろう。
{"family name": "慶應", "first-name": "太郎"}
また、人のようにオブジェクトを内包したオブジェクトの場合は下記のように記述することが可能である。
ここでは、「name」というプロパティは「{familyName: "慶應", firstName: "太郎"}
」というオブジェクトにひもづけられているので注意が必要である。
{name: {familyName: "慶應", firstName: "太郎"}, age: 19, gender: "male"}
オブジェクトの生成
オブジェクトが入った変数を作るのは簡単である。
予め初期化されたオブジェクトを作るためには下記のように記述する。
var 変数名 = {プロパティ名: 値, プロパティ名: 値, ...};
例えば、人のオブジェクトを生成するためには下記のようにすれば良い。
読みやすいように改行してあるが、改行はあっても無くても問題ない。
見やすいように書くよう心がけるとよい。
var human = { name: {familyName: "慶應", firstName: "太郎"}, age: 19, gender: "male" };
JavaScriptでは、他にもnew演算子を用いてオブジェクトを生成する方法がある。
new演算子を用いてオブジェクトを生成するためには、コンストラクタを用いる。
ここではあまり詳しいことは述べないが、Date()などがこの例である。
Date()を使ったプログラムでは、下記のようにオブジェクトを生成する。
var date = new Date();
これは、システムが提供しているオブジェクトであるDateオブジェクトを使って、Dateオブジェクトが持つ様々な機能が使える新たなオブジェクトを作り出し、それを変数dateに代入している。
Dateオブジェクトには、予めそのメンバとして、toLocaleString()のような関数(オブジェクトにひもづけられている関数をメソッドと呼ぶ)が定義されており、変数dateを通じてこれらを利用することが出来る。
つまり、オブジェクトには、本来、関数も格納することができますが、これについては追々みていくこととする。
オブジェクトの参照
オブジェクトを変数に入れたら、当然それを使う事を考えなければならない。
プログラムの中でオブジェクトの中の値を参照するためには次のように表現する。
変数名.プロパティ名 変数名["プロパティ名"] 変数名['プロパティ名']
どの行も同じ値を表しているが、1行目の表現方法の場合、注意が必要である。
プロパティ名が「123」という数字だったり、「first-name」の様にマイナスを含んでいたりして、変数名の命名規則に則っていない場合は問題がおきるからである。
これが、上で空白やマイナスなどの文字列は使わない方が無難だと言った理由である。
また、上のhumanの例では、nameの中にfamilyNameなどがはいっている。
このような場合は次のように書く。
変数名.プロパティ名1.プロパティ名2 変数名["プロパティ名1"]["プロパティ名2"] 変数名['プロパティ名1']["プロパティ名2"]
具体的に「”慶應”」という値が入っている部分は次のようになる。
human.name.firstName 変数名["name"]["firstName"] 変数名['name']["firstName"]
さて、では実際のプログラムの中ではどのように利用するのであろうか。
下記をみて欲しい。
下記は、「human」というオブジェクトを生成し、そのオブジェクトが含むそれぞれのプロパティの値を表示させた例である。
例では、いろいろな表現があることを示す為に、「human.name.familyName」「human.name[“firstName”]」など異なった表現を使っているが、不必要に表現を混ぜないことがプログラムの見やすさを向上させることに注意が必要である。
/* * オブジェクトの生成 */ var human = { name: {familyName: "慶應", firstName: "太郎"}, age: 19, gender: "male" }; /* * プロパティの表示 */ alert("姓: " + human.name.familyName); alert("名: " + human.name["firstName"]); alert("年齢: " + human.age); alert("性別: " + human['gender']);
一次元配列
多くのプログラミング言語では、多数のデータを扱うために配列という仕組みを持っている。
JavaScriptも例外ではない。
配列とは、変数名は1つのまま、それに番号をつけて複数の値を記憶できるようにしたものである。
配列の中の1つ1つの値を記憶できる場所のことを「要素」と呼ぶ。
上でも書いたが、配列の場合、変数名は配列全体に対して1つだけである。
配列全体は沢山の要素の集まりである。
それぞれの要素が、今まで学習してきた変数のように使える。
逆に言うと、変数名だけでは、これまでの変数のようには扱うことができないので注意が必要である。
配列リテラル
配列についてもリテラルが決まっている。
配列リテラルは次のとおりである。
[値, 値, 値, ...]
値の数は任意で、0個以上の必要な数だけ指定することができる。
0個の場合には空の配列が生成される。
実際には次のような記述となる。
["佐藤", "鈴木", "田中", ...]
上の例では全ての要素の値が文字列になっているが、JavaScriptでは、要素毎に値の型を変える事ができる。
例えば、「["a", 3]
」と書くと、1つめの要素の値は文字列だが、2つめの要素の値は数値として扱われる。
更には、オブジェクトの配列を作ったり、配列をオブジェクトのプロパティの1つに指定したりすることも可能である。
配列の生成
配列を生成する場合にもオブジェクトと同様に、配列リテラルで初期化された配列を生成する方法と、コンストラクタを使う方法がある。
ここでは、配列リテラルを使った方法についてみていく。
配列リテラルを使った方法は簡単で、下記のようになる。
var 変数名 = [値, 値, 値, ...];
実際にプログラムの中で使うと下記のようになる。
この例では、familyNameという変数に「”佐藤”」「”鈴木”」「”田中”」の3つの文字列が入った配列を代入している。
var familyName = ["佐藤", "鈴木", "田中"];
また、空の配列(要素が1つもない配列)を作るためには次のようにする。
var familyName = [];
配列の操作
配列オブジェクトには、様々なメソッドが用意されている。
ここではその幾つかを紹介する。
要素の追加
先頭に要素を追加(unshift)
var array = ['b', 'c']; array.unshift('a'); alert(array); // ['a', 'b', 'c']
末尾に要素を追加(push)
var array = ['a', 'b']; array.push('c'); alert(array); // ['a', 'b', 'c']
要素の結合
2つの配列を連結した配列を生成(concat)
var array1 = ['a', 'b']; var array2 = ['c', 'd']; // 新しい配列 var array = array1.concat(array2); alert(array); // ['a', 'b', 'c', 'd'] alert(array1); // ['a', 'b'] alert(array2); // ['c', 'd']
要素の取得
配列の要素数を取得(length)
var array = ['a', 'b', 'c']; var len = array.length; alert(len); // 3
何番目の要素に指定した値があるかを取得(同じものが複数存在する場合、最初の要素)(indexOf)
var array = ['a', 'b', 'c']; var index = array.indexOf('b'); alert(index); // 1
何番目の要素に指定した値があるかを取得(同じものが複数存在する場合、最後の要素)(lastindexOf)
var array = ['a', 'b', 'c']; var index = array.lastIndexOf('c'); alert(index); // 2
要素の削除
先頭を削除(shift)
var array = ['a', 'b', 'c']; array.shift(); alert(array); // ['b', 'c']
末尾を削除する(pop)
var array = ['a', 'b', 'c']; array.pop(); alert(array); // ['a', 'b']
要素内容を辞書順にソート
var array = ["e", "c", "b", "a", "d"]; array.sort(); alert(array); // ["a", "b", "c", "d", "e"]
配列の参照
配列の参照は、オブジェクトの参照と似ている。
変数名の後に角括弧をつけ、その中に番号を入れて指定する。
例えば、array という名前の配列の中の2番目の要素を参照するためには下記のように表記する。
array[1];
ここで気をつけなければならないことは、配列の番号が0番から始まることである。
2番目の場合は、0, 1なので「1」を指定する。
また、数字の代わりに変数を指定することもできる。
下に例を示します。この例では1行目でarrayという配列を作り、3行目で変数nに1を代入している。
4行目では、変数nを使って0から数えてn番目の要素を表示している。
var array = ["佐藤", "鈴木", "田中", "渡辺", "伊藤", "山本"]; var n = 1; alert(array[n]);
また、for文と組み合わせることによって、全ての要素を順に出力することも可能である。
下の例では、lengthプロパティを使ってfor文で繰り返しを作り、全ての配列要素に対して「○番目: ××」のように表示をしている。
var array = ["佐藤", "鈴木", "田中", "渡辺", "伊藤", "山本"]; var i; for (i = 0; i < array.length; i++) { alert(i + "番目: " + array[i]); }
オブジェクトと配列
実は、オブジェクトと配列には、その表現方法をみてもわかるように類似性がある。
プロパティが数字のオブジェクトを配列とみることもできる。
ただし、「obj.0」「obj.1」や「obj[0]」「obj[1]」などの表現はできないので注意が必要である。
この場合は、「obj[“0”]」「obj[“1”]」のように表現する必要がある。
プロパティは、オブジェクトでは文字列だが、配列では数字なのである。
HTMLとJavaScriptの結びつけ
要素と名前付け
HTMLでは各要素にIDやクラスをつけることができる。
IDやクラスをつけることによって、その要素だけに対してCSSでスタイルを指定することができた。
JavaScriptにおいても、IDやクラスをつけておくことによって、その要素を指定しやすくなる。
id
id属性は、要素を識別するために固有のID(識別子)を付与するものである。
1つの文書(ページ)内で同じのIDを複数つけることはできない(つまり、一意でなければならない)。
id属性を指定する目的は、CSSで装飾する要素を指定したり、JavaScriptで特定要素を参照して処理を行うためである。
また、a要素にページ内の指定箇所を参照できる終点(id=”ID”)にも使われ、開始タグには <a href="#ID名">
の形式で IDにハッシュ(#)を記述する。
このIDは、div要素や見出し要素内などに記述したものを指定することができる。
class
class属性は、その要素にクラス名を指定する。
class属性はid属性と異なり、ひとつの文書内に同じクラス名を何度でも用いることができる。
また、半角スペースで区切って、1つの要素に複数のクラスを適用することもできる。
JavaScriptによる要素の取扱
JavaScriptからHTML要素を参照する場合は、まずその要素をJavaScriptのプログラムの中に取り込む必要がある。
ここでは、IDやクラスを使ったHTML要素とJavaScriptの結びつけについて説明する。
getElementById()
JavaScriptからIDを指定してHTML要素を紐付ける関数として、documentオブジェクトにgetElementById()メソッドが用意されている。
getElementById()メソッドはIDを引数にとり、そのIDを持つHTML要素を返す。
返り値を変数に代入したりすることによって、以後JavaScriptからその要素に対して簡単にアクセスができるようになる。
テスト1
テスト2
上記のJavaScriptでは、ID属性がp1234という値の要素を、新しい変数eleに代入している。
その後アラートで、ID属性がp1234という値の要素のHTML、つまり指定されたID属性のある開始タグとその終了タグの間に書かれたHTML全て(=テスト1)が出力されている。
getElementsByClassName(“CLASS名”)
getElementsByClassName()は、指定したclass属性を持つ要素を全て取得する。
下の例では、「aaa」というclass属性を持つ要素を取得している。
ここで、「aaa」というclass属性を持つ要素は複数ある可能性があるため(事実、下の例では複数の要素が「aaa「というclass属性を持っている)、返り値を格納している変数classesは配列となっている。
要素1
要素2
要素3
要素4
要素5
1つのタグの中に、class属性を複数指定できるように、JavaScriptでも複数のclass名を同時に指定することもできる。
複数指定する場合は以下のようにスペースで区切って指定する。
要素1
要素2
要素3
要素4
要素5
getElementsByTagName(“タグ名”)
getElementsByTagName()は、タグ名を指定してHTML要素を取得するためのメソッドである。
getElementsByTagName()も、getElementsByClassName() と同様に、指定したタグ名を持つ要素を全て取得し、配列を返す。
getElementsByTagName()では、id属性やclass属性が付加されていても関係なく、指定したタグ名のものなら全て取得される。
DOM
HTMLの文書は構造化された文書の代表のようなものである。
ただ、これまではあまりそのことを意識した使い方はしなかったかもしれない。
しかし、プログラムからHTMLの文書を操作するには、その構造を意識する必要がある。
HTML文書のある部分の色を変えたり、他のテキストと置換するようなことを考えた場合、「HTML文書のある場所」を指定する必要があるからである。
ここでは、HTML文書構造を意識して、プログラムからアクセスするための手法について学ぶ。
HTML文書と木構造
HTML文書は実は木構造で表現することができる。
次のHTML文書を見てほしい。
非常に初歩的なHTML文書だが、この文書も構造を持っている。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JavaScript</title> </head> <body> <h1>JavaScriptとは</h1> <p>JavaScriptは、プログラミング言語の1つで、ブラウザ上で動作するという特徴を持つ。</p> </body> </html>
この文書の構造は、html要素の中にhead要素とbody要素があり、head要素の中にはメタ要素とタイトル要素がある。
これらの関係は下記のような木構造として表現することができる。
DOM
HTML文書は上記の様に木構造を成している。
では、「HTML文書のある場所」をどのようにして示すのであろうか。
この問題を解決するためにDOMを使う。
DOMとは、Document Object Modelの略で、文書をオブジェクトとして扱うための取り決めである。
難しそうだが、基本的には上で述べた木構造と等価なものである。
具体的に見ていこう。
下記の図を見てほしい。
この図は、上の木構造の図に”document”というノードと若干の説明が加わった図となっている。
上で、document.getElementById()という関数を紹介した。
実は、これが正にDOMモデルのインターフェイスそのものである。
この関数の意味は、documentという文書(全てのHTML文書の一番上のレベルのオブジェクトはJavaScriptではdocumentになる)の中から指定したIDをもつ要素をもってくる、というものである。
つまり、上の木構造を全探索し、指定したIDをもつノードを返り値とする。
DOMのインターフェイスは他にもある。
要素を格納しているオブジェクトは様々なプロパティ(値)を持っている。
例えば、ある要素に対してfirstChildというプロパティを指定すると、1つ目の子供要素を得ることができるし、childNodes[1]というプロパティを指定すると2つめの子供要素を得ることができる。
ここで鉤括弧の中が1なのは、JavaScriptの場合、配列は0から始まるためである。
例えば、タイトルの「JavaScript」という文字が入っている要素は次のようにして指定することができる。
document.childNodes[1].firstChild.childNodes[1];
ただし、HTMLファイルに改行やタグとタグの間に空白があったりすると、その改行や空白が要素として認識されてしまうことがあるため、注意が必要である。
次のように改行等を含めずに書く必要があるかもしれない。
<!DOCTYPE html><html id='toplevel'><head><meta charset="utf-8"><title>JavaScript</title></head><body><h1>JavaScriptとは</h1><p>JavaScriptは、プログラミン>グ言語の1つで、ブラウザ上で動作するという特徴を持つ。</p></body></html>
また、要素を格納したオブジェクトには、firstChildやchildNodes以外にも様々なプロパティが存在する。
例えば、innerHTMLというプロパティでは、その要素が内包する木構造のHTMLが得られる。
プロパティの例を下に示す。
プロパティ | 説明 |
---|---|
attributes[] | ノードの属性の配列。 |
childNodes[] | 子要素の配列。 |
firstChild | 最初の子要素 |
innerHTML | ノード内のHTML。 |
innerText | ノード内のテキスト。 |
lastChild | 最後の子要素。 |
parentNode | 親要素。 |
style | ノードのスタイルを指定する属性。 |
value | ノードのvalueプロパティの値。 |
練習問題5-
prompt()を使って6つの名前を入力してもらって配列に入れ、その中から3つずつ2回に分けてalert()で表示するプログラムを作成せよ。
練習問題5-
prompt()を使って5つの文字列を入力してもらい、辞書順に1つずつalert()で表示するプログラムを作成せよ。
ヒント: sort()メソッドを使うことができる。
練習問題5-
p要素が複数含まれているページを作り、getElementsByTagName()を使ってp要素の数を数え、その数をalert()で表示するプログラムを作成しなさい。
練習問題5-
p要素が複数含まれているページを作り、getElementsByTagName()を使ってp要素の数を数え、その数をテキストエリアに表示するプログラムを作成しなさい。
このページのp要素の数は、つです。
練習問題5-
次のようなHTMLがあるとき、cccを含んだ要素、aaaとbbbを含んだ要素の内容を変更するボタンを作成しなさい。
<p class="aaa">要素1</p> <p class="aaa bbb">要素2</p> <p class="ccc aaa bbb">要素3</p> <p class="aaa ccc bbb">要素4</p> <p class="aaa bbb">要素5</p>
要素1
要素2
要素3
要素4
要素5
内容: