迭代集合文档时所有对象均出现最后一次迭代值的问题排查
问题根源与修复方案
嘿,我一眼就看出你遇到的这个问题——所有对象最后都加载了最后一次迭代的值,这在处理循环和对象引用时是个超级常见的坑!
为什么会出现这个问题?
从你贴的代码片段来看,核心问题出在你复用了类的成员变量this.timingRef。每次在forEach循环里执行this.timingRef = new Timing();时,你其实是在覆盖同一个类属性的引用。如果之后你把this.timingRef添加到某个数组或集合里,本质上每次添加的都是同一个内存地址的引用。等循环结束后,所有集合里的元素指向的都是最后一次创建的Timing实例,自然显示的全是最后一次迭代的值。
打个比方:就像你拿同一个盒子,每次把里面的东西换掉,然后把盒子放进抽屉十次,最后抽屉里的十个“盒子”其实都是同一个,里面的东西当然是最后一次放的那个。
怎么修复?
最直接也最推荐的方法是在循环内部使用局部变量,避免复用类成员变量,这样每次循环都会生成独立的Timing实例,每个实例的引用都是唯一的:
public getxxxxxTimings(key : string) : any { console.log('key '+key); return this.afs.collection('/xxxxx/'+key+'/slots').doc('1').ref.get().then((doc)=>{ const json = doc.data(); console.log('json data ', json); console.log("Document keys:", Object.keys(json)); // 先初始化存储Timing实例的数组(如果还没初始化) this.timingsArray = []; Object.keys(json).forEach((name) => { // 创建局部的Timing实例,而不是用类的this.timingRef const timingInstance = new Timing(); console.log('name '+name); timingInstance.slot = name; timingInstance.available = ...; // 补全你的赋值逻辑 // 将这个独立的实例添加到数组中 this.timingsArray.push(timingInstance); }); return this.timingsArray; // 返回处理后的结果 }); }
如果因为某些特殊原因,你必须使用类成员变量this.timingRef,那可以通过克隆对象的方式避免引用问题(但这个方法不如局部变量直接,只作为备选):
Object.keys(json).forEach((name) => { this.timingRef = new Timing(); console.log('name '+name); this.timingRef.slot = name; this.timingRef.available = ...; // 添加对象的副本到数组,而不是直接添加this.timingRef // 如果Timing是自定义类,可能需要实现一个克隆方法,比如this.timingRef.clone() this.timingsArray.push({...this.timingRef}); });
额外提醒
- 检查你的
Timing类,确保它没有使用静态属性(静态属性是所有实例共享的,也会导致值被覆盖)。 - 如果之后在循环里嵌套了异步操作,记得用
let/const声明变量(避免var的函数作用域导致的闭包问题),不过从当前代码看,你用的forEach参数name是块级作用域的,这部分没问题。
内容的提问来源于stack exchange,提问作者kpvsrkp
相关产品推荐
相关产品推荐

