console.log 将在最后一个执行状态显示对象,而不是在调用 console.log的状态。
- 不展开对象看时,console.log()是按照代码执行顺序,同步地输出了对象当时的快照。所以我们看到的是预期的值。
- 展开对象时,它其实是重新去内存中读取对象的属性值,此时对象属性已被更改,所以展开对象后,可能看到的不是预期值了。
var obj = {'k1':[1,2,3], 'k2':[2,3,4]}
console.log( JSON.stringify(obj) ) // {'k1':[1,2,3], 'k2':[2,3,4]}
console.log( JSON.stringify(obj.k1) ) // [1,2,3]
obj['k1'] = [0,2,3]
console.log( JSON.stringify(obj.k1) ) // {'k1':[0,2,3], 'k2':[2,3,4]}
console.log( JSON.stringify(obj) ) // [0,2,3]
当我们在输出对象时我们看到的数据是异步处理最终的值,但是当我们仅输出对象中的某一key时,输出的值就是当前的值,从中我们可以看出实际上不同的浏览器实际异步处理的是对象的引用,当我们console.log输出对象时调用的是一个引用,如果我们仅输出其中的值,浏览器就不会进行异步处理输出最终的调用值。同理使用JSON.stringfy一样,浏览器仅仅异步处理对象,并不会处理序列化JSON字符串,所有输出的数据是当前的值,而不是最终值。
console.log()打印出来的内容并不是一定百分百可信的内容。一般对于基本类型number、string、boolean、null、undefined的输出是可信的。
但对于Object等引用类型来说,则就会出现上述异常打印输出。
建议
尽量不要直接输出对象,先将对象序列化JSON.stringify()为字符串再输出
最好使用打断点(debugger)的方式来调试。
引用大佬文章的引用:((●ˇ∀ˇ●))
There is no specification or set of requirements around how the console.* methods work – they are not officially part of JavaScript, but are instead added to JS by the hosting environment (see the Types & Grammar title of this book series).
So, different browsers and JS environments do as they please, which can sometimes lead to confusing behavior.
In particular, there are some browsers and some conditions that console.log(…) does not actually immediately output what it’s given. The main reason this may happen is because I/O is a very slow and blocking part of many programs (not just JS). So, it may perform better (from the page/UI perspective) for a browser to handle console I/O asynchronously in the background, without you perhaps even knowing that occurred.
并没有什么规范或一组需求指定console.* 方法族如何工作——它们并不是JavaScript 正式的一部分,而是由宿主环境(请参考本书的“类型和语法”部分)添加到JavaScript 中的。因此,不同的浏览器和JavaScript 环境可以按照自己的意愿来实现,有时候这会引起混淆。
尤其要提出的是,在某些条件下,某些浏览器的console.log(…) 并不会把传入的内容立即输出。出现这种情况的主要原因是,在许多程序(不只是JavaScript)中,I/O 是非常低速的阻塞部分。所以,(从页面/UI 的角度来说)浏览器在后台异步处理控制台I/O 能够提高性能,这时用户甚至可能根本意识不到其发生。