tiramola
tiramola

Reputation: 29

adding objects to array leads to duplicates

I know its fundamental but got stuck. I'm trying to add objects into an array:

Html

<p>
  <label>
    <input type="text" name="test1" id="test1" />
  </label>
</p>
<p>
  <label>
    <input type="text" name="test2" id="test2" />
  </label>
</p>

Script

var res = {};
  var array_res = [];
function init(){
    x= $('#test1').val();   
    res['x'] = x;
    y= $('#test2').val();
    res['y'] = y;       

    array_res.push(res);

    return array_res
}
 $('#btn').click(function(){
 init();
 console.log(array_res);
  });

When first adding x=1 and y=2 i get at console:

[Object { x="1",  y="2"}]

Next i try to insert x=3 and y=4 and i get:

 [Object { x="3",  y="4"}, Object { x="3",  y="4"}]

instead of

 [Object { x="1",  y="2"}, Object { x="3",  y="4"}]

Why is that? I smell its an object instance issue but can't figure out what to do. Thanks in advance

Upvotes: 0

Views: 33

Answers (2)

Mr. Llama
Mr. Llama

Reputation: 20919

When you add an object to an array, you're not adding the object itself, but instead a reference to it. Updating the object itself will also be reflected in the array because the array simply "points" to the object. Because your res object is declared in the global scope, the second call to init() will clobber the previous values which are being pointed to in array_res.

Consider this short demo: https://jsfiddle.net/35uu7bje/

var obj = {a: 5, b: 10};
var arr = [];

arr.push(obj);
console.log("Object in array before update");
console.log(arr[0]);
// Displays {a: 5, b: 10}

obj.a = 25;
console.log("Object in array after update");
console.log(arr[0]);
// Displays {a: 25, b: 10}

To fix this, you should declare res in the function scope so each new call creates a new object instead of recycling an old one:

// Do NOT declare res here
// Doing so will cause every entry in array_res to point to one instance of this object
// var res = {};
var array_res = [];

function init(){
    // Declare it here so each call creates a new res object
    var res = {};

It should also be noted that because objects are passed by reference, passing an object as a parameter to a function allows for the original object to be modified:

var obj = {a: 5, b: 10};

function f( some_obj ) {
    some_obj.a = 25;
}

console.log(obj); // {a: 5, b: 10}
f(obj);
console.log(obj); // {a: 25, b: 10}

Upvotes: 0

Oleksandr T.
Oleksandr T.

Reputation: 77522

Move res variable to init function

var array_res = [];

function init() {
   
    var res = {};
    x = $('#test1').val();   
    res['x'] = x;
    y= $('#test2').val();
    res['y'] = y;       

    array_res.push(res);

    return array_res
}

$('#btn').click(function(){
  init();
 
  console.log(array_res);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>
  <label>
    <input type="text" name="test1" id="test1" />
  </label>
</p>

<p>
  <label>
    <input type="text" name="test2" id="test2" />
  </label>
</p>

<button id="btn">Add</button>

Upvotes: 1

Related Questions