为何JavaScript的splice方法调用前就已影响原数组?
问题原因与解决办法
核心原因
JavaScript里数组是引用类型,浏览器控制台的console.log默认不会立即生成数组的快照。当你在控制台展开数组查看时,它才会去读取数组当前的实际状态——而这时候你已经调用splice修改了数组,所以两次日志显示的都是修改后的结果。
并不是splice回溯影响了第一个console.log,而是控制台的延迟求值特性让你产生了“提前修改”的错觉。
验证方式
把第一个console.log改成快照形式,就能看到真实的初始状态:
const z = [[1, 2, 3, 4, 5]]; // 转成字符串强制生成快照 console.log(JSON.stringify(z)); // 输出: [[1,2,3,4,5]] z[0].splice(1, 1); console.log(z); // 输出: [[1,3,4,5]]
解决办法
如果需要记录数组的历史状态,不能直接保存引用,要做深拷贝:
- 对于简单数组,用
JSON.parse(JSON.stringify(arr)):const z = [[1, 2, 3, 4, 5]]; // 保存初始快照 const history = JSON.parse(JSON.stringify(z)); z[0].splice(1, 1); console.log(history); // 初始状态 [[1,2,3,4,5]] console.log(z); // 修改后状态 [[1,3,4,5]] - 对于包含函数、Symbol这类复杂类型的数组,需要用递归实现深拷贝,或者借助第三方工具(比如Lodash的
_.cloneDeep)。
内容的提问来源于stack exchange,提问作者Professional - No Lifer
相关产品推荐
相关产品推荐

