console.log的小坑

996.icu

console.log里的小坑

兼听则明,偏信则暗

最近在写代码的时候,遇到了一个问题,很有趣所以要把这个现象记录下来。我在console.log里获取到的数值,会因为我后面调用的组件而改变,导致我debug的时候一直没有正确地定位到真正发生错误的地方,吃一堑长一智,以后在chrome里debug,不仅要使用console.log,以后还要使用断点调试。

问题描述

这个问题是这样的,我在异步获取到服务器的数据后,我使用了一个甘特图的组件来初始化另一个数据。伪代码大概如下:

1
2
3
4
5
get(url).then(data=>{
console.log(data);
let tempdata={...data,links:[]};
gantt.prom(tempdata);
})

然后我获取到的data一直是错误的,导致我一直以为是服务器端写错的问题。但是在服务器端打了断点,从数据库中获取到数据后,在服务器端的数据流里,变量一直是正确的,然后到了前端里,console.log后就是错误的。

问题解决

后来在同学的帮助下,先在console.log处打了断点,然后发现此时的data还是正确的。然后到了gantt.prom(tempdata)这句话后,data就变成了错误的数据。可以猜想到,这个控件会处理我组件里所有的数据结构,但是一开始没有想到是后面的语句修改了前面的数据数值。

问题分析

那么为什么console.log会发生这种现象呢?我在控制台里输入这样的语句:

1
2
3
let obj={id:1};
console.log(obj);
obj.id=110;

在chrome的控制台里会出现这个语句:

1
{id: 1}

这个和预想的是一样的,但是当我展开的时候,控制台就是这样的情况:

1
2
3
{id: 1}
id: 110
__proto__: Object

也就是说,id确实被改变了。即使控制台已经输出了,但是当展开的一瞬间,会指向新的对象,然后获取到当前对象的数值。产生这个现象的原因就是我打印的是一个对象,是一个引用,当我第一次打印的时候,数值还没有变化,而当我修改后展开这个对象,引用会指向对象,然后获取到新的数值。

但是我还是没有明白为什么gantt这个控件这么强大,可以修改我在react里的数据的属性,强行修改成他所需要的格式,即便是我传递给他的参数并不是data。我一开始分析是由于我的…解析了data放在了tempdata里面,但是后来在试验里发现并不会由于…的解析数据导致原数据的变化。
所以gantt修改数据我还是没有明白,但是console.log这一现象还是值得我在以后的生涯中注意的。而且也意识到了断点的好处,断点即使是在异步里,也可以完美的执行我所想要的顺序。并且可以避免这种调用了一个控件,偷偷在后面的步骤中,修改了之前的数值,导致我log出错的情况。