This is a question about how JavaScript might add a reference to existing rather than creating new.
Here are some examples that are hopefully illustrative-enough, in the context of a Redux reducer because it is a familiar place for spread operator or Object.assign():
See here we are just returning an object literal with a string, so there is nothing that could drag in a reference to something that is existing elsewhere.
export default (state = {}, action) => {
    switch (action.type) {
        case SOME_ACTION:
            return {
                props: 'something arbitray'
            }
    }
}
This one is the suspect problem:
We are returning an object literal but we have included reference to
args[type]. First, I need to know for certain, is this returning an object that maintains a link to whateverargs[type]is currently set to? Ifargs[type]were to get mutated after, would that be reflected in this returned object?
export default (state = {}, action) => {
    switch (action.type) {
        case SOME_ACTION:
            return {
                props: args[type]
            }
    }
}
Here are two examples I suspect would not have this problem:
Do I understand that correctly? Does JavaScript copy just the property and not maintain any reference to
args[type]?
export default (state = {}, action) => {
    switch (action.type) {
        case SOME_ACTION:
            return Object.assign({}, state, { props: args[type] })
    }
}
Here is another example that I recently learned might be syntactically identical to the Object.assign() syntax:
export default (state = {}, action) => {
    switch (action.type) {
        case SOME_ACTION:
            return { ...state, props: args[type] }
    }
}
The Questions:
- Does the spread operator do the exact same thing as - Object.assign()in this context and create an entirely new object without risk of illegal-mutability due to maintaining a reference to- args[type]? I need to be able to rely on the immutable state of the object after it is created.
- Would the second example I showed maintain a live reference to - args[type]?
I have some code that normally spreads in something, and I have a use case that omits that spread, so I am curious if that could be a problem. How can I guarantee random alterations of args[type] would not affect this returned object?
Would this be the correct answer?:
export default (state = {}, action) => {
    switch (action.type) {
        case SOME_ACTION:
            return Object.assign({}, { props: args[type] })
    }
}
[edit] I am able to reproduce the issue by doing this:
const arr = ['one', 'two', 'three']
const args = {
  type: arr
}
const something = {
  props: args.type
}
arr.push('four') // Notice how this appears in something.props
console.log(something)And this fixes it (so it seems to have something to do with primitives vs. maintaining an object reference):
const arr = ['one', 'two', 'three']
const args = {
  type: arr[2]
}
const something = {
  props: args.type
}
arr[2] = 'what' // Notice how this doesn't appear in something.props
console.log(something)Updated Question
Is there a way to copy a non-primitive (ie: object/array) so that it breaks this reference?
I am noticing it doesn't work with Object.assign()
 
    