-
Notifications
You must be signed in to change notification settings - Fork 22.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new “Shallow copy” and “Deep copy” glossary entries (#12474)
Co-authored-by: Hamish Willee <hamishwillee@gmail.com> Co-authored-by: Daniel D. Beck <dbeck@mozilla.com>
- Loading branch information
1 parent
b81ff9b
commit 80ac011
Showing
9 changed files
with
106 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
--- | ||
title: Deep copy | ||
slug: Glossary/Deep_copy | ||
tags: | ||
- Glossary | ||
- Deep copy | ||
--- | ||
{{MDNSidebar}} | ||
|
||
A **deep copy** of an object is a copy whose properties do not share the same references (point to the same underlying values) as those of the source object from which the copy was made. As a result, when you change either the source or the copy, you can be assured you’re not causing the other object to change too; that is, you won’t unintentionally be causing changes to the source or copy that you don’t expect. That behavior contrasts with the behavior of a [shallow copy](/en-US/docs/Glossary/Shallow_copy), in which changes to either the source or the copy may also cause the other object to change too (because the two objects share the same references). | ||
|
||
In JavaScript, standard built-in object-copy operations ([spread syntax](/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax), [`Array.prototype.concat()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat), [`Array.prototype.slice()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice), [`Array.from()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from), [`Object.assign()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign), and [`Object.create()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create)) do not create deep copies (instead, they create shallow copies). | ||
|
||
One way to make a deep copy of a JavaScript object, if it can be [serialized](/en-US/docs/Glossary/Serialization), is to use {{jsxref("JSON.stringify()")}} to convert the object to a JSON string, and then {{jsxref("JSON.parse()")}} to convert the string back into a (completely new) JavaScript object: | ||
|
||
```js | ||
let ingredients_list = ["noodles",{"list":["eggs","flour","water"]}]; | ||
let ingredients_list_deepcopy = JSON.parse(JSON.stringify(ingredients_list)); | ||
|
||
// Change the value of the 'list' property in ingredients_list_copy. | ||
ingredients_list_deepcopy[1].list = ["rice flour","water"] | ||
// The 'list' property does not change in ingredients_list. | ||
console.log(ingredients_list[1].list); | ||
// Array(3) [ "eggs", "flour", "water" ] | ||
``` | ||
|
||
As can be seen from the code above, because a deep copy shares no references with its source object, any changes made to the deep copy do not affect the source object. | ||
|
||
However, while the object in the code above is simple enough to be [serializable](/en-US/docs/Glossary/Serialization), many JavaScript objects are not serializable at all — for example, [functions](/en-US/docs/Web/JavaScript/Guide/Functions) (with closures), [Symbols](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol), objects that represent HTML elements in the [HTML DOM API](/en-US/docs/Web/API/HTML_DOM_API), recursive data, any many other cases. Calling `JSON.stringify()` to serialize the objects in those cases will fail. So there’s no way to make deep copies of such objects. | ||
|
||
For objects that _are_ serializable, you can alternatively use the [`structuredClone()`](/en-US/docs/Web/API/structuredClone) method to create deep copies. `structuredClone()` has the advantage of allowing {{Glossary("transferable objects")}} in the source to be _transferred_ to the new copy, rather than just cloned. But note that `structuredClone()` isn’t a feature of the JavaScript language itself — instead it’s a feature of browsers and any other JavaScript runtimes that implement a global object like [`window`](/en-US/docs/Web/API/Window). And calling `structuredClone()` to clone a non-serializable object will fail in the same way that calling `JSON.stringify()` to serialize it will fail. | ||
|
||
## See also | ||
|
||
- [Shallow copy](/en-US/docs/Glossary/Shallow_copy) | ||
- [`window.structuredClone()`](/en-US/docs/Web/API/structuredClone) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
--- | ||
title: Shallow copy | ||
slug: Glossary/Shallow_copy | ||
tags: | ||
- Glossary | ||
- Shallow copy | ||
--- | ||
{{MDNSidebar}} | ||
|
||
A **shallow copy** of an object is a copy whose properties share the same references (point to the same underlying values) as those of the source object from which the copy was made. As a result, when you change either the source or the copy, you may also cause the other object to change too — and so, you may end up unintentionally causing changes to the source or copy that you don’t expect. That behavior contrasts with the behavior of a [deep copy](/en-US/docs/Glossary/Deep_copy), in which the source and copy are completely independent. | ||
|
||
For shallow copies, it’s important to understand that selectively changing the value of a shared property of an existing element in an object is different from assigning a completely new value to an existing element. | ||
|
||
For example, if in a shallow copy named `copy` of an array object, the value of the `copy[0]` element is `{"list":["butter","flour"]}`, and you do `copy[0].list = ["oil","flour"]`, then the corresponding element in the source object will change, too — because you selectively changed a property of an object shared by both the source object and the shallow copy. | ||
|
||
However, if instead you do `copy[0] = {"list":["oil","flour"]}`, then the corresponding element in the source object **will not change** — because in that case, you’re not just selectively changing a property of an existing array element that the shallow copy shares with the source object; instead you’re actually assigning a completely new value to that `copy[0]` array element, just in the shallow copy. | ||
|
||
In JavaScript, all standard built-in object-copy operations ([spread syntax](/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax), [`Array.prototype.concat()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat), [`Array.prototype.slice()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice), [`Array.from()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from), [`Object.assign()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign), and [`Object.create()`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create)) create shallow copies rather than deep copies. | ||
|
||
## Example | ||
|
||
Consider the following example, in which an `ingredients_list` array object is created, and then an `ingredients_list_copy` object is created by copying that `ingredients_list` object. | ||
|
||
```js | ||
let ingredients_list = ["noodles",{"list":["eggs","flour","water"]}]; | ||
|
||
let ingredients_list_copy = Array.from(ingredients_list); | ||
console.log(JSON.stringify(ingredients_list_copy)); | ||
// ["noodles",{"list":["eggs","flour","water"]}] | ||
``` | ||
|
||
Changing the value of the `list` property in `ingredients_list_copy` will also cause the `list` property to change in the `ingredients_list` source object. | ||
|
||
```js | ||
ingredients_list_copy[1].list = ["rice flour","water"] | ||
console.log(ingredients_list[1].list); | ||
// Array [ "rice flour", "water" ] | ||
console.log(JSON.stringify(ingredients_list)); | ||
// ["noodles",{"list":["rice flour","water"]}] | ||
``` | ||
|
||
Assigning a completely new value to the first element in `ingredients_list_copy` will not cause any change to the first element in the `ingredients_list` source object. | ||
|
||
```js | ||
ingredients_list_copy[0] = "rice noodles" | ||
console.log(ingredients_list[0]) | ||
// noodles | ||
console.log(JSON.stringify(ingredients_list_copy)); | ||
// ["rice noodles",{"list":["rice flour","water"]}] | ||
console.log(JSON.stringify(ingredients_list)); | ||
// ["noodles",{"list":["rice flour","water"]}] | ||
``` | ||
|
||
## See also | ||
|
||
- [Deep copy](/en-US/docs/Glossary/Deep_copy) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters