为何这段代码中JavaScript console.log提前显示对象值?
为什么Firefox控制台中对象的输出和预期不符?
先来看你的代码:
var x = {list: [1, 2, 3], num: 4}; console.log(x); function asd(x) { x.list[0] = 4; return x; } console.log(x); asd(x); console.log(x);
你预期的输出应该是:
第一次打印:list: Array [1, 2, 3] num: 4
第二次打印:list: Array [1, 2, 3] num: 4
第三次打印:list: Array [4, 2, 3] num: 4
但实际在Firefox控制台里,三次展开查看的结果都是:
list: Array [4, 2, 3] num: 4
这其实是Firefox控制台的一个容易踩的小“坑”:它打印对象时不会立即生成状态快照,而是保存了对该对象的实时引用。只有当你点击展开控制台里的对象条目时,它才会去读取对象当前的最新状态。
具体到你的代码执行流程:
- 第一次
console.log(x)执行时,x的list确实是[1,2,3],但控制台只是记录了这个对象的引用,没有立刻解析并展示它的内容。 - 第二次
console.log(x)执行时,对象还没被修改,状态依然是[1,2,3],但同样只是保存了引用,没有即时渲染内容。 - 调用
asd(x)后,函数直接修改了x.list的第一个元素(因为对象和数组都是引用类型,函数里的x和外部的x指向同一个内存地址),此时对象的实际状态变成了[4,2,3]。 - 当你后续在控制台里点击展开这三次log的对象时,控制台会去读取对象当前的状态——也就是已经被修改后的
[4,2,3],所以看起来三次输出全是一样的。
如果想要看到执行时的真实快照状态,有两个简单的解决办法:
- 用
JSON.parse(JSON.stringify(x))克隆对象后再打印,这样每次打印的都是当时对象的副本,不会受后续修改影响:console.log(JSON.parse(JSON.stringify(x))); - 在Firefox控制台的设置里,找到「复制时捕获对象值」(类似名称的选项)并开启,这样控制台会在打印时就捕获对象的当前状态,而不是用实时引用。
内容的提问来源于stack exchange,提问作者Physicist137
相关产品推荐
相关产品推荐

