0

I want to be able to take in an object

const objectOriginal = {
  nestedObject: {
   someValue: 1
  }
}

Create a new object from the above and change it's value to

const newObject = {
  nestedObject: {
   someValue: 33
  }
}

I have a large object of nested objects as my original, and I want to create a new one based of this original. The problem is that I need these two objects to be different and not from the same prototype chain.

In order to solve this problem I've created a function that turns the first object to an array, filter out the object I need to change, change the values, push to an array, and then create a new object.

const originalObject = {
  nested1: {
    id: "nested1"
    value: 1
  },
  nested2: {
    id: "nested2"
    value: 2
  },
  nested3: {
    id: "nested3"
    value: 3
  }
}

const valueToChange = "nested1"

const createNewObject = (originalObject, valueToChange) => { 
  const originalObjectToArray = Object.values(originalObject)

  const temporaryArray = originalObjectToArray.filter(object => object.id !== valueToChange)

  const newNestedObject = {
    id: valueToChange,
    value: 33
  }
  temporaryArray.push(newNestedObject)

  const newAndDifferentObject = {}
  for (let obj of temporaryArray) {
    newAndDifferentObject[obj.id] = obj
  }
  return newAndDifferentObject
}

This solution works, but I feel that there must be a better way to achieve this? If I want to create a new and different object, I shouldn't (at least I would hope not) have change it to an array just to change it back to an object. Any advice would be greatly appreciated.

adam.k
  • 622
  • 3
  • 15
  • 1
    Possible duplicate of [What is the most efficient way to deep clone an object in JavaScript?](https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript) – Igor Feb 25 '19 at 20:21
  • Read through the suggested duplicate. IMO I prefer using `const myCopy = JSON.parse(JSON.stringify(source));` to make a copy. – Igor Feb 25 '19 at 20:21
  • Maybe you want something like [immutablejs](https://github.com/immutable-js/immutable-js) – Akxe Feb 25 '19 at 20:43

2 Answers2

1

I will use Object.assign() for this. We create a new empty object, assign all the original properties of the original object and then assign the new nested object. The method will take care of replace existing properties by the new ones (Read more here: Merging Objects With Same Properties).

const originalObject = {
  nested1: {id: "nested1", value: 1},
  nested2: {id: "nested2", value: 2},
  nested3: {id: "nested3", value: 3}
};

const createNewObject = (originalObj, valToChange, newVal) =>
{
    const newObj = {id: valToChange, value: newVal};
    return Object.assign({}, originalObj, {[valToChange]: newObj});
};

// Example of replacements.
console.log(createNewObject(originalObject, "nested1", 33));
console.log(createNewObject(originalObject, "nested2", 99));

// Example of a new property (none of the original are replaced)
console.log(createNewObject(originalObject, "nested4", 44));

You can even generalize the previous method to accept an array of pairs of the type [valToChange, newVal] to create a new object with multiple changes:

const originalObject = {
  nested1: {id: "nested1", value: 1},
  nested2: {id: "nested2", value: 2},
  nested3: {id: "nested3", value: 3}
};

const createNewObject = (originalObj, updateList) =>
{
    let newObjs = updateList.reduce((acc, [k, v]) =>
    {
        acc[k] = {id: k, value: v};
        return acc;
    }, {});

    return Object.assign({}, originalObj, newObjs);
};

console.log(createNewObject(
    originalObject,
    [["nested1", 33], ["nested2", 99], ["nested4", 44]]
));
Shidersz
  • 16,846
  • 2
  • 23
  • 48
0

Your problem is that both variables point to the same object (a shallow copy). What you're doing is a deep copy, and there is an easier way to do this is using JSON:

function jsonCopy(src) {
    return JSON.parse(JSON.stringify(src));
}

Passing your original object as src, it will convert it to a JSON string and parse it back to an object, performing a deep copy of your object and returning it.

Logan Rodie
  • 673
  • 4
  • 12