「Reactを学習していると突然登場する分割代入が何か分からない」
「配列とオブジェクトにconstを指定しているのに中身を書き換えられてしまう」
「ググった時に分割代入をしている記事とそうでない記事を見かけて不思議に感じている」
本日は分割代入の説明に始まり、JavaScriptにおける配列とオブジェクトのちょっとした豆知識まで紹介していきます。
動画もあるので必要に応じてどうぞ。
JavaScriptの分割代入とは書き方のテクニック
例えば以下のようなオブジェクトがあったとして、各プロパティの出力や変更は「オブジェクト名」「プロパティ名」を指定すれば操作できます。
const student = {
id: "0001",
name: "山田",
age: 18
};
console.log(student.id); // "0001"と出力される
console.log(student.name); // "山田"と出力される
console.log(student.age); // "18"と出力される
分割代入とは上記の内容を「書き方を変えた」だけで同じことをやっています。
const student = {
id: "0001",
name: "山田",
age: 18
};
// 分割代入で書いた場合
const {id,name,age} = student;
console.log(id); // "0001"と出力される
console.log(name); // "山田"と出力される
console.log(age); // "18"と出力される
「student」というオブジェクトを定数のオブジェクト型で再定義しているだけなんですが、その後の操作では「student」という記載を省略できています。
簡単に言うと分割代入はコレだけの話です。
また分割代入ではオブジェクトのプロパティ名を自分のオリジナルに変更することもできます。
const student = {
id: "0001",
name: "山田",
age: 18
};
// 分割代入でidをnumberに名称変更
const {id: number,name,age} = student;
console.log(id); // エラーになる
console.log(number); // "0001"と出力される
console.log(name); // "山田"と出力される
console.log(age); // "18"と出力される
さらに特定のプロパティに値の初期値を指定することもできます。
const data = {
id: "0001",
title: "タイトル",
};
const { id, title, desc = "" } = data;
console.log(id);
console.log(title);
console.log(desc); // descが無いと空文字に、descが設定されていると値を出力する
APIでもプロパティによっては必ずデータがあるとは限らないものってありますよね。
そういった不確定要素のあるものに初期値の設定が便利です。
API関連で言うとネストされたオブジェクト形式が最近ではよく見ます。
ネストされている場合の分割代入は注意が必要で、以下のように親と子はそれぞれ別で分割する必要があります。
const place = {
area: "関東エリア",
pre: {
tokyo: "東京",
saitama: "埼玉",
kanagawa: "神奈川",
},
};
// 親要素のpreのみを使う場合には、pre:{...}の部分とは別途でpreと分割しておく
const { area, pre: { tokyo, saitama, kanagawa }, pre } = place;
console.log(area); // 「関東エリア」と出力される
console.log(tokyo); // 「東京」と出力される
console.log(saitama); // 「埼玉」と出力される
console.log(kanagawa); // 「神奈川」と出力される
console.log(pre); // 「{tokyo: "東京",saitama: "埼玉",kanagawa: "神奈川"}」と出力される
JavaScriptの初学者向けのコンテンツでは登場しないので、ReactのようなモダンJSを触り出した時に突然現れて難しく感じますよね。
ちなみにReactの場合ではpropsの管理に分割代入がよく使われます。
例えば上記のコードは以下のような関数に利用することができます。
const place = {
area: "関東エリア",
pre: {
tokyo: "東京",
saitama: "埼玉",
kanagawa: "神奈川",
},
};
const text = (place) => {
console.log(
`${place.area}は${place.pre.tokyo},${place.pre.saitama},${place.pre.kanagawa}です`
);
};
text(place); // 「関東エリアは東京、埼玉、神奈川です」と出力される
関数textはこのような書き方から、さらに簡潔な書き方に変更できます。
関数textの引数部分で分割代入を使った以下のようなものです。
const place = {
area: "関東エリア",
pre: {
tokyo: "東京",
saitama: "埼玉",
kanagawa: "神奈川",
},
};
// 関数の引数にも分割代入が使えて、ReactのPropsはこの原理で動く
const text = ({ area, pre: { tokyo, saitama, kanagawa } }) => {
console.log(`${area}は${tokyo},${saitama},${kanagawa}です`);
};
text(place); // 「関東エリアは東京、埼玉、神奈川です」と出力される
こちらの方が短く書けていますし、いわゆるReactのコンポーネントという作り方に非常に似ていますよね。
Reactをいきなり触ると書き方が独特に感じられるかもしれませんが、ほとんどはJavaScriptの書き方から影響されているわけです。
JavaScriptの配列、オブジェクトのハマりポイント
分割代入とはオブジェクトの書き方のテクニックであることを紹介しました。
この流れでオブジェクトに関する初学者ハマりポイントも紹介します。
配列でも同じ内容になっています。
const student = {
id: "0001",
name: "山田",
age: 18
};
student.id = "0002";
console.log(student.id); // "0002"と出力される
上記のようにidというプロパティの値を変更してみました、分かりやすくするために分割代入を使わずに行っています。
察しの良い方なら気付かれたと思いますが、オブジェクトstudentは定数で扱っているのに変更が行われています。
自分も含め初学者向けの学習では「constは変更できない」と理解させられたはずです。
こちらエラーではなく公式ドキュメントにも記載がある正しい書き方なんです。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/const
やや難しいですがザックリ表現すると「constは場所が変えれられないだけで、中身は変更できる」ということです。
const number = "111";
number = "222";
console.log(number); // エラーになる
例えば上記のような内容であればスッと理解できるかと思います。
定数numberに違う文字列を入れようとするとエラーになります。
「中身が変えられない」と自分も理解していたんですが、正確には文字列という場所が変更できないことを意味しています。
先ほどから「場所」と言っていますが、コンピューターの世界では「メモリ」と言われるものです。
もう一度オブジェクトを例にしてみます。
const obj = {
id: "111"
};
obj = "222";
console.log(obj); // エラーになる
上記の書き方も「{ id: “111” }」を「222」という形で場所を変えようとしているのでエラーになります。
一方で以下のようにオブジェクトのプロパティの値は場所ではないので変更できるわけです。
const obj = {
id: "111"
};
obj.id = "222";
console.log(obj.id); // "222"が出力される
初学者の方からすると何とも言えない不思議な現象に見えますよね。
理解しづらければ最初のうちは「オブジェクトと配列はconstでも変更できる」と覚えてしまっても良いでしょう。
「constだから絶対安心」と思っていると後々ハマりますので。
オブジェクト、配列でも定数で固定したい
ここまでの話から「じゃあオブジェクトと配列は固定できないの?」と思われた方がいるかもしれません。
結論、専用の関数を使うと「プロパティの変更を出来なくする」ことが可能です。
//オブジェクト、配列を変更禁止にする
const student = {
id: "0001",
name: "山田",
age: 18
};
Object.freeze(student);
student.id = "0002";
console.log(student.id); // "0001"のまま出力される
JavaScriptでは「オブジェクトフリーズ」という関数があり、そちらの引数に固定したいオブジェクトや配列を入れてあげればOKです。
1点注意なのが変更できなくなるだけで、エラーになるわけではありません。
万が一、変更を加えようとしても何も変わらずデータが出力され続けます。
「定数に変更を加えようとしたら、あえてエラーにして処理を止めたい」といった場合には上記の内容に別の処理を加えてあげる必要があります。
そんな感じで分割代入を皮切りにJavaScriptのオブジェクトについての深掘りをしてみました。
一番は自分で手を動かして実験してみることですので、ぜひ色々と試してみてください。