Q1const copied = [...items]; のあとに copied.push("X") すると、元の items はどうなりますか?
スプレッド構文 — コピー・結合・設定の上書き
配列やオブジェクトの中身をその場に並べるスプレッド構文で、元を変えずにコピー・結合し、既定の設定にユーザーの変更だけを重ねる書き方を扱います。
在庫ありの商品リストと入荷待ちの商品リストを 1 本にまとめたい、既定の設定にユーザーが変更した項目だけを重ねたい。こうした場面では、元のデータをそのまま残したまま、中身を並べた新しい配列やオブジェクトを作ります。
この記事では、そのためのスプレッド構文と、同じキーが重なったときにどちらが残るかを扱います。
中身をその場に並べる — スプレッド構文
在庫ありの商品リストと入荷待ちの商品リストを 1 本にまとめたいとき、push で 1 件ずつ足していくと元の配列が書き換わります。元のリストはそのまま残したまま、中身を並べた新しい配列を作りたい場面です。
スプレッド構文(... を値の前に付けて、配列やオブジェクトの中身をその場に並べる書き方)を使うと、const allItems = [...inStock, ...backOrder]; で結合した新しい配列を作れます。[...inStock] のように 1 つだけ書けば、同じ中身の別の配列を作るコピーです。
オブジェクトでも { ...product } の形で同じように書けます。ただしこれは1 段目だけを写すコピーで、内側にオブジェクトや配列を持つ場合の挙動は、参照とコピーの記事で扱います。
... は書く場所で役割が変わります。= の左側に書けば残りをまとめる rest、右側の [] や {} の中に書けば中身を並べるスプレッドです。記号は同じですが、まとめる側と広げる側で向きが逆です。
const inStock = ["ペン", "テープ"];
const backOrder = ["ボード"];
// 2 つを並べた新しい配列を作る
const allItems = [...inStock, ...backOrder];
console.log(allItems.join(", ")); // ペン, テープ, ボード
// 元の配列はそのまま
console.log(inStock.length); // 2
// 途中に個別の値を混ぜて書ける
const featured = ["今週のおすすめ", ...inStock];
console.log(featured.length); // 3
// オブジェクトも同じ書き方でコピーできる
const product = { name: "テープ", price: 380 };
const copied = { ...product };
console.log(copied.price); // 380
設定を重ねる — あとに書いたほうが勝つ
アプリの設定は、既定値をひととおり用意しておき、ユーザーが変更した項目だけを上書きする形にすることがあります。変更された項目だけを 1 つずつ調べて代入すると、項目が増えるたびにコードを足す必要があります。
オブジェクトのスプレッド構文を 2 つ並べて { ...defaultSettings, ...userSettings } と書くと、同じキーはあとに書いたほうの値で上書きされます。ユーザーが指定していないキーは既定値のまま残ります。
書く順序がそのまま優先順位になるので、既定値を先に、優先したい値をあとに置きます。
const defaultSettings = { theme: "light", itemsPerPage: 20, notifications: true };
const userSettings = { theme: "dark" };
const merged = { ...defaultSettings, ...userSettings };
console.log(merged.theme); // dark(あとに書いたほうが勝つ)
console.log(merged.itemsPerPage); // 20(ユーザー側に無いので既定値のまま)
// 順序を逆にすると既定値が勝ってしまう
const reversed = { ...userSettings, ...defaultSettings };
console.log(reversed.theme); // light
// あとの側の値が undefined でも、キーがあれば上書きされる
const partial = { theme: undefined };
const broken = { ...defaultSettings, ...partial };
console.log(broken.theme); // undefined
undefined でも上書きされる
重ねる側にキーがあれば、値が undefined でも上書きが起こります。フォームから受け取った未入力の項目をそのまま重ねると、既定値が消えて undefined に置き換わります。値が入っているときだけ使いたい項目は、userSettings.theme ?? defaultSettings.theme のように 1 項目ずつ判定します。
理解度チェック
まずは1問ずつ答えてみましょう。
Q2const merged = { ...defaults, ...user }; で、両方にある同じキーの値はどうなりますか?
Q3重ねる側のオブジェクトにキーがあり、その値が undefined だったとき、既定値はどうなりますか?