使用array.push(obj)创建对象数组报错:仅最后一项被推入结果数组
解决对象数组仅显示最后一组值的问题
嘿,我一眼就看出问题出在哪啦!你遇到的是JavaScript里引用类型的经典坑——大概率是你在循环外只创建了一个对象,每次循环都修改这个对象的属性,最后把同一个对象的引用反复push到数组里,结果数组里所有元素都指向同一个对象,自然显示的都是最后一次修改的结果~
先看错误的写法(就是你现在可能在用的)
const keysArray = ['key1', 'key2', 'key3', 'key4']; const valuesArray = [ ['value1', 'value2', 'value3', 'value4'], ['value5', 'value6', 'value7', 'value8'], ['value9', 'value10', 'value11', 'value12'] ]; const results = []; let foo = {}; // 只创建了一个对象,所有循环都修改它 for (let i = 0; i < valuesArray.length; i++) { const values = valuesArray[i]; for (let j = 0; j < keysArray.length; j++) { foo[keysArray[j]] = values[j]; } results.push(foo); // 每次push的都是同一个foo的引用 } console.log(results); // 所有项都是最后一组{key1: 'value9', ...}
问题根源
对象是引用类型,你在循环外声明的foo只有一个实例,每次循环修改的都是这个实例的属性。把它push到数组里时,数组存的不是对象的副本,而是指向这个对象的“指针”。所以最后数组里的所有元素都指向同一个对象,自然显示的都是最后一次循环修改后的结果。
正确的写法(把对象创建放到循环内部)
只需要把foo = {}移到循环里面,让每次循环都生成一个新的对象实例:
const keysArray = ['key1', 'key2', 'key3', 'key4']; const valuesArray = [ ['value1', 'value2', 'value3', 'value4'], ['value5', 'value6', 'value7', 'value8'], ['value9', 'value10', 'value11', 'value12'] ]; const results = []; for (let i = 0; i < valuesArray.length; i++) { const foo = {}; // 每次循环都创建新的对象! const values = valuesArray[i]; for (let j = 0; j < keysArray.length; j++) { foo[keysArray[j]] = values[j]; } results.push(foo); // 现在push的是不同的对象引用 } console.log(results); // 每个对象都对应各自的值组啦!
更简洁的写法(用map+reduce)
如果喜欢函数式编程风格,可以用map遍历值数组,配合reduce生成每个对象:
const results = valuesArray.map(values => { return keysArray.reduce((obj, key, index) => { obj[key] = values[index]; return obj; }, {}); // 每次reduce都传入新的空对象作为初始值 });
这里每次map迭代时,reduce都会创建一个新的空对象来组装键值对,同样避免了引用共享的问题。
核心总结
只要记住:引用类型(对象、数组)存的是引用,不是副本。如果要生成多个独立的对象,一定要在每次循环/迭代时创建新的实例,而不是复用同一个对象。
内容的提问来源于stack exchange,提问作者user9397809
相关产品推荐
相关产品推荐

