Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
JavaScript
中級編
- トップページ
- JavaScript中級編 - オブジェクトを使ってみよう
オブジェクトを使ってみよう
みなさまどうもこんにちは。
初めましての方ははじめまして、どこかの記事でお会いした方はまたお会いできて光栄でございます。
こちらJavaScriptの中級編となります。ちょっと難しい内容まで踏み込んでいきますのでHTML、CSS、JavaScriptの基本的な知識が必要になってきます。当サイトの場合ですとHTML入門編、CSS入門編、JavaScript入門編あたりをお読み頂いた後に読み進めて頂ければテンポよく進められるような気がします。
ではいきましょう。
まずJavaScriptの『オブジェクト』というものを使用してみたいと思います。『オブジェクト』とは直訳すると『物』になるのですが、『データのあつまり』と覚えてしまったほうが調子良いかもしれません。
JavaScriptでは『連番が付けられた変数(データ)の集合体』である『配列』という概念がありますが、『オブジェクト』とは『独自の名前』を持ったデータの集合体のようなイメージになります。
配列ではインデックス番号(連番)で操作していましたね。以下のような感じです。
var x = [0, 1, 2]; console.log(x[2]); // これは2が出力されます。
オブジェクトになるとこのようになります。
var x = {}; x["hoge"] = 0; console.log(x["hoge"]); // 『0』と出力されます。
通常の配列と違ってインデックス番号ではなく『hoge』という名前をつけてそれを定義し呼び出していますね。これがJavaScriptにおいての『オブジェクト』になります。ちなみにJavaScriptでのオブジェクトは他の言語でいうところの『連想配列』(ハッシュ)と同じ概念です。厳密な定義だとJavaScriptでの連想配列は存在してないって事になっていたりするのですが、まあとどのつまりオブジェクトは連想配列だと思って頂いて問題ありません。
JavaScriptでのオブジェクトに入っているそれぞれのまとまりを『プロパティ』と呼び、プロパティに入ってる値はそのまま『値』と呼びます。
そして各プロパティが持つ名前は『プロパティ名』(もしくは『キー』)と呼びます。
var x = {}; x["hoge"] = 0; console.log(x["hoge"]); // この場合は『{"hoge": 0}』がプロパティで『hoge』がプロパティ名、『0』が値になります。
ちょっとややこしいですが『プロパティ』と『プロパティ名』と『値』は現場でも良く使用される言葉なので覚えておきましょう。
ちなみにプロパティ名(キー)のことを配列と同じように『インデックス』や『識別子』と呼んでしまっても特に問題ありません。他の言語でも呼び方に違いがあったりするので、制作現場などでも気にしなくて大丈夫です。プログラマーさんはみんな知ってます。
では文法と使い方を確認していきましょう。まずオブジェクトを定義するには『{}』を使用します。波括弧ですね。
var x = {};
これで『x』はオブジェクトとなります。『{}』を使用した定義は『リテラル式』(オブジェクトリテラル)と呼ばれる記法になります。
他の定義方法として『new Object();』を使用するという方法があります。
var x = new Object();
こちらでも同じ動きをします。ただし、JavaScriptにおいての『new』演算子の動きが想像とかけ離れた動きをするのと、JavaScriptでは元々定義されている『Object』というオブジェクトそのものを上書きできてしまったりするので基本的に『{}』を使用して定義するようにした方が良いです。タイピング的にも『{}』の方がさくっと記述できるのでとっても楽です。
オブジェクトを生成したらそこに値を入れていきましょう。値の入れ方はいくつかパターンがあり、まず『[]』を使って代入する方法を紹介したいと思います。以下のサンプルをみてください。
var x = {}; x["hoge"] = 0;
これは『x』というオブジェクトを生成し、プロパティ名『hoge』というプロパティに『0』という値を代入しています。配列と同じような記法になりますね。注意点ですが『[]』の中に入れる際の『"』か『'』を忘れないようにしてください。これを忘れると『[]』の中が変数展開されてしまいます。
var x = {}; x[hoge] = 0; // この場合の『[]』の中は変数『hoge』となります。変数『hoge』は定義していないのでエラーとなります。
これを逆に利用すると変数に文字列を入れ、それを展開させてプロパティ名としてしまうというちょっとトリッキーな記法も使えます。
var x = {}; var hoge = "hoge"; x[hoge] = 0; // 変数『hoge』を展開させて『x["hoge"]』に値を入れています。
状況によってはこの記法は非常に強力です。ちょっと慣れないと難しいかもしれませんが覚えておくと良いです。
続いてのパターンですが、『{}』の中でそのままプロパティを定義してしまうという方法があります。以下のような感じですね。
var x = { "hoge": 0, "hoge1": "Hello World" };
これでもオブジェクトにプロパティを定義することができます。上記のサンプルではオブジェクト『x』に『hoge』というプロパティ名に値『0』を代入、『hoge1』に値『"Hello World"』を代入しています。
プロパティ名と値の区切りには『:』を使用します。
注意すべきは『,』ですね。上記のように複数のプロパティを定義する際の区切りは『,』を使用します。最後のプロパティの『,』は省略できるのですが省略しなくても問題ありません。以下のような感じですね。
var x = { "hoge": 0, "hoge1": "Hello World", // 最後のプロパティのおしりに『,』を入れてもOKです。 };
ちなみにプロパティ名の『"』か『'』は省略しても大丈夫です。
var x = { // プロパティ名の『"』や『'』は省略できます。 hoge: 0, hoge1: "Hello World" };
ただし、『-』などの演算子や半角スペースがプロパティ名に含まれている場合は『"』か『'』で必ずくくる必要がありますので注意しましょう。
var x = { Hello World: 0, // これはダメです。 Hello-World: "Hello World" // これはダメです。 };
なので慣れないうちは『"』か『'』で必ずくくるようにしたほうが良いかもしれませんね。
さて、続いてのパターンで『.』を使用する記法があります。以下のような感じですね。
var x = {}; x.hoge = 0;
上記の場合もプロパティ名『hoge』に『0』を代入しています。『.』で繋げてプロパティ名を記述するとそのままプロパティの操作をすることが可能です。
その場合、『var』をつけてしまわないように注意して下さい。オブジェクト『x』はすでに定義されているので『var x.hoge』としてしまうと変数『x.hoge』を再定義していることになってしまいます。JavaScriptでは変数名に『.』は使えませんのでエラーになっちゃいます。
var x = {}; var x.hoge = 0; // これは『x.hoge』という名前の変数の再定義になってしまいます。JavaScriptでは変数名に『.』は使えませんのでエラーになります。
そして『-』などの演算子や半角スペースがプロパティ名に含まれている場合は『.』を使った記法は使えません。以下はプロパティ名『ho-ge』を定義しようとしているサンプルになります。
var x = {}; x.ho-ge = 0; // この場合の『-』は演算子扱いになるのでエラーになります。
とこんな感じですね。
JavaScriptではオブジェクトに関する色々な記法が存在しているために慣れないうちは大変かと思います。しかもどの記法が一番使用されるか、というのも特になかったりします。単純に定義したい場合は『.』がよく使われますし、オブジェクトを先に定義したい場合は『{}』が良く使用され、変数展開処理をかませたい場合などは『[]』の記法が使われます。なのでちょっと大変ですが全ての記法をマスターするようにしてください。
当サイトのJavaScript入門編で紹介したHTML要素のstyle属性を変更する『.style』というのがありましたね。以下のような感じでした。
var x = document.getElementById("hoge"); x.style.color = "red";
実はこの『.style』というのは『document.getElementById()』で取得したオブジェクトのプロパティです。なので先ほど解説したオブジェクトの記法を守ればどのような形でも値にアクセスすることができます。
var x = document.getElementById("hoge"); // JavaScriptのオブジェクトの記法に則れば記述方法は何でもOKです。 x.style.color = "red"; x["style"]["color"] = "red"; x.style["color"] = "red";
突然ですがJavaScriptにおいてのオブジェクト周りの気持ち悪さをちょっと紹介したいと思います。
まずJavaScriptにおいての配列の実態は実はオブジェクトだったりします。以下のサンプルをみてください。以下は通常の配列を定義しています。
var x = [0, 1, 2]; console.log(x[0]); // 0が出力されます。
さて、これを『x["0"]』として呼び出して、さらに『x["3"] 』に値を追加してみます。
var x = [0, 1, 2]; x["3"] = 3; // 文字列の『3』に3を代入。 console.log(x["0"]); // インデックスを文字列の『0』として記述しても問題なく0が出力されます。 console.log(x[3]); // こちらも問題なく3が出力されます。
なんとこれ普通に動いてしまいます。JavaScriptでは『"0"』や『"3"』のように通常の数値としても認識できそうな『文字列の数値』をインデックスに指定しても通常の数値のインデックスとして呼び出せたり値を入れたりすることができます。
しかも配列を定義したあとそのまま文字列のインデックス(キー)を追加できてしまったりします。
var x = [0, 1]; // 配列を定義。 x["hoge"] = "hoge"; // 配列を定義したにも関わらず文字列のインデックスに値を追加する。 console.log(x["hoge"]); // 問題なく"hoge"が出力されます。
この場合の『.length』の値はどうなっているのかというと『2』になっています。中身をブラウザのコンソール画面で確認してみるとこうなっています。
こんな感じで通常の配列の要素として追加されているわけではなく、別のものとして扱われている感じになりますね。
正直、通常の配列に文字列のインデックスを追加したらエラーになってほしいところなのですがJavaScriptではそうはなりませんので注意してください。
では「配列とオブジェクトの違いって何?」って話になりますが、JavaScriptで配列を定義すると裏側で『Array.prototype』というオブジェクトから通常のオブジェクトにはない機能が継承されます。その代表が『.length』です。配列の要素数を数えるときに使用した『.length』プロパティは通常のオブジェクトには生成されません。
var x = [0, 1]; console.log(x.length); // これは2と出力されます。 var y = { "hoge": 0, "hoge1": 1 }; console.log(y.length); // これはundefinedです。
オブジェクトの数に合わせた処理を構築することも可能ですが、処理が面倒くさいので要素数にあわせて何かしらの処理をしたいといった場合には『.length』プロパティが用意されている配列を使用した方が色々と楽です。使い分けていきましょう。
と、こんな感じでJavaScriptのオブジェクト周りの仕様は非常にゆるーい感じになってます。特に他のプログラム言語に精通した方だとかなり気持ち悪く感じるかと思います。
思わぬミスの原因になりがちなのでオブジェクトと配列の裏側の動きには注意するようにしてください。
さて、続きましてオブジェクトの中にオブジェクトを入れたり、オブジェクトの中に配列を入れたりすることも可能です。以下のサンプルをみてください。
var x = { "hoge": { "fuga": 0 }, "array": [0, 1, 2] };
このような記法を『多次元オブジェクト』と呼びます。
さて、この場合のオブジェクトの値とかの呼び出し方はどうすればよいのかというと以下のようになります。
var x = { "hoge": { "fuga": 0 }, "array": [0, 1, 2] }; console.log(x.hoge.fuga); // 『.』を繋げて呼び出します。 console.log(x.array[0]); // 『.』と『[]』で呼び出します。 console.log(x["array"][0]); // 『[]』を使って呼び出します。
『[]』もしくは『.』を必要な分だけ連続して繋げれば良いという感じですね。
JavaScriptでのオブジェクト使用時に関する大きな注意点がひとつあります。JavaScriptではオブジェクトの代入式を記述した際、実際に値が複製(コピー)されて収まっているわけではありません。以下にサンプルを記述してみます。
var x = { // オブジェクト『x』を適当に定義。 "hoge": 0, "hoge1": 1 } var y = x; // オブジェクト『y』にオブジェクト『x』を代入。 x.hoge = 2; // 『x["hoge"]』に新しい値『2』を代入。 console.log(y.hoge); //オブジェクト『y』のプロパティ名『hoge』を出力しているにも関わらず『x["hoge"]』の『2』が出力される。
これを実行してみると不思議なことが起こります。オブジェクト『x』をオブジェクト『y』に代入しているにも関わらず『y["hoge"]』と実行すると『x["hoge"]』の値が返ってきます。
なぜこうなるのかというとJavaScriptでオブジェクトを他のオブジェクトに代入してもそのオブジェクトの『参照』(対象となるオブジェクトの場所)のみが代入されているせいだったりします。なので元のオブジェクトを操作すると参照先のオブジェクトにも変化が起こります。
解説が長くなるので詳しい内容は先の記事で紹介しますが、JavaScriptにおいては上記のように代入式でオブジェクトを代入してもそのオブジェクトは複製(コピー)されない、ということだけは覚えておきましょう。
ちなみにこの『参照』が代入される挙動は『参照渡し』と呼ばれます。JavaScript以外の他の言語でも同じ挙動になる場合がありますので『参照渡し』という言葉は覚えておくようにしてください。参考書などで良く出てきます。
というわけでJavaScriptのオブジェクト周りに関する基本的なところはこんな感じになります。括弧だらけだし記述方法は色々あるし定義方法はゆるいしオブジェクトを代入しても複製されてるわけじゃないしで最初は大変かもしれませんが頑張ってください。
続いての記事ではオブジェクトの数だけ処理を加える事ができる『for...in文』をやっていきたいと思います。ではまたお会いしましょう。
この記事は桜舞が執筆致しました。
著者が愛する小型哺乳類 |
桜舞 春人 Sakurama HarutoISDN時代から様々なコンテンツを制作しているちょっと髪の毛が心配な東京在住のプログラマー。生粋のロングスリーパーで、10時間以上睡眠を取らないと基本的に体調が悪い。好きなだけ寝れる生活を送るのが夢。ゲームとスポーツと音楽が大好き。誰か髪の毛を分けて下さい。 |
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。