0

I have a template object that I am recursively modifying and needing to push into an array like so

var base = {
  a: 600,
  b: 1.15,
  c: 0,
  d: 200,
  e: 3,
  f: 3,
  g: 1,
  h: 1,
}
var array2 = new Array();
for(var i=1;i<=3;i++){
  base.a = base.a*12
  base.b = base.b-0.01
  base.d = base.d*4
  base.e = Math.ceil(base.e * 1.5)
  base.f = base.e
  array2.push(base)
}

The expected output would be

[ { a: 7200, b: 1.13, c: 0, d: 800, e: 5, f: 5, g: 1, h: 1 },
{ a: 86400, b: 1.12, c: 0, d: 3200, e: 8, f: 8, g: 1, h: 1 } ]

Actual is

[ { a: 86400, b: 1.11, c: 0, d: 3200, e: 8, f: 8, g: 1, h: 1 },
  { a: 86400, b: 1.11, c: 0, d: 3200, e: 8, f: 8, g: 1, h: 1 } ]

And I am finding that when I manipulate the object, it recursively changes the values for each time the object was placed in the array.

So the question is, how can I place new objects into this array in a fashion that I do not retroactively change all values when recursively updating the base template.

(Edited a value that was incorrect by 0.01 in the expected output [1].b)

4 Answers 4

1

You are mutating the values of the original object. You will have to keep track of the previous object, based on which you want to compute the values and push into the array.

var base = {
  a: 600,
  b: 1.15,
  c: 0,
  d: 200,
  e: 3,
  f: 3,
  g: 1,
  h: 1,
}
var array2 = [];
// store the reference of the original object
var prev = base;

for (var i = 1; i <= 3; i++) {
  var obj = {};
  // populate the data for the new object 
  // based on the previous object in array 
  obj.a = prev.a * 12;
  obj.b = prev.b - 0.01;
  obj.c = prev.c;
  obj.d = prev.d * 4;
  obj.e = Math.ceil(prev.e * 1.5);
  obj.f = prev.e;
  obj.g = prev.g;
  obj.h = prev.h;

  array2.push(obj);
  
  // save the reference of the current object state
  // to be used in the next iteration
  prev = obj;
}

console.log(array2);

Sign up to request clarification or add additional context in comments.

Comments

0

You only have one object and you are pushing the same object in that array. Think of this variable base as a pointer to that object being stored in that array, and that's why, your last modification shows up in all elements of your array.

What you need is a deep copy of the base object before pushing it to array.

use lodash cloneDeep for deep copy.

Object assign can also help perform that, but make sure you read the warning for deep clone before using this.

Comments

0

To expand on Sushanth's answer, you have a couple additional choices.

(1) base function instead of base object:

function getBase() {
  return {
    a: 600,
    b: 1.15,
    c: 0,
    d: 200,
    e: 3,
    f: 3,
    g: 1,
    h: 1,
  };
}

var array2 = []; // You should use array literals instead of `new Array`
for(var i=1;i<=3;i++){
  var base = getBase();

  base.a = base.a*12
  base.b = base.b-0.01
  base.d = base.d*4
  base.e = Math.ceil(base.e * 1.5)
  base.f = base.e
  array2.push(base)
}

(2) Object.assign - If you're in node4+ (or at least a browser environment that doesn't support IE11 or lower), you can copy a flat object (no nested properties) with this. Neeraj Sharma's answer touches on what to do if you have nested properties.

var _base = {
  a: 600,
  b: 1.15,
  c: 0,
  d: 200,
  e: 3,
  f: 3,
  g: 1,
  h: 1,
};

var array2 = []; // You should use array literals instead of `new Array`
for(var i=1;i<=3;i++){
  var base = Object.assign({}, _base);

  base.a = base.a*12
  base.b = base.b-0.01
  base.d = base.d*4
  base.e = Math.ceil(base.e * 1.5)
  base.f = base.e
  array2.push(base)
}

Comments

0

In your case, you are pushing array elements from same reference. To push elements from different references you can use the tricky line below. No need for deep copy.

array2.push(JSON.parse(JSON.stringify(base)));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.