10

I want to make an array that including object by for loop but there is a problem, The shape what I want is below :

[ 
  { data: 'apple', label: 'Fruits'  },
  { data: 'banana', label: 'Fruits' },
  { data: 'mango', label: 'Fruits'  } 
]   

So I tried to below way, but It's not working properly.

var arr = [];
obj = {};
var fruits = ['banana', 'apple', 'mango'];
var label = 'Fruits';

for (var i=0; i<fruits.length; i++){
    obj['data'] = fruits[i];
    obj['label'] = label;
    arr.push(obj);
}

console.log(arr);

The result is just same object pushed.

[
  { data: 'apple', label: 'Fruits' },
  { data: 'apple', label: 'Fruits' },
  { data: 'apple', label: 'Fruits' } 
]

Is this because of closer function ? How can I make it well?

ton1
  • 7,238
  • 18
  • 71
  • 126

4 Answers4

34

That's happening because the obj object is referencing to the same object and it is updated in each iteration.

The same object obj is referenced inside the loop

Move the object declaration inside the loop to create a new object in each iteration.

for(var i = 0; i < fruits.length; i++) {
    var obj = {}; // <---- Move declaration inside loop

    obj['data'] = fruits[i];
    obj['label'] = label;
    arr.push(obj);
}

var arr = [];
var fruits = ['banana', 'apple', 'mango'];
var label = 'Fruits';

for(var i = 0; i < fruits.length; i++) {
    var obj = {};
    obj['data'] = fruits[i];
    obj['label'] = label;
    arr.push(obj);
}

console.log(arr);

A simple way to avoid this is using Array#map to create new array from old.

var arr = fruits.map(fruit => ({
    data: fruit,
    label: label
}));

var arr = [],
    fruits = ['banana', 'apple', 'mango'],
    label = 'Fruits';

var arr = fruits.map(fruit => ({
    data: fruit,
    label: label
}));
console.log(arr);
Tushar
  • 85,780
  • 21
  • 159
  • 179
6

You are always overwriting the same object.

You need after the for line

obj = {};

for creating an empty object

var arr = [],
    obj,
    fruits = ['banana', 'apple', 'mango'],
    label = 'Fruits',
    i;

for (i = 0; i < fruits.length; i++){
    obj = {}; // <----- new Object

    obj['data'] = fruits[i];
    obj['label'] = label;
    arr.push(obj);
}
 
document.write('<pre>' + JSON.stringify(arr, 0, 4) + '</pre>');

A shorter way would be the use of Array#map()

var arr = [], 
    fruits = ['banana', 'apple', 'mango'],
    label = 'Fruits';

arr = fruits.map(function (a) {
    return { data: a, label: label };
});

document.write('<pre>' + JSON.stringify(arr, 0, 4) + '</pre>');
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
5

You should create new object obj inside the loop, you was always reference to the same object.

var arr = [];
var fruits = ['banana', 'apple', 'mango'];
var label = 'Fruits';

for (var i = 0; i < fruits.length; i++) {
    var obj = {};
    obj['data'] = fruits[i];
    obj['label'] = label;
    arr.push(obj);
}
isvforall
  • 8,768
  • 6
  • 35
  • 50
1

I've had a similar issue. This is because when you do following, you're only pushing a 'reference' to the object and when the object value is updated in the loop, the object that was pushed also changes value because it was merely a 'reference' and eventually the last value that was set in the loop is also set in the 'references', hence you see multiple values of the last object that was pushed.

arr.push(obj);

So, to tackle this issue you do the following:

arr.push(JSON.parse(JSON.stringify(obj))); //see Note below

The other way to prevent references is by doing the following:

let obj = { a: 1 };
let copy = Object.assign({}, obj); // Object.assign(target, ...sources)

obj.a = 2;
console.log(copy); // { a: 1 }
console.log(obj); // { a: 2 }

Note: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#warning_for_deep_clone

Pulkit Chaudhri
  • 531
  • 5
  • 6