分享一下今天做的一次实验!
问题重现:打开浏览器执行以下代码
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}}
是刚开始期望的结果。