1

I'm trying to collect all the objects from DATA and compare to schemesFromPOI. If the name is AMERICAN_EXPRESS I want to change it to AMEX in the scheme object only, preserving the DATA object.

const DATA =
    [
      {
        "name": "MASTERCARD",
        "id": "MASTERCARD123"
      },
      {
        "name": "VISA",
        "id": "VISA456"
      },
      {
        "name": "AMERICAN_EXPRESS",
        "id": "AMEX789"
      }
    ];

const schemesFromPOI = [
  { dpaId: 'DPA1', name: 'MASTERCARD' },
  { dpaId: 'DPA2', name: 'VISA' },
  { name: 'AMERICAN_EXPRESS' }
];

let config = [];

schemesFromPOI.forEach(function (schemeFromPOI) {

  let scheme = DATA.find(function (element) { return element.name === schemeFromPOI.name; });

  if(scheme) {
    if (scheme.name === "AMERICAN_EXPRESS") {
      console.log("Before updating scheme.name property: ", DATA);
      scheme.name = 'AMEX';
      console.log("After updating scheme.name property: ", DATA);
    }

    config.push(scheme);
  }

});

However, when I change scheme.name, the DATA object is updated as well. Here is the result of the above console outputs:

Before updating scheme.name property: "[{'name':'MASTERCARD','id':'MASTERCARD123'},{'name':'VISA','id':'VISA456'},{'name':'AMERICAN_EXPRESS','id':'AMEX789'}]"
After updating scheme.name property: "[{'name':'MASTERCARD','id':'MASTERCARD123'},{'name':'VISA','id':'VISA456'},{'name':'AMEX','id':'AMEX789'}]"

Clearly the DATA object is being updated, not just the scheme object. Why is this coercion happening? Does it have to do with the .find() method?

Paul Erdos
  • 1,355
  • 2
  • 23
  • 47
  • 1
    Possible duplicate: [JavaScript by reference vs. by value](https://stackoverflow.com/questions/6605640/javascript-by-reference-vs-by-value) – Tyler Roper Dec 19 '19 at 18:36

2 Answers2

3

It happens because arrays are reference types. So when you are editing scheme.name = 'AMEX';, then it means that scheme.name will be changed and an object which was found in DATA.

If you want to create a brand new object, then use spread ... operator :

const data = [
    { name: "John", age: "22", weight: "60", height: "180cm" },
    { name: "Emma", age: "25", weight: "55", height: "160cm" }
];

let obj = data.find(f=> f.name =='John');

let brandNewObject = {...obj};

An example:

const data = [
        { name: "John", age: "22", weight: "60", height: "180cm" },
        { name: "Emma", age: "25", weight: "55", height: "160cm" }
    ];
    
    let obj = data.find(f=> f.name =='John');        
    let brandNewObject = {...obj};        
    brandNewObject .name = "Joseph";
    
    console.log(`obj`, obj);
    console.log(`brandNewObject `, brandNewObject );
StepUp
  • 36,391
  • 15
  • 88
  • 148
  • This works! However spread operator isn't supported by IE, and I have to support that unfortunately. Is there a workaround? – Paul Erdos Dec 19 '19 at 19:49
  • Using `let scheme = Object.assign({}, obj);` with the IE polyfill instead of the spread operator was a good workaround for me. – Paul Erdos Dec 19 '19 at 20:23
1

This happens in JS we call it with the term Mutable type, you can visit this link for better understanding https://developer.mozilla.org/en-US/docs/Glossary/Mutable

To get back to your answer

Object.freeze(DATA);

The above code will freeze the object and won't allow it to get updated.

D3v30
  • 162
  • 1
  • 3
  • 14