AllisonC
AllisonC

Reputation: 3099

Modifying an object causes the modifications to be reflected in a copy of that object previously pushed to an array

I have code similar to the following

var l_mattes_array = [];
var matte_array = [];
var mattes = [];
mattes[0] = "<test><imgsrc>test1</imgsrc></test>";
mattes[1] = "<test><imgsrc>test2</imgsrc></test>";
$(mattes).each(function(i, el)
{
  matte_array.imgsrc = ($(el).find("imgsrc").first().text());
  l_mattes_array[i] = matte_array;
  console.log(l_mattes_array[i]);
});
console.log(l_mattes_array);

The output I am getting is:

[imgsrc: "test1"]
[imgsrc: "test2"]

(2) [Array(0), Array(0)]
0:[imgsrc: "test2"]
1:[imgsrc: "test2"]

The output I want: [imgsrc: "test1"] [imgsrc: "test2"]

(2) [Array(0), Array(0)]
0:[imgsrc: "test1"]
1:[imgsrc: "test2"]

Upvotes: 3

Views: 54

Answers (4)

Yosvel Quintero
Yosvel Quintero

Reputation: 19070

You can use Array.prototype.map() and remove all html tags with the regular expression /<{1}[^<>]{1,}>{1}/g.

Code:

const mattes = ['<test><imgsrc>test1</imgsrc></test>', '<test><imgsrc>test2</imgsrc></test>'];
const l_mattes_array = mattes.map(el => ({imgsrc: el.replace(/<{1}[^<>]{1,}>{1}/g, '')}));

console.log(l_mattes_array);

Upvotes: 0

doubleOrt
doubleOrt

Reputation: 2507

The problem is that matte_array is a reference type (all objects are, and arrays are objects, so yes). What this means is, when you say l_matte_array[i] = matte_array, you are actually setting that index of l_matte_array to a reference to the value of the array matte_array, and then when you modify the matte_array again in the second iteration, you are modifying the value referenced by matte_array, that value is the same value that you set l_matte_array[i] to refer to in the preceding iteration.

So all your l_matte_array indices are merely holding a reference to a single shared value, and you have modified that value to have its imgsrc property be equal to "test2".

Go read this MDN article, you will come out of it having a nice understanding of JavaScript datatypes.


Another problem with you code is, you are using an array as an object, which is inappropriate. Use an array if you want to take advantage of its functionality of having numerically indexed elements; if you want to group some properties and/or methods somewhere, just use a normal object (created with a literal: var obj = {}); if you want something to hold a single value, use a variable.

So, I solved your problem in the following way (I am not using a variable for imgsrc because I believe you are modifying the objects that hold imgsrc sometime later in your code, if you are not adding any properties/methods to the objects that you push to l_mattes_array, just replace my object with an imgsrc variable):

var l_mattes_array = [];
    var mattes = [];

    mattes[0] = "<test><imgsrc>test1</imgsrc></test>";
    mattes[1] = "<test><imgsrc>test2</imgsrc></test>";

    $(mattes).each(function(i, el) {
      var matte_object = {};
      matte_object.imgsrc = ($(el).find("imgsrc").first().text());
      l_mattes_array[i] = matte_object;
    });

    console.log(l_mattes_array);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Upvotes: 2

Piyin
Piyin

Reputation: 1834

The problem is you're referencing the same object (matte_array), so you're changing the src property but the reference is still the same. What you could to is just initialize matte_array inside the cycle, so each time it becomes a new array, like this:

// ...
// var matte_array = []; // Should not be here
// ...
$(mattes).each(function(i, el)
{
  var matte_array = []; // Should be here
  // ...
});
// ...

Here you have a working example: https://jsfiddle.net/6j73wgdw/

Upvotes: 0

AllisonC
AllisonC

Reputation: 3099

I added

matte_array = [];

after adding to l_mattes_array and that fixed it

Upvotes: -1

Related Questions