0

there's my problem:

I've a function that add a element to a array (A), the element to add comes from the argument. Then when I modify this element in the array (A), it also modify the element that I used as argument.

it look like that :

addTemplates(nTemplate){
    let k = nTemplate;
    k.id=this.templates.length+1;
    this.templates.push(k);
    this.emitTemplateSubject();
  }
  
  //when I use the function:
  
  let aObject={id:1, sth:"aa", sthE:"bb"}
  addTemplate(aObject);
  
  
  //then  aObject.id is also change.

It's probably normal but how can I avoid to apply the changement on 'aObject' ?

L.DZ
  • 111
  • 3
  • 12
  • 1
    Most of the answers you will get will recommend you various ways to create a shallow clone of your object. Assuming that your objects will not all be as simple as the one in your question, you'd probably be better off looking into [deep cloning of JavaScript objects](https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript). TL;DR: In my personal opinion, importing lodash's `cloneDeep()` method is the simplest and most robust solution for Angular. – Robby Cornelissen Jul 09 '19 at 08:43

4 Answers4

2

You have to create a copy of your object and then send it to the function

let newObject = Object.assign({}, aObject);
addTemplate(newObject );

This is because when you are passing the object, it is passing as a reference. What you need is to pass as data for that you need to create a copy of your object and send it to function.

Gopesh Sharma
  • 6,730
  • 4
  • 25
  • 35
  • 1
    Note that when using the spread operator on an object that has objects as properties, those objects will be referenced: `const aObject={child:{"property":"value"}}; const spread = {...aObject}; spread.child.property = 'new value'; console.log(aObject.child.property === spread.child.property);` – fjc Jul 09 '19 at 08:45
1

With this.templates.push(k);, you add a reference, not a copy, of kto templates. Hence, when you modify properties of the reference in the array, you are modifying the same object as when modifying k directly.

A simple example that shows the difference between a reference and a copy (in this case, I am creating a copy using JSON.parse(JSON.stringify(...)), which I would not recommend for actual real-life projects):

const original = {"property":"value"};
const reference = original;
const copy = JSON.parse(JSON.stringify(original));

const array = [reference, copy];

array[0].property = 'new value for reference';
array[1].property = 'new value for copy';

console.log(reference.property === original.property);
console.log(copy.property !== original.property);

If you have a shallow object, you can simply use the spread operator (this.templates.push({...k});) to create a copy.

If you have objects as properties of k, which would mean that they would be referenced in the copy, you'd need to deep-clone k.

fjc
  • 5,590
  • 17
  • 36
0

You can use the spread operator and have something like:

let aObject={id:1, sth:"aa", sthE:"bb"}
addTemplate({... aObject});
Morema
  • 145
  • 2
  • 12
  • 2
    Note that when using the spread operator on an object that has objects as properties, those objects will be referenced: `const aObject={child:{"property":"value"}}; const spread = {...aObject}; spread.child.property = 'new value'; console.log(aObject.child.property === spread.child.property);` – fjc Jul 09 '19 at 08:45
0

You could try something like below and use assign keyword for creating new objects instead of assigning refrence.

let aObject = {
  id: 1, sth: "aa", sthE: "bb"
}
addTemplates(aObject);


function addTemplates(nTemplate) {
  let k  = Object.assign({}, nTemplate);
  k.id=this.templates.length+1;
  this.templates.push(k);
  this.emitTemplateSubject();
}
Vishwajeet
  • 1,575
  • 2
  • 19
  • 35