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

12
我想用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' } 
]

这是因为 closer 函数引起的吗?我应该如何改进它?

4个回答

36

这是因为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);


7
您总是在覆盖同一个对象。
在for循环行之后需要添加以下内容。
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 = {} 是无用的,不是吗? - Technoh
@isvforall,在哪里?是什么? - Nina Scholz

6

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

1

我有类似的问题。这是因为当你执行以下操作时,你只是推送了一个对象的“引用”,当对象值在循环中更新时,被推送的对象也会更改值,因为它只是一个“引用”,最终在循环中设置的最后一个值也被设置为“引用”,因此你看到了被推送的最后一个对象的多个值。

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/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#warning_for_deep_clone。此链接提供了有关深拷贝的警告信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接