使用Object.assign赋值后修改newScore仍影响oldScore如何解决?
问题本质
你现在写的words.newScore = Object.assign( {}, words.oldScore )之所以会出现修改同步的问题,核心原因是Object.assign仅支持浅拷贝,无法实现完全独立的对象隔离:
- 浅拷贝仅会遍历目标对象的第一层属性,将字符串、数字、布尔值这类原始值类型的属性完整复制到新对象
- 对于对象、数组这类引用类型的属性,拷贝的是原属性的内存地址引用,而非独立的全新副本
也就是说,只要oldScore存在嵌套结构(哪怕一层嵌套),newScore和oldScore的嵌套属性其实指向的是同一块内存,你通过newScore修改嵌套属性时,自然会同步改动oldScore上的对应值。
独立对象的实现方案
根据你的oldScore实际结构选择对应方案即可:
- 如果oldScore是无任何嵌套的纯一级结构,所有属性都是原始值类型:你现有的
Object.assign代码本身就能实现两个对象完全独立,出现同步问题可以逐属性排查是不是误将某个引用类型的地址直接赋值给了newScore - 如果oldScore存在多层嵌套结构:
- 现代浏览器、Node.js 17+ 环境下直接用原生结构化克隆API即可,代码为
words.newScore = structuredClone(words.oldScore),该方法会完整递归拷贝所有嵌套属性,斩断所有内存引用关联,能支持常规的对象、数组、Date、Map、Set等类型的正确拷贝 - 需要兼容老旧运行环境的纯可序列化场景,可以用
JSON.parse(JSON.stringify(words.oldScore))做临时深拷贝,但要注意这个方法会丢失函数、undefined、Symbol类型属性,也无法正确处理循环引用,Date对象会被转为时间字符串,仅适合无特殊数据类型的简单场景 - 项目已引入工具库(如lodash)的话,直接调用库提供的深拷贝方法是最稳妥的选择,比如
words.newScore = _.cloneDeep(words.oldScore),能覆盖绝大多数边界场景,无需自行处理兼容问题
- 现代浏览器、Node.js 17+ 环境下直接用原生结构化克隆API即可,代码为
注意:所有深拷贝方案都无法直接处理函数、DOM节点、WeakMap这类不可结构化克隆的特殊属性,如果oldScore包含这类内容,需要先手动剥离、单独处理这类属性后再做对象拷贝。
内容的提问来源于stack exchange,提问作者LesDentsDeLaMer
相关产品推荐
相关产品推荐

