JS遍历数组push对象时所有元素均为最后一个值的问题
问题根因
JavaScript里对象是引用类型,你整个循环过程中一直在反复修改同一个this.productToShowOnView对象的属性,每次往productsInBasket数组里push的都是这个对象的内存地址,不是独立的新对象。等循环执行完,this.productToShowOnView的属性已经被最后一条遍历的商品数据覆盖,数组里所有存了这个对象引用的条目,自然全显示最后一条的4份糖块数据。
另外你代码里还有两处无效逻辑:
const newBasket = this.productsInBasket;拿到的是原数组本身的引用,后面的[...newBasket]展开操作只是浅拷贝了数组壳,数组里存的对象引用一点没变,解决不了问题this.cd.detectChanges()放在循环内每次遍历都触发,完全没必要,只会增加不必要的性能消耗
修复代码
每次循环时为当前商品创建一个独立的新对象,不要全程复用同一个productToShowOnView对象存所有条目数据,循环全部跑完再触发一次变更检测即可:
for (let bill of dataOfBillHeader.billBodies) { console.log(dataOfBillHeader) // 每次循环生成独立的新对象,切断引用关联 const currentProduct = { cipher: bill.product.cipher, name: bill.product.name, measure: bill.product.measure, price: bill.product.price, id: dataOfBillHeader.id, // 原代码先后给count赋了bill.product.count、bill.count两个值,后者会覆盖前者,这里保留你原本的赋值逻辑 count: bill.count, quantity: bill.quantity, discount: bill.discount, discountAmount: bill.discountAmount, totalPrice: bill.totalPrice } // 如果视图绑定需要用到this.productToShowOnView,这里做一次浅拷贝赋值即可 this.productToShowOnView = {...currentProduct} console.log("to show on view is " + JSON.stringify(this.productToShowOnView)); this.productsInBasket.push(currentProduct); } // 所有数据处理完统一触发一次变更检测 this.cd.detectChanges();
避坑提示
- 所有往数组里存对象的场景,只要需要保留多条独立数据,就不能复用同一个对象反复修改属性后push,必须每次新建对象或者做深/浅拷贝生成独立副本
- 数组浅拷贝只会复制数组本身,不会复制数组里存的引用类型对象,不要以为做了
[...arr]操作就解决了对象引用的问题
内容的提问来源于stack exchange,提问作者Ranko Koturic
相关产品推荐
相关产品推荐

