有许多坑可能真的需要自己去踩一踩😂,不得不说Javascript真的是一门神奇的语言~~;一些看起来习以为常的调用,往往得不到自己想要的结果,只能通过不断踩坑或者别人踩的坑积累经验值,来再次踩坑~~
最近在调bug...由于涉及的链路比较长、多个项目之前通过postMessage来进行通信,首先想到的就是在JS调用链路中通过console.log输出状态变量,观察状态变量是在何时改变的,进行bug定位。
本来一个挺简单的bug,由于console.log的坑,导致在定位bug的路上进入了一个错误的方向,愣是多花了好久时间。最后还是在debugger的帮助下,成功解决了bug。
问题复现
首先来看一段代码
<!DOCTYPE html><html>
<head>
<meta charset="utf-8" >
<title>console.log测试</title>
</head>
<body>
<script>
const obj = { name: 'Tom', height: 170,
}; console.log(obj);
obj.height = 180; </script>
</body></html>
在浏览器控制台中,你认为会输出什么?如果没有踩这个坑之前我估计也会认为会输出这个结果:
然而,
实际上:
是不是感觉像是薛定谔的猫,箱子没打开之前不知道里面是什么状态?
原因
我们知道JS里面分为基本类型和引用类型,具体每个类型的分类可以查看MDN。 我们在代码中调用console.log(obj), 其实就是把obj这个引用类型传给了console.log这个函数,只有这个函数真正用到obj内部属性的时候,才会去内存中查找对应的属性值。
由于console.log并没有标准的实现规范,在chrome里是异步的,导致后面obj.height的赋值先与console.log对height属性的取值,这个顺序问题,造成了上述的问题。
解决办法
一般来说有两种方式可以解决这个问题:
使用同步的方式保存调用console.log时,obj的快照,比较典型的是使用深拷贝、JSON序列化的方式,这样在后续改变obj的属性也不会对console.log的调用造成影响
使用debugger的方式进行调试,不过在长链路的调试中,跳来跳去的调试略微有点麻烦😂
作者:flyingbird
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。