为什么 console.log 一个对象时往往得不到当时的值?

1,848 阅读1分钟

背景

修 bug 时,我常常用 console.log 去查看问题到底出在哪儿了。但当我打印一个对象时,经常不得不使用 JSON.stringify 去打印对象某个时刻的值。

比如:

let object = {a: 1}
console.log(object)
object.a++

执行结果是什么呢?

chrome 中,浅蓝色背景的 i 提示我:value below was evaluated just now.

我以前以为,出现这个现象的根本原因是,对象是一个引用。而从来没有思考过问题可能也出现在 console.log 这个方法身上。

console.log

https://developer.mozilla.org/zh-CN/docs/Web/API/Console/log

从文档可以看到,console.log 不属于任何公开的规范,事实上,不止 console.log ,对于整个 console.* ,都没有什么规范指定它们如何工作。

也就是说,console.* 并不是 javascript 正式的一部分,而是由宿主环境添加到 javascript 中的。

因此,不同的浏览器和 javascript 环境可以按照自己的意愿来实现。

而在某些浏览器里,console.log 并不会把传入的内容立即输出。因为在许多语言里,I/O 都是非常低速的阻塞部分。所以浏览器会选择在后台异步处理控制台 I/O ,以便提高性能。因此用户根本没有意识到这是个异步行为...

补充

什么时候浏览器控制台 I/O 会延迟,是不确定的,如果在调试过程中,对象在 console.log 语句之后被修改,导致你看到了意料之外的结果,要意识到这可能是 I/O 的异步化造成的。

解决方案:

  • 使用断点调试
  • 把对象序列化到字符串中输出