函数内filter()引发异常:accountCompare遭非预期过滤的问题求助
问题根源:JavaScript引用类型的共享陷阱
兄弟,你踩了JavaScript里一个经典到不能再经典的坑——对象和数组都是引用类型!你看似把responseHandler的返回值分别赋值给了this.accountView和this.accountCompare,但实际上这俩变量指向的是内存里同一个对象/数组。所以你对this.accountView执行filter()(或者任何修改原对象的操作)时,本质是在修改那个共享的引用对象,this.accountCompare自然也会跟着变,根本不是你以为的“独立常量”。
先验证这个结论
你可以在赋值之后加一行代码测试,一测一个准:
console.log(this.accountView === this.accountCompare); // 会输出true,说明是同一个引用
解决方案:给accountCompare创建独立副本
要让this.accountCompare真的不受accountView操作的影响,你得把responseHandler返回的内容完整拷贝一份,而不是直接赋值引用。根据返回值的类型,有几种常用实现方式:
情况1:返回的是纯数组(无嵌套对象)
用数组自带的slice()或者ES6展开运算符就能快速创建副本:
// 方式一:slice() 方法 this.accountView = this.apiHandler.responseHandler(response); this.accountCompare = this.accountView.slice(); // 方式二:ES6展开运算符,写法更直观 this.accountView = this.apiHandler.responseHandler(response); this.accountCompare = [...this.accountView];
PS:filter()本身是返回新数组的,但如果你后续有修改原数组的操作(比如push/splice),或者数组里存的是对象(修改对象属性也会互相影响),那还是得用下面的深拷贝方法。
情况2:返回的是对象,或包含嵌套对象的数组
这时候浅拷贝(比如上面的展开运算符)就不够用了,必须用深拷贝:
// 简单深拷贝:JSON序列化(注意:会丢失函数、Symbol等特殊类型,适合普通数据场景) const responseData = this.apiHandler.responseHandler(response); this.accountView = responseData; this.accountCompare = JSON.parse(JSON.stringify(responseData)); // 更靠谱的深拷贝:自定义递归函数(支持所有数据类型) function deepClone(obj) { if (obj === null || typeof obj !== 'object') return obj; // 处理数组类型 if (Array.isArray(obj)) return obj.map(item => deepClone(item)); // 处理对象类型 const cloneObj = {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { cloneObj[key] = deepClone(obj[key]); } } return cloneObj; } // 使用示例 const responseData = this.apiHandler.responseHandler(response); this.accountView = responseData; this.accountCompare = deepClone(responseData);
额外提醒
如果你的apiHandler.responseHandler返回的是Immutable对象(比如用Immutable.js库创建的),那引用共享就不会有问题,但从你的场景来看,应该是返回的普通JS对象/数组,所以手动拷贝是必须的。
内容的提问来源于stack exchange,提问作者Sandra Willford
相关产品推荐
相关产品推荐

