JavaScriptを基礎学習していくと配列という言葉が出てきたり、オブジェクトという言葉や、しまいにはクラスという概念まで出てきて、もう最後の方になるともうどうにでもしてくれ!とわからないまま学習していたのを覚えています。
オブジェクトってよくわかってなくてもJavaScript自体は書けちゃうんで、僕も今までよくわからないままきてしまいました。
最近、徐々にオブジェクトの理解が進んできたので、オブジェクトについてわかりやすく解説していきたいと思います。
オブジェクトとというワードに拒否反応が出る!!
っていう人のために今回書いていこうと思います。
今回の内容になります↓↓
JavaScriptのオブジェクトをわかりやすく解説します。
実はオブジェクトってなんだか難しい内容だと思っている人が多いと思うんですけど、JavaScriptではオブジェクトはただの入れ物なんです。
オブジェクトは何を入れれるかというと、
- 変数
- 関数
この2つがオブジェクトに入れられるものになります。
前に変数にはデータしか入れれなくて、関数には処理しか入れれないよ。という内容の記事を上げてます。
実はオブジェクトは変数と関数をまとめて放りこめる入れ物になります。
ここまで一度まとめますと、
- 変数はデータを入れれる
- 関数は処理を入れれる
- オブジェクトは変数と関数を入れれる
ということになります。
ちょっとJavaScriptを触ったことがある人ならわかる例を入れていきます。
オブジェクトの例を紹介します
実はJavaScriptではデフォルトで色々なオブジェクトを用意してくれてます。
console.log()というブラウザに変数の値などをコンソールに表示するJavaScriptの処理がありますよね。
console.log()は「console」というオブジェクトの入れ物に「log()」という関数を入れてあるので、そのlog()という関数を取り出して実行しています。
console.log()の「console」の部分は実はオブジェクトだったんですね!
オブジェクトの中の関数を実行する時は「.」ドットで繋いで書くとオブジェクトの中の関数を実行することができます。
次の例をみてもらいましょう。
HTMLをJavaScriptで取得するときにdocument.querySelectorを使いますよね。
こちらは「document」というオブジェクトの中に「querySelector()」という関数があり、documentオブジェクトから「querySelector()」という関数を取り出して実行しています。
ここで感の鋭い人なら気づいた人がいると思いますが、JavaScript自体がオブジェクトで出来ています。
オブジェクトと関数の位置関係についてイメージを作ってみました。
JavaScriptの下には次の大きな仕切りとしてオブジェクトがあって、そのオブジェクト中には色々な処理が入った関数が入っているのがイメージできたんじゃないでしょうか?
log()関数を使おうと思うと、console.log()と書きます。つまり「オブジェクト」をドットで繋いで「関数名」を書くことで、オブジェクト内の関数を呼び出して使うことができるということになります。
今までよくわからずにdocumentとか、consoleとか書いていたのは、まず「オブジェクト」を呼び出していたんですね。console.log()だったら、consoleオブジェクトの中のlog()という関数を使いますよ。という意味だったんですね。
今紹介していた「オブジェクト」はデフォルトでJavaScriptが用意しているものを紹介していました。
次は自分でオブジェクトを作ることができるので、一緒に書いていきましょう。
オブジェクトを自分で作ってみよう
実はオブジェクトは自分で作ることができます。
まずは簡単にHTMLファイルを作ってください。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>デモサイト</title>
</head>
<body>
<p>デモサイトの内容</p>
<script src="js/index.js"></script>
</body>
</html>
まずは簡単にhtmlファイルを用意しました。
jsを読み込むscriptタグを書いてindex.jsを作っておいてください。
次はindex.jsでオブジェクトを作っていきます。
'use strict';
{
// オブジェクトを生成
const person = {
};
// これは配列✖️
// const person = [
// ];
}
まずはconstでオブジェクトの名前を決めます。今回は「person」というオブジェクトの名前をつけました。
オブジェクトを書くポイントは波括弧「{}」を使うことがポイントです。
これを角括弧「[]」にすると配列の定義方法になってしまいますので注意してください。
ちなみにですが、オブジェクト内の変数に当たる部分と関数にあたる部分の呼び方が変わってきます。
どうなるかというと、
- 変数 = プロパティ
- 関数 = メソッド
オブジェクト内ではこの様な呼び方に変わります。変数はプロパティ、関数はメソッドと覚えておいてください。ここからはその呼び方を使っていきますね。
では、personオブジェクトのプロパティにデータを入れていきます。
'use strict';
{
// オブジェクトを生成
const person = {
// プロパティを登録
name: ["加藤", "佐藤"],
age: 32,
gender: "male",
interests: ["music", "skiing"],
};
// これは配列✖️
// const person = [
// ];
}
「name: ["加藤", "佐藤"],」となっていますが、nameという部分は変数名と同じで、nameというプロパティの入れ物に配列で、加藤さんと佐藤さんの名前をnameというプロパティに入れています。
オブジェクトの中ではイコール「=」ではなく、コロン区切り「:」書くことでプロパティにデータを入れれます。
そして「,」で区切って改行して次のデータを入れていきます。
「age」プロパティには「32」というデータを入れていますね。
次は、メソッド(関数)もpersonオブジェクトに入れていきましょう。
bio: function() {
alert(
`${this.name[0]}、${this.name[1]} は ${this.age} 歳です。 趣味は ${
this.interests[0]} と ${this.interests[1]}です。`,
);
},
こちらが、オブジェクトにメソッドを入れる書き方になります。
プロパティと同じ感じで、「bio」の部分が関数名になります。
処理内容は先ほどプロパティで定義したものを使ってalertでダイアログボックスで表示していきます。
alertの中身にある「this」ですが、オブジェクトの中で使うと「person」を指します。なので、「this.name[0]」だったら「person.name[0]」という意味になります。
「this」は使う場所によって出力する内容が変わるので注意が必要です。
このメソッドをオブジェクトの中に追加するとこうなります。
'use strict';
{
// オブジェクトを生成
const person = {
name: ["加藤", "佐藤"],
age: 32,
gender: "female",
interests: ["music", "skiing"],
// メソッド
bio: function() {
alert(
`${this.name[0]}、${this.name[1]} は ${this.age} 歳です。 趣味は ${
this.interests[0]} と ${this.interests[1]}です。`,
);
},
};
// これは配列✖️
// const person = [
// ];
}
メソッドを追加するとこんな感じになりました。
それではpersonオブジェクトのプロパティとメソッドをコンソールに出力していきます。
こちらを追記してください。
// オブジェクト内のプロパティとメソッドを出力
console.log(person.name[0]);
console.log(person.bio());
index.js全体はこうなります。
'use strict';
{
// オブジェクトを生成
const person = {
name: ["加藤", "佐藤"],
age: 32,
gender: "female",
interests: ["music", "skiing"],
bio: function() {
alert(
`${this.name[0]}、${this.name[1]} は ${this.age} 歳です。 趣味は ${
this.interests[0]} と ${this.interests[1]}です。`,
);
},
};
// これは配列✖️
// const person = [
// ];
// オブジェクト内のプロパティとメソッドを出力
console.log(person.name[0]);
console.log(person.bio());
}
これでブラウザに表示してコンソールを見てみましょう。
ページを表示した途端にダイアログが表示されていると思います。ダイアログに表示するのがalertの機能になります。
alert内で「this.name[0]」と書いてますが、nameプロパティ内の配列一つ目のデータを出力しています。「this.age」で登録している「32」を取り出してます。「this.interests[0]」は配列一つ目の「music」を取り出してます。
ダイアログボックスのOKを押してください。
「console.log(person.name[0]);」で加藤という名前は取得できてますが、2つ目の「console.log(person.bio());」がundefinedになっています。
index.jsの「console.log(person.bio());」の部分が間違ってますね。
console.logを外して、「person.bio();」だけにしてみてください。
ダイアログはちゃんと表示されてますね。関数は処理なのでconsole.logはなくても実行できるんでしたね。
OKを押しても「undefined」が出なくなりました。
それではもう一つメソッドを追加していきます。
calc: function() {
const today = new Date();
const year = today.getFullYear();
alert(
`${this.name[0]}、${this.name[1]}は${year - person.age}年生まれです。`,
);
},
次は「calc」というメソッドを追加しました。
「new Date()」で現在の年月日のデータを取得して、「getFullYear()」で西暦のデータだけを取得しています。
そして、alertの中身の処理を見ると「year - person.age」と書いてあるので、person.ageで年齢を入れて、「現在の西暦 - 年齢」で生まれた時の西暦が取得されるということになります。
それではcalcメソッドとcalc()を書いてみましょう。現在のindex.jsです。
'use strict';
{
// オブジェクトを生成
const person = {
// プロパティを登録
name: ["加藤", "佐藤"],
age: 32,
gender: "female",
interests: ["music", "skiing"],
// メソッドを登録
bio: function() {
alert(
`${this.name[0]}、${this.name[1]} は ${this.age} 歳です。 趣味は ${
this.interests[0]} と ${this.interests[1]}です。`,
);
},
// calcメソッドを追記
calc: function() {
const today = new Date();
const year = today.getFullYear();
alert(
`${this.name[0]}、${this.name[1]}は${year - person.age}年生まれです。`,
);
},
};
// これは配列✖️
// const person = [
// ];
console.log(person.name[0]);
person.bio();
// calcを実行
person.calc(20);
}
calcメソッドを追記してから、最後の方でcalc()を実行するコードを追記しました。
それではコンソールでチェックしていきます。
現在の西暦から年齢を引いた西暦が取得できればOKです。
次はpersonオブジェクトの中身をみていきたいと思います。
console.log()の部分と、実行部分を削除して「console.log(person);」を追記していきます。
index.jsはこうなります。
'use strict';
{
// オブジェクトを生成
const person = {
// プロパティを登録
name: ["加藤", "佐藤"],
age: 32,
gender: "female",
interests: ["music", "skiing"],
// メソッドを登録
bio: function() {
alert(
`${this.name[0]}、${this.name[1]} は ${this.age} 歳です。 趣味は ${
this.interests[0]} と ${this.interests[1]}です。`,
);
},
calc: function() {
const today = new Date();
const year = today.getFullYear();
alert(
`${this.name[0]}、${this.name[1]}は${year - person.age}年生まれです。`,
);
},
};
// これは配列✖️
// const person = [
// ];
// オブジェクトの中身を見る
console.log(person);
}
実行部分をconsole.log(person);のみにします。personオブジェクトの中身をコンソールで見てみましょう。
波括弧なのでオブジェクトとして取得できますね。
左の矢印で開いてみてください。
プロパティとメソッドがちゃんと入っているのがわかりますね
次はついでなのでconsoleオブジェクトの中身も確認しておきましょう。
「console.log(console);」を追加して、console.log()でconsoleオブジェクトの中身を見ていきます。
index.jsはこうなります。
'use strict';
{
// オブジェクトを生成
const person = {
// プロパティを登録
name: ["加藤", "佐藤"],
age: 32,
gender: "female",
interests: ["music", "skiing"],
// メソッドを登録
bio: function() {
alert(
`${this.name[0]}、${this.name[1]} は ${this.age} 歳です。 趣味は ${
this.interests[0]} と ${this.interests[1]}です。`,
);
},
calc: function() {
const today = new Date();
const year = today.getFullYear();
alert(
`${this.name[0]}、${this.name[1]}は${year - person.age}年生まれです。`,
);
},
};
// これは配列✖️
// const person = [
// ];
// オブジェクトの中身を見る
console.log(person);
// consoleオブジェクトの中身を見る
console.log(console);
}
コンソールを開いて、consoleオブジェクトの中身を見ます。
consoleオブジェクトの中身にはかなりもメソッドが入っています。その中にはlogメソッドも確認できました。
これを見るとconsoleはオブジェクトとして機能していることがわかりましたね。
このようにJavaScriptではデフォルトのオブジェクトもありますし、自分でもオブジェクトを作ることができます。あまりWEB制作などでは使わないかもですが、大規模なコードになるとオブジェクトでジャンルごとに関数をまとめると見やすいコードになるかもしれませんね。
次はJavaScriptではオブジェクト指向という考え方が導入されました。そのオブジェクト指向をちょっとだけつまんで説明したいと思います。
オブジェクトとオブジェクト指向の違いを解説
JavaScriptではその仕様を決めているECMAScriptというものがあり、ECMAScript2015でオブジェクト指向が導入されました。
オブジェクト指向はクラス型プログラミングのことで、クラス型プログラミングをベースに作られている言語がRuby、C言語、Javaなどがあります。
JavaScriptもオブジェクト指向のプログラミングをそろそろ導入しないとね。となってもともとあったオブジェクトをクラス型プログラミングっぽく書けるようにして追加しました。
なので、JavaScriptでもともとあるオブジェクトとクラス型プログラミングは仕様は似たようなものになっています。
今回はちょっとだけクラス型プログラミングを書いていきたいと思います。
index.jsに先ほど書いていた部分をコメントアウトして、同じ内容をクラス型プログラミングで書いていきます。
もともと書いていた実行部分は削除してみやすくしています。
'use strict';
{
// // オブジェクトを生成
// const person = {
// // プロパティを登録
// name: ["加藤", "佐藤"],
// age: 32,
// gender: "female",
// interests: ["music", "skiing"],
// // メソッドを登録
// bio: function() {
// alert(
// `${this.name[0]}、${this.name[1]} は ${this.age} 歳です。 趣味は ${
// this.interests[0]} と ${this.interests[1]}です。`,
// );
// },
// calc: function() {
// const today = new Date();
// const year = today.getFullYear();
// alert(
// `${this.name[0]}、${this.name[1]}は${year - person.age}年生まれです。`,
// );
// },
// };
// クラスを定義
class Person {
constructor() {
// プロパティ
this.name = ["加藤", "佐藤"];
age = 32;
gender = "female";
interests = ["music", "skiing"];
}
// メソッド
bio() {
alert(
`${this.name[0]}、${this.name[1]} は ${this.age} 歳です。 趣味は ${
this.interests[0]} と ${this.interests[1]}です。`,
);
}
calc() {
const today = new Date();
const year = today.getFullYear();
alert(
`${this.name[0]}、${this.name[1]}は${year - person.age}年生まれです。`,
);
}
}
}
先ほど書いていたオブジェクトとクラスはよく似ていますよね。
クラスを定義するときは先頭で「class」と書きます。
そしてクラス名は1文字目を大文字で書くのがルールとなっていて「Person」になります(小文字でもエラーはでない)。
オブジェクトの書き方で大きく違う部分は「constructor()」だと思います。constructorの概念がちょっとむずいですね。僕も今書きながら頭を整理しています。
constructorはPersonクラスそのものです。なので、Personクラスを実行するとまずconstructorが実行されます。
- Personクラス = constructor()
と覚えてもらってもいいです。クラスのデフォルトの設定がconstructorになります。
実はPersonクラスはまだこの状態では使えないので「初期化」をします。
Personクラスを初期化するとこんな感じになります。
'use strict';
{
// // オブジェクトを生成
// const person = {
// // プロパティを登録
// name: ["加藤", "佐藤"],
// age: 32,
// gender: "female",
// interests: ["music", "skiing"],
// // メソッドを登録
// bio: function() {
// alert(
// `${this.name[0]}、${this.name[1]} は ${this.age} 歳です。 趣味は ${
// this.interests[0]} と ${this.interests[1]}です。`,
// );
// },
// calc: function() {
// const today = new Date();
// const year = today.getFullYear();
// alert(
// `${this.name[0]}、${this.name[1]}は${year - person.age}年生まれです。`,
// );
// },
// };
// クラスを定義
class Person {
constructor() {
// プロパティ
this.name = ["加藤", "佐藤"];
this.age = 32;
this.gender = "female";
this.interests = ["music", "skiing"];
}
// メソッド
bio() {
alert(
`${this.name[0]}、${this.name[1]} は ${this.age} 歳です。 趣味は ${
this.interests[0]} と ${this.interests[1]}です。`,
);
}
calc() {
const today = new Date();
const year = today.getFullYear();
alert(
`${this.name[0]}、${this.name[1]}は${year - person.age}年生まれです。`,
);
}
}
// 初期化
const p001 = new Person();
}
初期化のことを「インスタンス」ともいいます。
「p001」の部分は変数名なのでなんでもいいです。初期化したものが入った「p001」を使い、メソッドを実行してみましょう。
'use strict';
{
// // オブジェクトを生成
// const person = {
// // プロパティを登録
// name: ["加藤", "佐藤"],
// age: 32,
// gender: "female",
// interests: ["music", "skiing"],
// // メソッドを登録
// bio: function() {
// alert(
// `${this.name[0]}、${this.name[1]} は ${this.age} 歳です。 趣味は ${
// this.interests[0]} と ${this.interests[1]}です。`,
// );
// },
// calc: function() {
// const today = new Date();
// const year = today.getFullYear();
// alert(
// `${this.name[0]}、${this.name[1]}は${year - person.age}年生まれです。`,
// );
// },
// };
// クラスを定義
class Person {
constructor() {
// プロパティ
this.name = ["加藤", "佐藤"];
this.age = 32;
this.gender = "female";
this.interests = ["music", "skiing"];
}
// メソッド
bio() {
alert(
`${this.name[0]}、${this.name[1]} は ${this.age} 歳です。 趣味は ${
this.interests[0]} と ${this.interests[1]}です。`,
);
}
calc() {
const today = new Date();
const year = today.getFullYear();
alert(
`${this.name[0]}、${this.name[1]}は${year - person.age}年生まれです。`,
);
}
}
// 初期化
const p001 = new Person();
// メソッドを実行
p001.bio();
}
「p001」にドットで繋いでbio()メソッドを実行しています。この辺りはオブジェクトと一緒ですね。
ブラウザを確認してみましょう。
ダイアログボックスにこの内容が出てくればOKです。
どうですか?オブジェクトとクラスは微妙に書き方が違えど、かなり似ていますよね。
次はconstructorに引数を追加して、nameプロパティの配列にもう一人追加してみましょう。
'use strict';
{
// // オブジェクトを生成
// const person = {
// // プロパティを登録
// name: ["加藤", "佐藤"],
// age: 32,
// gender: "female",
// interests: ["music", "skiing"],
// // メソッドを登録
// bio: function() {
// alert(
// `${this.name[0]}、${this.name[1]} は ${this.age} 歳です。 趣味は ${
// this.interests[0]} と ${this.interests[1]}です。`,
// );
// },
// calc: function() {
// const today = new Date();
// const year = today.getFullYear();
// alert(
// `${this.name[0]}、${this.name[1]}は${year - person.age}年生まれです。`,
// );
// },
// };
// クラスを定義
class Person {
constructor(name) { // ①引数にnameを追記
// プロパティ
this.name = ["加藤", "佐藤"];
this.name.push(name); // ②追記
this.age = 32;
this.gender = "female";
this.interests = ["music", "skiing"];
}
// メソッド
bio() {
// ③${this.name[2]}を追記
alert(
`${this.name[0]}、${this.name[1]}、${this.name[2]}は ${this.age} 歳です。 趣味は ${
this.interests[0]} と ${this.interests[1]}です。`,
);
}
calc() {
const today = new Date();
const year = today.getFullYear();
alert(
`${this.name[0]}、${this.name[1]}は${year - person.age}年生まれです。`,
);
}
}
// 初期化
const p001 = new Person('tono'); // ④'tono'を追記
// メソッドを実行
p001.bio();
}
まずやることをリストしました。
- constructorの()にnameの引数を追加
- 「this.name = ["加藤", "佐藤"];」下に「this.name.push(name);」を追記
- bio()メソッドのalertの中に${this.name[2]}を追記
- Personの()の中に'tono'を追記
リストの通りに変更してみてください。
これでブラウザをリロードすると、
tonoさんが追加されましたね。この引数の動きがどうなっているかというと、
Personクラスとconstructorは一緒なので、Personクラスの初期化に値を入れると、それがconstructorのname引数に渡されて、this.nameプロパティの配列にpushされるという流れになります。
このように引数を追加することで後からもプロパティを追加できます。これはオブジェクトでも一緒なので試してみてください。
以上、今回はオブジェクトって何?でした。
今回のコーディングデータをダウンロードできます。
もし実装などで上手くいかないことありましたら、下記ボタンからご相談いただけましたらありがたいです。