About this article
This article is generated using an automated generation workflow utilizing generative AI. Based on official MDN documentation, we created educational material comparing copying methods using dummy configuration data.Verification Status: 📘 Official MDN specification verified. 10 conditions passed for equivalent logic on Linux Node.js 22.16.0. Re-tests for GitHub-saved version, actual browsers, GitHub Pages, and WordPress rendering are unverified.
"I just copied the settings and edited them, but the original settings changed too." This strange phenomenon occurs when handling objects in JavaScript. The cause is:the difference between copying only the outer layer and copying nested data as well. This time, using dummy settings, we compare the results at the click of a button.
- Try it first: Does the original setting change?
- Why the original data changes
- Comparing Date and Map: Differences from JSON conversion
- Try changing just one condition
- Troubleshooting when things do not work
- For professional use: Comparing before and after changes.
- Official documentation
- Organizing with diagrams: What to check before choosing a copy method
- Confirming that the same configuration is referenced
- What to compare before and after a deep copy
- The Concept of "Reversible Changes" Useful in Business
- Summary
Try it first: Does the original setting change?
| Item | Conditions for this test |
|---|---|
| Target | structuredClone()Supported browsers, Node.js 18 or later |
| Technologies used | JavaScript spread syntax, structuredClone, Date, Map |
| Cost & Communication | Standard API only. No CDN, no API keys, no personal information, no external transmission |
| Actual measurements | 10 pure logic tests passed on Linux Node.js 22.16.0. Browser rendering unverified |
Daily Code: Full code of fixed commit and README
We have not verified the reachability or actual functionality of the GitHub Pages public URL this time.The reliable way to check the sourceis to retrieve web/structured-clone-lab/ from the pinned commit above. The design is to run python3 -m http.server 8000 at the repository root and open http://127.0.0.1:8000/web/structured-clone-lab/. Stop with Ctrl+C. Actual browser behavior is unverified.
There are three operations.
Click "Compare Again" to check the original data values.
Observe that "Original data after shallow copy modification" becomes
red.Compare how "Original data after deep copy modification" remains
red, while only the copy side becomesgreen.
Note: The original data is already red due to the initial shallow copy modification. A deep copy does not revert this. We verify that modifying the deep copy does not further affect the original data.
Why the original data changes
In the next example, {...original} creates the outer object. However, settings points to the same nested object.
const original = {settings: {theme: "blue"}};
const shallow = {...original};
shallow.settings.theme = "red";
console.log(original.settings.theme); // "red"
Meanwhile,structuredClone() deeply clones the corresponding values.
const original = {settings: {theme: "blue"}};
const deep = structuredClone(original);
deep.settings.theme = "green";
console.log(original.settings.theme); // "blue"
These two code snippets are independent examples. The comparison button in the tutorial applies modifications to the same source data using a shallow copy, and then modifies the deep copy side.
flowchart TD
A["元の架空設定"] --> B["浅いコピー {...original}"]
A --> C["深いコピー structuredClone"]
B --> D["入れ子の参照を共有"]
C --> E["対応する入れ子も複製"]
D --> F["変更が元データに反映"]
E --> G["コピー側の変更は元に影響しない"]
Comparing Date and Map: Differences from JSON conversion
Frequently seen in legacy code, JSON.parse(JSON.stringify(value)) can also copy JSON-representable data into a new object. However, it does not preserve all original types.
| Data | structuredClone | JSON serialization and deserialization |
|---|---|---|
| Nested plain object | Deeply cloned | Cloned within JSON-representable limits |
| Date | Preserved as a Date | Converted to an ISO format string |
| Map | Preserved as a Map | Maps in this tutorial become empty objects |
| Circular reference | Supported | JSON.stringify typically throws an error |
| Functions | DataCloneError | properties may be omitted |
That is,"being able to copy via JSON" and "being able to copy while preserving data types" are different. In this tutorial, Date and Map are used as fixed inputs, and the difference is displayed as text.
Try changing just one condition
First, change the nested value settings.theme. Next, copy the code and try changing only the non-nested team to "架空のB班". Even with a shallow copy, reassigning an outer string property does not affect the original data.
This comparison shows that shallow copies are not always dangerous, but rather thatit is important to understand and manage shared nested structures when using them. Immutability-based design, copying only necessary parts, and simplifying data structures are also valid options.
Troubleshooting when things do not work
| Symptom | Potential cause | Solution |
|---|---|---|
structuredClone is missing | The browser or runtime environment is outdated. | Check compatibility. Node.js version 18 or later is assumed. |
DataCloneError occurs. | Unsupported values such as functions or DOM elements. | Review the target to be duplicated. |
| The display does not change even when the button is pressed. | JavaScript is disabled, or the file is not loaded. | clone.js and app.jsCheck the path and developer tools for . |
| Date became a string. | Duplicated via JSON. | Consider whether the type needs to be preserved. |
| Slow with large data. | Deep copies require time and memory. | Reduce the duplication range. |
structuredClone() is not a universal object cloning method. Functions and DOM elements cannot be cloned, and custom class prototypes or property descriptors are not preserved as-is. Pay attention to memory consumption when copying huge data. Although a transfer mechanism exists, it may render the original buffer unusable, so it is not covered in this introductory tutorial.
For professional use: Comparing before and after changes.
For example, when creating a "preview before saving" on a business system settings screen, if display changes are reflected in the original data, it can lead to bugs where changes cannot be reverted even if canceled. Identify the range where original values must be preserved and choose a copying method that matches the data type and capacity.
This tutorial uses only mock data. There is no need to enter actual customer data or confidential information into the demos. UI display, communication, saving, and WordPress display are not verified this time.
Official documentation
MDN: Window.structuredClone() — Deep copy, circular references, exceptions, and transfer.
MDN: Structured clone algorithm — Cloneable types and unsupported values.
MDN: Spread syntax — Characteristics of shallow copy.
MDN: JSON.stringify() — Limitations of JSON conversion.
Organizing with diagrams: What to check before choosing a copy method
When a copied and modified value propagates back to the original data, the cause is not necessarily a JavaScript bug. Using the term "copied" without understanding object reference relationships makes it ambiguous whether only the outer container was duplicated or if the inner containers were also duplicated. A shallow copy creates a new outer object, but nested objects may retain the same references as the original.
flowchart TD
A["コピーする値を調べる"] --> B{"入れ子の値があるか"}
B -->|"ない"| C["浅いコピーでも足りるか検討"]
B -->|"ある"| D{"入れ子も独立させる必要があるか"}
D -->|"ない"| E["参照の共有を許可する設計か確認"]
D -->|"ある"| F["structuredClone対応の型か確認"]
F -->|"対応"| G["深いコピー後の変更を比較"]
F -->|"非対応"| H["用途に合わせ別の明示的な複製処理"]
G --> I["メモリー・性能・例外も確認"]
This diagram is not a universal decision algorithm applicable to all JavaScript values. For instance, functions, DOM elements, and instances of custom classes cannot necessarily be duplicated with the exact same functionality simply by using structuredClone. What is necessary is to first determine "what you want to change" and "what you want to leave intact in its original state."
Confirming that the same configuration is referenced
Just because the next two values look similar does not mean that two independent configurations are stored. With a shallow copy, even if the outer object is recreated, the nested properties may still point to the same reference. A small example using a fictitious color configuration allows you to compare whether inner references are shared.
const original = { settings: { theme: "blue" } };
const shallow = { ...original };
console.log(original === shallow); // false と予想
console.log(original.settings === shallow.settings); // true と予想
You can see that even though the outer objects are separate, the nested settings are the same object. Therefore, modifying shallow.settings.theme also changes original.settings.theme. Conversely, if you replace shallow.settings with a new object, it does not mean you have overwritten the original settings themselves. It is also incorrect to memorize that "because it is a shallow copy, changing anything will always propagate to the original."
What to compare before and after a deep copy
A deep copy is necessary not simply because nested structures exist, but when you want to keep the original configuration and the editing configuration independent. For example, suppose a business application has features like "preview changes" and "cancel." If the original configuration is modified directly in the preview, a bug occurs where canceling fails to revert to the previous value. Therefore, editable values must be made independent.
On the other hand, fully duplicating large data every time can cause issues with memory consumption and processing time. If the required scope is only partial, designing to explicitly update only that specific part becomes an alternative to consider. When choosing a copy method, consider the scope of changes and data volume, not just correctness.
Why copying via JSON is not a universal solution
While you may see the approach JSON.parse(JSON.stringify(value)), Date objects may become strings and fail to retain their original types. For values including Maps, functions, or circular references, some items cannot be represented or may not yield the expected results. Do not assume it is the same deep copy just because it can be written in two steps; verify what data types the copied data contains.
structuredClone also has values that cannot be cloned, which may result in a DataCloneError. The behavior of custom classes, getters, and property descriptors are not necessarily preserved completely as-is. To prevent the original data from being partially modified when an exception occurs, it is important to design copy and edit processes separately.
The Concept of "Reversible Changes" Useful in Business
In a mock application screen, settings might be modified and reviewed before saving, with the option to cancel if unsatisfied. In this scenario, it is natural to apply screen changes only to temporary data and reflect them in the actual data only after the save is confirmed. The copy method is one tool for this purpose, but how to update the destination state and how to detect conflicts when multiple users edit simultaneously are separate design challenges.
The highlight of this experiment is not just whether the values are the same, but tracking "where the same object is referenced." Observing the outer comparison, the nested comparison, and the original data after modification each time the code is changed makes it possible to explain why the values turned out differently than expected. Rather than simply memorizing a new API, this serves as training for considering where changes propagate.
Summary
There is more than one type of copy. First, observe in the order of shallow copy -> original nesting changes -> deep copy -> original remains unchanged. In practical work, verifying what you want to duplicate and which data types are included is the shortcut to safe design.
