メインコンテンツまでスキップ

オブジェクト

今まで扱ってきた JavaScript の「値」は、文字列、数値、論理値の 3 つでした。オブジェクトは、複数の値をひとまとまりにして名前と値のペアで管理できる、新たな種類の値です。また、JavaScript におけるオブジェクトではない値を総称して、プリミティブな値といいます。

オブジェクトの生成

const student1 = {
name: "Becky Jones",
age: 20,
};
document.write(
`Hello. I am ${student1.name}. I am ${student1["age"]} years old.`,
);

オブジェクトを生成するには、{から}までで表されるオブジェクトリテラルを用います。括弧内では、名前: 値のペアをコンマで区切って記述します。

ヒント

リテラルとは、値を直接生成するための構文です。たとえば、3は数値を生成するための数値リテラルですし、'Hello'は文字列を生成するための文字列リテラルです。

オブジェクトの内部にアクセスするためには、ドット記法(.)またはブラケット記法([])を用います。多くの場合、student1.namestudent1['name']は等価です。可読性の観点からドット記法を用いる場合がほとんどですが、ブラケット記法では内部に式を記述できるため、アクセスするプロパティを動的に制御することができます。

ネストされたオブジェクト

student1.namestudent1.ageを、student1プロパティと呼びます。プロパティには任意の値を含むことができるため、当然のことながらオブジェクトのプロパティにオブジェクトを指定することもできます。

const student2 = {
name: "Sakura",
scores: {
math: 90,
science: 80,
},
};
document.write(`student2の数学の点数は${student2.scores.math}です。`);

上記の例において、student2scoresプロパティには、オブジェクト{ math: 90, science: 80 }が指定されています。このオブジェクトのmathプロパティにアクセスするために、student2.scores.mathと記述しています。

オブジェクトを引数や戻り値に持つ関数

オブジェクトも値の一種ですので、当然のことながら関数の引数として渡したり、戻り値として返したりすることができます。

function introduce(person) {
document.write(`I am ${person.name}. I am ${person.age} years old.`);
}
introduce({ name: "Becky Jones", age: 20 });

上の例では、introduce関数にnameプロパティとageプロパティを持つオブジェクトを渡しています。

オブジェクトと参照

次のコードの実行結果を予想してみてください。

const taro = {
name: "太郎",
age: 20,
};

const hanako = taro;
hanako.name = "花子";

document.write(taro.name);

驚くべきことに、このプログラムの実行結果は花子になります。というよりそもそも、constで宣言したはずの変数hanakoに再代入が行われているように見えますが、これは許されるのでしょうか。

この結果のカラクリは、JavaScript の持つ参照という仕組みにあります。実は、

{ name: '太郎', age: 20 };

のようにオブジェクトリテラルを使用したとき、この式の値は、オブジェクトそのものではありません。オブジェクト自体はメモリ(コンピューターが一時的に値を保存しておく場所)に生成されるのですが、その式の値は生成されたオブジェクトへの参照、つまり場所を指し示す値でしかないのです。

オブジェクトへの参照

taro.age = 18;

などとしてもtaro自体が書き換えられるわけではなく、参照が指し示す値を書き換えているだけに過ぎません。このため、constによる制約は満たされているのです。

上の例では、taroの値をhanakoに代入することにより、taroが持っていたオブジェクトへの参照と同じものをhanakoが持つことになります。参照先のオブジェクトは全く同じものですので、hanako.nameを変更した場合、taro.nameも書き変わってしまうことになるのです。

課題

以下のコードを実行したのち、変数sakuraはどのような値となるでしょうか。

const sakura = {
name: "Sakura",
scores: {
math: 90,
science: 80,
},
};
let sakuraScores = sakura.scores;
sakuraScores.math = 100;
sakuraScores = {
math: 80,
science: 90,
};

なお、オブジェクトの中身を見るためには、開発者ツールを利用すると便利です。ネストされたオブジェクトも、ツリー形式で簡単に表示できます。console.logをしたり、ブレークポイントで止めたりして変数の値を確認してみましょう。debugger文を使用することもできます。