【JavaScript】特定のキーを除いたオブジェクトをコピーする方法(シャローコピーとディープコピー)
JavaScriptであるオブジェクトをコピーしたいけれど、特定のキー(プロパティ)だけは含めたくない——そんな場面は開発でよくあります。最もシンプルな方法は、まずオブジェクト全体をコピーし、その後不要なプロパティを削除するというアプローチです。
ただし、オブジェクトのコピーには「浅いコピー(シャローコピー)」と「深いコピー(ディープコピー)」という2種類がある点に注意が必要です。それぞれの特徴と使い方を見ていきましょう。
シャローコピー(浅いコピー)とは
シャローコピーは、可能な限り最小限の複製を行う方法です。コレクションの「構造」だけがコピーされ、中身の要素までは複製されません。つまり、元のオブジェクトとコピー先がネストされた内部オブジェクトを共有する状態になります。
シャローコピーを作成するには、Object.assign() やスプレッド構文 { ...obj } を使います。
サンプルコード
let innerObj = {
a: 'b',
c: 'd'
}
let obj = {
x: "test",
y: innerObj
}
// シャローコピーを作成
let copyObj = Object.assign({}, obj);
// copyObj.y と obj.y は同じ innerObj を参照しているため、
// 変更が両方に反映される
innerObj.a = "test"
console.log(obj)
console.log(copyObj)実行結果
{ x: 'test', y: { a: 'test', c: 'd' } }
{ x: 'test', y: { a: 'test', c: 'd' } }このように、シャローコピーは再帰的にクローンを作るわけではなく、トップレベルのプロパティだけをコピーします。ネストされたオブジェクトへの変更は、元のオブジェクトにも影響するので注意してください。
ディープコピー(深いコピー)とは
ディープコピーは、すべてを完全に複製する方法です。元のコレクション内の全要素が個別に複製されるため、コピー後に一方を変更しても他方には影響しません。
手軽な方法としては JSON.parse(JSON.stringify()) を使うやり方が知られています。
サンプルコード
let innerObj = {
a: 'b',
c: 'd'
}
let obj = {
x: "test",
y: innerObj
}
// ディープコピーを作成
let copyObj = JSON.parse(JSON.stringify(obj))
// 元の innerObj を変更しても copyObj には影響しない
innerObj.a = "test"
console.log(obj)
console.log(copyObj)実行結果
{ x: 'test', y: { a: 'test', c: 'd' } }
{ x: 'test', y: { a: 'b', c: 'd' } }実行結果を見ると、元のオブジェクトの a の値が "test" に変わっている一方、コピー先は元の値 'b' のままになっています。これがシャローコピーとの大きな違いです。
なお、モダンな環境では structuredClone() を使えば、関数や Date オブジェクトなども安全にディープコピーできます。JSON.stringify 方式では関数や undefined が失われるという制限があるため、状況に応じて使い分けるのがおすすめです。
不要なキーの削除方法
上記のいずれかの方法でコピーを作成したら、delete キーワードを使って不要なプロパティを削除できます。
サンプルコード
let original = { x: 'test', y: { a: 'test', c: 'd' } }
let copy = JSON.parse(JSON.stringify(original))
delete copy['x']
console.log(copy)
console.log(original)実行結果
{ y: { a: 'test', c: 'd' } }
{ x: 'test', y: { a: 'test', c: 'd' } }このように、コピー側からのみ x を削除でき、元のオブジェクトはそのまま保持されます。
補足:分割代入(レスト構文)でより簡潔に書く
ES2018以降の環境では、分割代入のレスト構文を使うことで、「特定のキーを除いたコピー」を1行で作成できます。削除処理も不要になるため、より簡潔で意図が伝わりやすいコードになります。
const original = { x: 'test', y: { a: 'test', c: 'd' } }
// x 以外のプロパティだけを取り出す
const { x, ...copy } = original
console.log(copy)
// { y: { a: 'test', c: 'd' } }ただしこの方法はシャローコピーである点には注意が必要です。ネストされたオブジェクトまで完全に独立させたい場合は、レスト構文と structuredClone() を組み合わせるとよいでしょう。
const { x, ...rest } = original
const deepCopy = structuredClone(rest)まとめ
- 特定のキーを除いたコピーは「コピーしてから delete で削除」が基本の流れ
- シャローコピー:
Object.assign()やスプレッド構文 — ネストした要素は参照共有される - ディープコピー:
JSON.parse(JSON.stringify())やstructuredClone()— 完全に独立した複製ができる - モダンな書き方なら、レスト構文
{ x, ...rest }で除外対象以外を一括取得できる
用途に応じてコピーの種類を選び、目的に合った方法でオブジェクトを扱いましょう。
-
JavaScriptで特定のキーを除外してオブジェクトを分割代入する方法
JavaScriptでは、レストパラメータ(...)を使った分割代入(デストラクチャリング)を利用することで、オブジェクトから特定のキーだけを取り出し、残りのプロパティをまとめて別の変数に格納できます。この手法は、オブジェクトから不要なプロパティを除外したい場合に非常に便利です。 以下のコードは、オブジェクトから「firstName」キーを除外し、残りのプロパティを「restParam」にまとめて取得する例です。 コード例 <!DOCTYPE html> <html lang=ja> <head> <meta charset=UTF-8 />
-
【JavaScript入門】Symbolを使ってオブジェクトごとに一意のIDを作成する方法
はじめにJavaScriptでオブジェクトごとに一意のIDを作成したい場合、Symbol()を使うのが最も簡単かつ確実な方法です。Symbolは呼び出されるたびに必ず新しい一意の値を生成するため、たとえ同じ説明文字列を渡しても、二度と同じ値にはなりません。以下は、各オブジェクトに対して一意のIDを作成するサンプルコードです。実装例<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewp