React中函数内修改对象结果异常,与浏览器控制台表现不符
问题分析与解决
嘿,我之前也踩过这个浏览器控制台的小坑!这不是React的问题,是控制台本身的特性导致的~
为啥会出现这种“异常”?
浏览器控制台打印对象的时候,并不是立刻把对象当时的状态拍个快照存下来,而是只保存了这个对象的引用。等你后续修改了对象的属性,再去点开控制台里的日志条目,看到的会是对象最新的状态,而不是你调用console.log那一刻的状态。
看你的代码:
const makeChanges = i => { i.foo = "test"; i["new"] = "i am new"; return i; }; function App() { var A = { foo: "foo", bar: "bar" }; console.log(A); // 这里存的是对象的引用,不是当时的内容 A = makeChanges(A); // 直接在原对象上修改了属性 console.log(A); // 还是同一个对象的引用 }
因为makeChanges是直接修改传入的对象(没有创建新对象),两次console.log指向的是同一个对象。等你在控制台展开查看时,对象已经被改完了,所以两次显示的都是修改后的结果。
你说在浏览器控制台单独执行能得到预期结果,是因为分步执行时,每一步操作后对象的状态是固定的,控制台能捕捉到当时的快照。
怎么搞定这个问题?
要看到打印那一刻的真实状态,你需要在打印时生成对象的快照,而不是直接打印引用。常用的两种方法:
深拷贝快照(适合嵌套对象):
用JSON.parse(JSON.stringify())来复制一个和原对象内容完全一样的新对象,后续修改原对象不会影响这个快照:console.log(JSON.parse(JSON.stringify(A)));浅拷贝快照(适合简单层级对象):
用ES6的展开语法快速生成新对象:console.log({...A});
另外,在React里其实更推荐不直接修改原对象(因为React依赖状态的不可变性来正确触发重新渲染),你可以修改makeChanges函数,返回一个新对象:
const makeChanges = i => { return {...i, foo: "test", "new": "i am new"}; };
这样原对象A不会被改动,两次console.log就会分别显示原对象和新对象的状态,哪怕控制台是引用也能看到正确结果啦~
内容的提问来源于stack exchange,提问作者Ali Ahmadi
相关产品推荐
相关产品推荐

