VIDEO LESSON
JavaScriptのstructuredClone():入れ子のデータを独立してコピーするの解説動画
再生時間 7:53動画を別のタブで開く ↗
動画の字幕・文字起こしを読む
再生中の字幕を濃い黒で表示し、一番上に追従します。字幕の行を選ぶと、その位置から再生できます。
- 0:00こんにちは。
- 0:00今回はジャバスクリプトのストラクチャードクローンを紹介します。
- 0:05入れ子になったデータを、元とは独立した形で深くコピーするグローバル関数です。
- 0:10設定画面で入力を変更しても、保存するまでは元の設定を残したい。
- 0:15そんな場面では、内側まで独立した編集用データが必要になります。
- 0:19単に別の変数へ代入しただけでは、同じデータを指し続けてしまいます。
- 0:24この動画では、浅いコピーとの違い、基本の使い方、循環参照の扱い、コピーできない値、
- 0:29そして転送オプションまで、実行結果と一緒に学びます。
- 0:33身近なコピー手段との住み分けを理解すると、場面ごとに迷わず選べるようになります。
- 0:39まず、浅いコピーとの違いを確認します。
- 0:42オブジェクトを別の変数へ代入しても、それは同じデータを指しているだけです。
- 0:49スプレッド構文で外側だけをコピーしても、内側のオブジェクトは元のものと共有されたままになります。
- 0:57そのため、コピー側の内側を変更すると、元のデータまで変わってしまうのです。
- 1:03一方、ストラクチャードクローンで作った深いコピーでは、内側のオブジェクトも別物として複製されます。
- 1:12コピー側をいくら変更しても、元には影響しません。
- 1:16編集用データを作るときに必要なのは、この独立性です。
- 1:20この共有の仕組みは参照と呼ばれる考え方で、ジャバスクリプトを学ぶうえでの大切な土台でもあります。
- 1:29呼び出し方を確認します。
- 1:31第一引数にコピーしたい値を渡し、第二引数のオプションは省略できます。
- 1:36戻り値はコピーされた値で、オブジェクトを渡した場合は、元とは別のオブジェクトになります。
- 1:43注意したいのは、処理が同期的である点です。
- 1:47戻り値はプロミスではなく、その場でコピーが完成します。
- 1:51大量のデータを頻繁にコピーすると、その間、呼び出し側の処理が待たされてしまいます。
- 1:58そのため、コピーは編集開始時など、必要なタイミングと範囲に絞って使うのが基本です。
- 2:05対応しているかどうかは、関数として存在するかを実行前に確かめることもできます。
- 2:11記事の中心となる例を見ます。
- 2:13ユーザー名と通知設定を持つプロフィール、タグの配列、そして更新日時を持つ設定オブジェクトを用意します。
- 2:21これをストラクチャードクローンでコピーし、編集用データを作ります。
- 2:27そのうえで、コピー側だけ、通知をオフにし、タグを追加し、日時を一日進めます。
- 2:33ポイントは、変更がすべてコピー側に閉じていることです。
- 2:37元の設定は手つかずで残るため、ユーザーがキャンセルすれば、編集用データを捨てるだけで済みます。
- 2:45保存が決まったときだけ、編集結果を反映すればよいのです。
- 2:49この形は、フォームの編集画面で特によく使われる、実務に近いパターンです。
- 2:55実行結果を読みます。
- 2:57元の通知はトゥルーのまま、編集用の通知だけがフォルスになっています。
- 3:02タグも、元はジャバスクリプトだけですが、編集用にはノード・ジェイエスが追加されています。
- 3:09日時も、元は九月一日、編集用は九月二日と分かれました。
- 3:13さらに大切なのは、日時が文字列に化けていない点です。
- 3:17コピー後もデートとして扱え、日時のメソッドをそのまま使えます。
- 3:22内側のプロフィールが元と別物であることも確認できました。
- 3:26この出力はノード・ジェイエスの実機でも確認済みで、記事の期待出力と完全に一致しています。
- 3:33ユーティーシーで日時をそろえているため、この結果は実行環境の地域設定に左右されません。
- 3:40少し特殊な例として、循環参照を見ます。
- 3:43オブジェクトが自分自身を参照しているデータを、循環参照と呼びます。
- 3:47文字列化によるコピーでは、この形はエラーになりがちです。
- 3:52しかしストラクチャードクローンは、循環参照をそのままコピーできます。
- 3:57コピーは元とは別物であり、コピー側の自己参照は、コピー自身を正しく指します。
- 4:02元を指し続けることもありません。
- 4:04結果は順にトゥルー、トゥルー、フォルスとなり、実機でも確認済みです。
- 4:09循環をほどく処理を自分で書く必要がないのは、この関数の大きな強みです。
- 4:15同じオブジェクトへの参照が複数ある場合も、その関係はコピー側で正しく保たれます。
- 4:20コピーできる値の範囲を確認します。
- 4:23通常のオブジェクトや配列だけでなく、日時を表すデート、キーと値の組を保つマップ、
- 4:28重複のない集合であるセット、正規表現なども対象です。
- 4:33数値や文字列のような基本的な値は、そのままコピーされます。
- 4:37文字列化を経由する昔ながらの方法では、日時が文字列になったり、マップやセットが壊れたりしましたが、
- 4:42この関数なら型を保ったまま複製できます。
- 4:47ただし、ブラウザー専用のオブジェクトまで、ノード・ジェイエスで同じように扱えるわけではありません。
- 4:55環境をまたぐ場合は、共通して使える値に絞ってください。
- 4:59対応範囲の広さが、単純な文字列化によるコピーとの大きな違いになっています。
- 5:04失敗例を確認します。
- 5:06設定値と一緒に、保存処理のような関数を持つオブジェクトを渡すと、コピーは成功しません。
- 5:12関数だけを無視して残りをコピーするのではなく、呼び出し全体が失敗し、データクローンエラーという名前の例外が発生します。
- 5:21例外は同期的に発生するため、トライ・キャッチで捕まえることができます。
- 5:27実務では、テーマのようなデータと、保存処理のような振る舞いを分け、データ側だけをコピーする設計にすると扱いやすくなります。
- 5:36想定外の例外まで握りつぶさず、名前を確認してから処理する習慣も大切です。
- 5:42シンボルを含めた場合も、同様に例外になります。
- 5:46コピー前に中身を見直しましょう。
- 5:48もう一つの注意点は、振る舞いまでは複製されないことです。
- 5:52独自に作ったクラスのインスタンスを渡しても、メソッドを持った同じ種類のインスタンスにはなりません。
- 5:58プロトタイプやプライベートな要素、プロパティの読み取り専用といった細かな設定も、
- 6:01保持されません。
- 6:04正規表現の検索位置も、コピーでは引き継がれません。
- 6:08ドムノードも対象外です。
- 6:09つまり、この関数が複製するのは、あくまでデータの構造です。
- 6:13コピーしたいものがデータなのか、振る舞いを持つインスタンスなのかを、先に判断してください。
- 6:19読み取り専用だった項目が、コピー側では書き換え可能になる点も、見落としやすい変化です。
- 6:24最後に、転送オプションを押さえます。
- 6:27第二引数にトランスファーを指定すると、指定した転送可能な資源が、コピーではなく移動になります。
- 6:34バイト配列のバッファーを転送する例では、転送先では中身を読めますが、元のバッファーは切り離され、
- 6:38長さがゼロになります。
- 6:42指定するのは配列そのものではなく、そのバッファーである点にも注意してください。
- 6:48編集前のデータを残したい今回のような用途では、このオプションは省略するのが正解です。
- 6:54転送は、元を手放してよい場面専用の仕組みと覚えてください。
- 6:59同じバッファーを別のビューが参照している場合、そのビューにも影響が及びます。
- 7:04まとめです。
- 7:05ストラクチャードクローンは、入れ子のデータを独立して深くコピーする関数で、
- 7:10循環参照や日時、マップなども扱えます。
- 7:14導入時の判断は三つです。
- 7:16まず、コピー対象を通常のデータに絞り、関数や独自クラスが混ざっていないか確認すること。
- 7:23次に、編集開始など必要なタイミングに絞って呼び出し、毎回全体をコピーし続けないこと。
- 7:30そして、履歴機能に使う場合は、保存件数や対象範囲を先に決めることです。
- 7:36練習として、小さな設定オブジェクトをコピーし、内側を変更しても元が変わらないことを確かめてみてください。
- 7:44お疲れさまでした。
- 7:46小さな例で確かめる習慣が、共有や例外による思わぬ不具合を未然に防いでくれます。
この動画で学べること
structuredClone()で入れ子のオブジェクトを深くコピーする方法を解説。ブラウザーとNode.jsの対応、実行手順、循環参照、コピーできない値、転送時の注意点をコードで学びます。
解説記事・サンプルコードを読む:JavaScriptのstructuredClone():入れ子のデータを独立してコピーする →