0

I need for my Cypress tests two slightly differed sets of data. As the dataset isn't short and the variation deviates from the original only slightly - I thought to just duplicate the object and mutate it the way I need it. But well, variables in ES6 Imports are bindings so mutating the copy results in mutating the original as well.

To demonstrate this behavior:

//test.json
{
  "foo":{
     "bar":"XXX"
  }
}
import test from './test.json'

const firstTest = {...test}
const secondTest = {...test}

secondTest.foo.bar = '@@@'

console.log(firstTest.foo.bar)
// Output: @@@

Spread operator obviously doesn't work there as well as Object.assign()

What works for me to get rid of the bindings is:

import test from './test.json'

const firstTest = JSON.parse(JSON.stringify(test)) //<---
const secondTest = JSON.parse(JSON.stringify(test)) //<---

secondTest.foo.bar = '@@@'

console.log(firstTest.foo.bar)
// Output: XXX

Is there a better way to achieve this or just get rid of the bindings in a different way?

Hexodus
  • 12,361
  • 6
  • 53
  • 72
  • 1
    "*variables in ES6 Imports are bindings so mutating the copy results in mutating the original as well*" - that has nothing to do with them being bindings. Actually the bindings are immutable, you cannot reassign them! Your actual problem is that all imports refer to the same, shared object, and when making a copy of that with the spread operator you are failing to make a *deep* copy. It would have worked with `{...test, foo: {...test.foo}}` – Bergi Sep 28 '22 at 14:36

1 Answers1

4

You can use the strcuturedClone() algorithm.

Be sure to check compatibility with your target environment.

// import test from './test.json';
const test = JSON.parse(`{
  "foo":{
     "bar":"XXX"
  }
}`);

const copy1 = structuredClone(test);
const copy2 = structuredClone(test);

copy2.foo.bar = '@@@';

console.log('test', test.foo.bar); // "XXX"
console.log('copy1', copy1.foo.bar); // "XXX"
console.log('copy2', copy2.foo.bar); // "@@@"
jsejcksn
  • 27,667
  • 4
  • 38
  • 62