Angular2+中克隆变量仍致原数据变更的问题排查
你遇到的问题是浅拷贝导致的引用共享,我来给你拆解清楚:
为什么当前代码没切断引用?
你用的扩展运算符 [...this.contactInformation.business] 属于浅拷贝——它只会复制数组本身的结构,但数组里的每个 item 对象,依然和原数组 contactInformation.business 里的对象指向同一个内存地址。
简单来说:原数组里的对象是{ contactName: "张三" },浅拷贝后的数组里的item还是指向这个对象,所以你修改item.contactName时,本质上还是在修改原对象的属性,自然会同步到contactInformation里。
怎么彻底切断引用?
你需要对数组里的每个对象也做拷贝(也就是深拷贝数组的元素),这里有几种适合Angular场景的方案:
方案1:用map配合对象扩展运算符(推荐,简单高效)
如果你的business数组里的对象都是简单的普通对象(没有嵌套对象、函数等),可以用map遍历每个元素,并用对象扩展运算符创建新对象:
ngOnInit() { this.businessArray = this.contactInformation.business.map(item => ({ ...item })); }
这样每个item都是全新的对象,和原数组的对象完全独立,修改businessArray里的属性就不会影响原数据了。
方案2:JSON序列化反序列化(适合有嵌套对象的场景)
如果你的对象有多层嵌套结构,可以用JSON.parse(JSON.stringify(...))做深拷贝,但要注意这个方法的局限性:无法处理函数、undefined、循环引用以及Date对象(会被转成字符串):
ngOnInit() { this.businessArray = JSON.parse(JSON.stringify(this.contactInformation.business)); }
方案3:自定义克隆方法(适合自定义类实例)
如果business里的元素是自定义类(比如BusinessModel)的实例,推荐给类添加克隆方法,或者手动创建新实例并赋值:
// 假设你的业务对象是BusinessModel类的实例 ngOnInit() { this.businessArray = this.contactInformation.business.map(item => { const newItem = new BusinessModel(); Object.assign(newItem, item); // 把原对象的属性赋值给新实例 return newItem; }); }
验证效果
修改后的代码运行后,你再通过输入框修改item.contactName,只会改变businessArray里的对象属性,原contactInformation.business的数据就不会被同步修改了。
内容的提问来源于stack exchange,提问作者Pascal

