TypeScript数组push对象时意外修改原数组问题咨询
问题产生原因
JavaScript/TypeScript 中的数据类型分为原始类型(number、string、boolean、null、undefined、symbol、bigint)和引用类型(对象、数组、函数)两类,二者的赋值逻辑完全不同:
- 原始类型赋值时,会直接在栈内存中复制一份完整的值,两个变量互相独立,修改其中一个不会影响另一个
- 引用类型的实体存在堆内存中,变量中存储的只是实体的内存地址(引用指针),赋值时仅会复制这个指针地址,不会复制堆内存中的对象实体
你的代码中执行this.neuerBezahlvorgang.push(this.tischContent[0])时,推入新数组的只是tischContent[0]这个对象的引用地址,最终两个数组的对应位置存储的指针指向堆内存中完全同一个对象。此时你修改neuerBezahlvorgang[0]的属性,本质就是在修改堆内存里的原对象,自然tischContent[0]取到的值也会同步变化。
修复方案
核心逻辑是在推入新数组前,先创建原对象的副本,切断两个变量的引用关联。你的业务对象中所有属性都是原始类型(数字、字符串),使用浅拷贝即可满足需求,常用实现方式如下:
- 方式1:使用对象展开运算符(代码最简洁,推荐)
将原push逻辑替换为拷贝后推入:// 先创建原对象的浅拷贝,再推入新数组 this.neuerBezahlvorgang.push({...this.tischContent[0]}); - 方式2:使用Object.assign方法
this.neuerBezahlvorgang.push(Object.assign({}, this.tischContent[0]));
注意:如果后续你的对象中新增了嵌套的对象、数组类属性,浅拷贝只能拷贝外层属性,内层嵌套属性依然是引用关系,此时需要做深拷贝。简单无循环引用的场景可以用
JSON.parse(JSON.stringify(源对象))实现深拷贝,复杂场景推荐使用lodash的_.cloneDeep方法规避特殊值、循环引用导致的拷贝异常。
修正后的完整pushBestellung方法参考:
pushBestellung(itemkey, indexOfElement){ console.log(this.neuerBezahlvorgang); console.log('修改前原数组anzahl值:', this.tischContent[0].anzahl); // 拷贝对象后推入新数组 const newItem = {...this.tischContent[0]}; this.neuerBezahlvorgang.push(newItem); // 仅修改新拷贝的对象,不会影响原数组元素 newItem.anzahl = Math.random(); console.log('修改后原数组anzahl值:', this.tischContent[0].anzahl); }
内容的提问来源于stack exchange,提问作者Fabian Mayer
相关产品推荐
相关产品推荐

