George Hastings
George Hastings

Reputation: 35

Data in javascript factory is being overridden if factory is ran multiple times

In the following code pen you can see that I have setup a factory that takes in an array of Objects as data, loops through that data and then add's button's into the page with an onclick event that logs out the data object.

const testData = [{
    fruit: 'Banana'
  },
  {
    fruit: 'Apple'
  },
  {
    fruit: 'Pear'
  }
];



const scopeCreep = ({
  data
}) => {
  const outputDiv = document.getElementById('output');
  const getID = () => {
    return Math.random().toString(36).substring(7);
  };
  var lastID;

  for (let x = 0; x < data.length; x++) {
    data[x].ID = getID();
    lastID = data[x].ID;
  }

  //Add a button to the test div
  let button = document.createElement('button');
  button.innerText = lastID;
  button.onclick = () => {
    console.log(privateData, lastID);
    outputDiv.innerHTML += "Click resulted in: </br>";
    outputDiv.innerHTML += "Array data: " + JSON.stringify(data, null, 2) + ", lastID: " + lastID + "</br>";
  };
  document.body.appendChild(button);

  //JSON parse hack
  var privateData = JSON.parse(JSON.stringify(data, null, 2));

  //Add new IDS and choose a random one to output as selection
  return {
    privateData,
    data
  };
};

const tester = () => {
  const outputDiv = document.getElementById('output');
  var data1 = scopeCreep({
    data: testData
  });
  outputDiv.innerHTML += "1 load: " + JSON.stringify(data1.privateData, null, 2) + " - " + JSON.stringify(data1.data, null, 2) + "</br>";
  var data2 = scopeCreep({
    data: testData
  });
  outputDiv.innerHTML += "2 load: " + JSON.stringify(data2.privateData, null, 2) + " - " + JSON.stringify(data2.data, null, 2) + "</br>";
  var data3 = scopeCreep({
    data: testData
  });
  outputDiv.innerHTML += "3 load: " + JSON.stringify(data3.privateData, null, 2) + " - " + JSON.stringify(data3.data, null, 2) + "</br>";
};

document.addEventListener("DOMContentLoaded", tester);
<div id="test">
</div>
<div id="output">
</div>

It seems that the data is being overridden with the last loaded data. (I hope that makes sense?)

My question boils down to: Why is this data being changed out of scope & how can I stop it?

Thanks,

Upvotes: 0

Views: 37

Answers (2)

George Hastings
George Hastings

Reputation: 35

I am cloning the data in scope using the following, thankfully the data does not contain any functions as the following would not replicate functions.

JSON.parse(JSON.stringify(data));

Upvotes: 0

HaneTV
HaneTV

Reputation: 926

you have to put this line var privateData = JSON.parse(JSON.stringify(data, null, 2)); at the top of the function in order to clone it before modify the original object

Upvotes: 1

Related Questions