JavaScript中const对象为何被间接修改?如何保留原始数据?
问题成因
JavaScript中对象属于引用类型:当你把对象作为参数传入函数、或者赋值给其他变量时,传递/存储的只是指向堆内存中同一份对象的内存地址,并不会创建新的独立对象副本。
你的代码里几个逻辑直接导致old_dimen被修改:
var dimen = def_contain、const old_dimen = def_contain这两行操作,只是把同一个对象的引用分别赋值给了两个变量,dimen、old_dimen、def_contain甚至全局的data本质上都指向堆里的同一个对象。const关键字仅限制变量本身存储的引用地址不能被重新赋值,不会限制对引用指向的对象的属性修改——简单说就是你不能把old_dimen重新赋值成其他值,但你通过其他引用修改了原对象内容时,old_dimen访问到的自然是修改后的内容。find_replace函数里直接执行dimen.glob = xxx修改属性,本质就是修改了所有引用共同指向的那份原对象,所以你打印old_dimen时会看到值已经变了,连全局的data对象也会被同步篡改。
修复方案
核心逻辑是:对需要保留的原始数据做独立拷贝,所有修改操作只在拷贝出的新对象上执行,不要直接操作原对象的引用。
根据你的对象结构(存在val嵌套对象),直接用深拷贝生成独立副本最稳妥,不需要担心嵌套属性引用共享的问题:
var data = { "glob": "test1my-account:membership:homepage", "val": { "func": "attr", "name": "variables/prop5" }, "description": "Page Name", "func": "matches" } var replace_dimen_def = { old : "test", new : "new", } function find_replace(dimen){ if (dimen.func == 'matches') { var re_old = new RegExp(replace_dimen_def.old); dimen.glob = dimen.glob.replace(re_old,replace_dimen_def.new); return dimen; } } function update_segment(def_contain){ // 存原始数据的独立深拷贝,和后续操作的对象完全隔离 const old_dimen = structuredClone(def_contain); // 拷贝一份新对象做修改操作,不影响原数据 const dimen = structuredClone(def_contain); const replace_dimen = find_replace(dimen); console.log('原始数据:', old_dimen); console.log('修改后数据:', dimen); } update_segment(data); // 此时全局data也不会被篡改 console.log('全局原始data:', data);
拷贝方案选型说明
- 现代环境(Chrome 98+、Node.js 17+)优先用原生
structuredClone()做深拷贝,支持大部分常规数据类型,兼容性足够的场景下最方便。 - 如果需要兼容更低版本环境,且你的对象都是普通字符串、数字、普通对象/数组结构,可以用
JSON.parse(JSON.stringify(def_contain))实现深拷贝,注意这种方式会丢失函数、undefined、Symbol类型的值,也会把Date对象转成时间字符串。 - 如果你确定后续只会修改对象的第一层属性,不会修改
val这类嵌套对象的内容,也可以用浅拷贝:const old_dimen = {...def_contain},性能更好,但嵌套属性还是和原对象共享引用,修改嵌套值会串数据。
内容的提问来源于stack exchange,提问作者atulsemwal
相关产品推荐
相关产品推荐

