【初心者向け】JavaScriptでオブジェクトのディープクローンを作成する方法を実例付きで解説
はじめに
JavaScriptでは、単純な代入(=)やObject.assign()などによるコピーはシャローコピー(浅いコピー)となり、元のオブジェクトとプロパティへの参照が共有されてしまいます。そのため、一方を変更するともう一方にも影響が及びます。これを防ぐには、参照関係まで完全に切り離したディープクローン(深いコピー)を作成する必要があります。
本記事では、JSON.parse(JSON.stringify()) を使ったシンプルな方法で、オブジェクトのディープクローンを作成する例を紹介します。
ディープクローンのサンプルコード
以下のコードでは、ボタンをクリックすると元のオブジェクト obj の firstName プロパティを変更し、クローン元とクローン先の値が互いに影響しないことを確認できます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
body {
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
}
.result {
font-size: 18px;
font-weight: 500;
color: rebeccapurple;
}
</style>
</head>
<body>
<h1>JavaScriptでオブジェクトをディープクローンする</h1>
<div class="result"></div>
<button class="Btn">CLICK HERE</button>
<h3>上のボタンをクリックすると obj オブジェクトのディープクローン結果を確認できます</h3>
<script>
let BtnEle = document.querySelector(".Btn");
let resEle = document.querySelector(".result");
let obj = {
firstName: "Rohan",
lastName: "Sharma",
age: 22,
rollNo: "A12",
};
let obj1 = JSON.parse(JSON.stringify(obj));
BtnEle.addEventListener("click", () => {
obj.firstName = "Mohit";
resEle.innerHTML = "obj.firstName =" + obj.firstName + "<br>";
resEle.innerHTML += "obj1.firstName = " + obj1.firstName + "<br><br>";
});
</script>
</body>
</html>コードのポイント
JSON.stringify(obj):オブジェクトをJSON形式の文字列に変換します。この時点で元のオブジェクトとの参照関係が切れます。JSON.parse(...):文字列を新しいオブジェクトとして再構築します。- この2段階の処理により、ネストされたプロパティも含めて完全に独立した複製(ディープクローン)が得られます。
実行結果
上記のコードを実行すると、以下のような画面が表示されます。

「CLICK HERE」ボタンをクリックすると、次のように表示されます。

元のオブジェクト obj.firstName は「Mohit」に変更されていますが、クローンである obj1.firstName は「Rohan」のまま維持されていることが確認できます。つまり、両者は完全に独立しているため、片方を変更してももう片方には一切影響しません。
注意点と補足
JSON.parse(JSON.stringify()) は手軽で便利な反面、以下のような制限があります。
DateオブジェクトやMap・Setなどの特殊な型が正しく復元されない- 関数や
undefinedのプロパティが失われる - 循環参照を含むオブジェクトではエラーになる
より堅牢なディープクローンが必要な場合は、ES2022以降で利用可能な構造化クローンアルゴリズム structuredClone(obj) の使用を検討してください。
-
【初心者向け】JavaScriptの非同期関数(async/await)をサンプルコード付きで解説
非同期関数(async function)とはJavaScriptの非同期関数は、asyncキーワードを付けて定義する特別な関数です。ES2017(ES8)で標準仕様に組み込まれ、従来のコールバック関数よりも簡潔で読みやすい形でPromiseを扱えるようにするために導入されました。async関数の内部ではawaitキーワードを使用できます。awaitを付けた箇所では処理の流れが一時停止し、対象のPromiseが完了(resolveまたはreject)するまで待機します。この仕組みにより、非同期処理をあたかも同期処理のような直感的なコードとして書ける点が最大のメリットです。押さえておきたいポイン
-
JavaScriptにおける継承の基本を具体例で解説
JavaScriptは、クラスベースではなくプロトタイプベースのオブジェクト指向言語です。そのため、継承はprototype(プロトタイプ)オブジェクトを通じて実現されます。コンストラクタ関数のprototypeプロパティにメソッドやプロパティを追加すると、そのコンストラクタから生成されたすべてのインスタンスが、それらを共有して利用できるようになります。 プロトタイプによる継承の仕組み JavaScriptでは、インスタンスからプロパティやメソッドが参照されるとき、まずオブジェクト自身を検索し、見つからなければプロトタイプチェーンをたどって上位のオブジェクトへと探しに行きます。これにより、各イ