如何在JavaScript中正确地将对象从for循环推送到数组

How to push object to array from for loop properly in JavaScript?

本文关键字:循环 for 数组 对象 JavaScript 正确地      更新时间:2024-06-14

我想通过for循环创建一个包含对象的数组,但有一个问题,我想要的形状如下:

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

所以我试着用下面的方法,但它不能正常工作。

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);

结果就是推送了相同的对象。

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

这是因为函数更紧密吗?我怎样才能做好?

之所以会发生这种情况,是因为obj对象引用了同一个对象,并且在每次迭代中都会更新。

循环内引用相同对象obj

在循环中移动对象声明,以便在每次迭代中创建一个新对象。

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);


避免这种情况的一个简单方法是使用Array#map从旧数组创建新数组。

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);

您总是覆盖同一个对象。

您需要在线路之后

obj = {};

用于创建空对象

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>');

较短的方法是使用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>');

您应该在循环中创建新对象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);
}

我也遇到过类似的问题。这是因为当您执行以下操作时,您只向对象推送一个"引用",当对象值在循环中更新时,被推送的对象也会更改值,因为它只是一个"参考",最终在循环中设置的最后一个值也在"引用"中设置,因此您可以看到最后一个被推送对象的多个值。

arr.push(obj);

因此,要解决这个问题,您需要执行以下操作:

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

防止引用的另一种方法是执行以下操作:

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 }

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