New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
console.log()输出时是同步还是异步的问题 #30
Labels
Comments
https://cnodejs.org/topic/59142d12ba8670562a40ef4d |
👍👍 |
收藏了,刚好也遇到了相应的疑惑,多谢了 |
阿伟,是你吗?😄 |
由此可见,console.log打印出来的内容并不是一定百分百可信的内容。一般对于基本类型number、string、boolean、null、undefined的输出是可信的。但对于Object等引用类型来说,则就会出现上述异常打印输出。 所以对于一般基本类型的调试,调试时使用console.log来输出内容时,不会存在坑。但调试对象时,最好还是使用打断点(debugger)这样的方式来调试更好。 |
分析的不错 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
最近帮助一个同学在调试问题的时候,
console.log()
的输出真的让我诧异了一把,因为它竟然会出现异步输出的情况,因而误导了我们的判断,找错了方向,耽误了很多时间,所以这里记录一下遇到的这个问题,加深印象。问题现象:
正常输出:
异常输出:
我们可以发现,异常输出的时候,没展开的时候,显示的name值是
Tom
,点击箭头展开对象里的name则是Jack
,而且,此时的输出值Jack
执行语句,明显是在赋值语句obj.per.name = 'Jack'
之前调用的,展开的时候,却变成了Jack
,明显有些异常,是不是很神奇?我刚遇到这个问题的时候,也是懵逼状态的。为什么会出现这个异常输出呢?
异常出现原因分析
在分析之前,我们得知道一点,JS中对象是引用类型,每次使用对象时,都只是使用了对象在堆中的引用。
当我们在使用
obj.per.name = 'Jack'
改变了对象的属性值时,它在堆中name的值也变成了'Jack'
,而当我们不展开对象看的时候,console.log
打印的是对象当时的快照,所以我们看到的name
属性值是没改变之前的'Tom'
,展开对象时,它其实是重新去内存中读取对象的属性值,所以当我们展开对象后看到的name
属性值是Jack
。浏览器或者可以说是开发者工具为什么会有这样的表现?
这个问题在《你不知道的javascript中卷》第二部分异步和性能1.1节异步控制台部分有提及:
翻译:
书中还了个例子:
我们通常认为恰好在执行到
console.log(..)
语句的时候会看到a 对象的快照,打印出类似于{ index: 1 }
这样的内容,然后在下一条语句a.index++
执行时将其修改,这句的执行会严格在a 的输出之后。多数情况下,前述代码在开发者工具的控制台中输出的对象表示与期望是一致的。但是,这段代码运行的时候,浏览器可能会认为需要把控制台I/O 延迟到后台,在这种情况下,等到浏览器控制台输出对象内容时,
a.index++
可能已经执行,因此会显示{ index: 2 }。到底什么时候控制台I/O 会延迟,甚至是否能够被观察到,这都是游移不定的。
所以如果在调试的过程中遇到对象在console.log(..) 语句之后被修改,可你却看到了意料之外的结果,要意识到这可能是这种I/O 的异步化造成的。
书中建议:
结论
由此可见,console.log打印出来的内容并不是一定百分百可信的内容。一般对于基本类型
number、string、boolean、null、undefined
的输出是可信的。但对于Object
等引用类型来说,则就会出现上述异常打印输出。所以对于一般基本类型的调试,调试时使用console.log来输出内容时,不会存在坑。但调试对象时,最好还是使用打断点(
debugger
)这样的方式来调试更好。The text was updated successfully, but these errors were encountered: