'Is destructing assigning in JavaScript shallow or deep copy?

I'm confused by the destructing assigning in JavaScript about shallow and deep copy. For example,

const obj = {key:{}, value:{}}
let {key} = obj
key = {msg: 'hello'}

Is the value of key in the sample above a shallow or deep copy of the key in obj? What is the value of key should be?



Solution 1:[1]

let {key} = obj

… is the same as saying:

let key = obj.key

It is a shallow copy.


key = {msg: 'hello'}

… overwrites the reference to the object that also exists in obj.key with a reference to a new object.

This renders the previous line pointless as nothing was done with the value before it was overwritten.

Solution 2:[2]

It's shallow, though there's some nuance.

This:

let {key} = obj;

has exactly the same result as this:

let key = obj.key;

E.g., all it does is copy the value of obj.key into key, making both of them point to the same object — a shallow copy, if the word "copy" really applies. (Normally I think of a "shallow copy" as copying multiple properties, not just one, like Object.assign does.)

You can reach deeper into the object graph you're retrieving from by using nested destructuring:

const obj = {
    a: {
        b: {
            c: {
               d: "hi",
            },
        },
    },
};
const {a: {b: {c}}} = obj;
console.log(c.d); // "hi"

but at the end of the day it's just like an assignment, so it's just grabbing the object reference (if the value is an object reference), not a copy of the object:

const obj = {
    a: {
        b: {
            c: {
               d: "hi",
            },
        },
    },
};
const {a: {b: {c}}} = obj;
console.log(c.d);         // "hi"
console.log(obj.a.b.c.d); // "hi"
c.d = c.d.toLocaleUpperCase();
console.log(c.d);         // "HI"
console.log(obj.a.b.c.d); // "HI"

But, even if it were a deep copy, your code still wouldn't change anything in obj, because you're changing the value of what's in key (an object reference), not the state of the object that reference refers to. After let {key} = obj, key is completely disconnected from obj.key other than that they both refer to the same object. If you change the value in key, the variable, it has no effect on the object it refers to. If you're goign to do key = ..., there's no point to let {key} = obj at all, just use let key.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Quentin
Solution 2