Shallow copy

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, 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, Array.prototype.concat(), Array.prototype.slice(), Array.from(), Object.assign(), and 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.

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.

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.

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