オブジェクト
今まで扱ってきた 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.name
とstudent1['name']
は等価です。可読性の観点からドット記法を用いる場合がほとんどですが、ブラケット記法では内部に式を記述できるため、アクセスするプロパティを動的に制御することができます。
ネストされたオブジェクト
student1.name
やstudent1.age
を、student1
のプロパティと呼びます。プロパティには任意の値を含むことができるため、当然のことながらオブジェクトのプロパティにオブジェクトを指定することもできます。
const student2 = {
name: "Sakura",
scores: {
math: 90,
science: 80,
},
};
document.write(`student2の数学の点数は${student2.scores.math}です。`);
上記の例において、student2
のscores
プロパティには、オブジェクト{ 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
文を使用することもできます。