console.log是同步还是异步?眼见不一定为实

分享一下今天做的一次实验!
问题重现:打开浏览器执行以下代码

var a = {b:{c:1}};
console.log(a);
a.b.c = 2;
控制台看到打印出来的是什么?{b:{c:2}}对吗?由此你得出console.log应该是异步的结果。我能告诉你眼见不一定为实么?你所看到的是错误的!拿同样的代码放到node环境下跑你就会发现打印出的是{b:{c:1}}。
是不是感觉很无奈?同一个V8引擎,执行结果最后居然不一样!
事实上,执行结果是一样的,只不过你看到的不一样罢了!原因就出在浏览器控制台所见不一定为实。
尝试把打印的代码换一下,改为console.log(a.b.c)你会发现这次是跟node下一致了。我也不想在此延伸浏览器控制台的问题了,实际上相当于一种懒加载,这也是为什么你可以在控制台无限查看Object的prototype了。
回到问题本身,console.log究竟是同步还是异步?我觉得console.log应该和alert一样是同步的,会阻塞线程执行。丢一个问题这里:

function test() {
console.log('a'); // 为什么加上console.log之后,执行不会报Maximum call stack size exceeded
test();
}
test();

答案:
其实在 console.log 执行的时候,chrome 会对 log 的对象求一次值,打印出来是 Object ,可以继续展开的。但当你展开控制台中的 Object 的时候,chrome 又会对它求一次值,这一次是显示它的属性。所以才会有前后打印的东西不一样的情况发生,因为对象引用的实体的值改变了。
如果把 console.log(a) 改为 console.log(JSON.stringify(a)), 这时就会输出
{"b":{"c":1}}
是刚开始期望的结果。

推荐阅读更多精彩内容

  • pdf下载地址:Java面试宝典 第一章内容介绍 20 第二章JavaSE基础 21 一、Java面向对象 21 ...
    王震阳阅读 70,379评论 26 501
  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    泰迪学长_阅读 1,661评论 0 12
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 68,112评论 12 115
  • 生活喜欢单纯傻傻的精灵 复杂的心情 比较着功利 错过了美好的风景 人生总有些挥之不去的阴影 做错了决定 还想着回去...
    微心诗话阅读 18评论 0 0
  • 我这里依然以张三为例子,让大家来看看,在什么样的情况下,张三患的是疑病症。 张三一年前投资失败,加上...
    夏雨凡星阅读 270评论 0 1