console.log的踩坑日记

157 阅读3分钟

坑爹的console.log

const obj = {
    a: 'a'
}
console.log(obj);
obj.b = 'b'
上面的结果输出会是什么呢?

{a: 'a'} 还是 {a: 'a', b: 'b'}

结果是你还没点击展开查看时会显示第一种,即{a: 'a'}, 点击展示后你会看到第二种{a: 'a', b: 'b'} (右上角会多一个蓝色的i)

const obj = {
    a: 'a'
}
console.log(obj);
setTimeout(() => {
    obj.b = 'b'
}, 2000)
这次上面的输出结果会是什么呢?

{a: 'a'} 还是 {a: 'a', b: 'b'}

结果是你还没点击展开查看时会显示第一种,即{a: 'a'}。

当你在两秒内点击展示你会看到{a: 'a'},此时反复点击展开关闭都只是显示{a: 'a'}(右上角会多一个蓝色的i)。

当你在两秒后点击展开你会看到{a: 'a', b: 'b'} (右上角会多一个蓝色的i)

对此还是似懂非懂,所以拿了setInterval做了测试

const obj = {
    a: 'a'
}
console.log(obj);
let b = 'b'
setInterval(() => {
    obj[b] = 'b'
    b += 'b'
}, 1000)
这次上面的输出结果会是什么呢?

{a: 'a'} 还是 {a: 'a', b:'b', bb:'b', .....}

结果符合预期,当你没点开展示的时候只会显示{a: 'a'}, 当你点击展示的时候,会展示出你点击的那时刻setInterVal对obj添加了多少元素,并且右上角出现蓝色的i

蓝色的i告诉你,打印出来的值可能已经改变了(引用类型皆是)

不展示时会显示对象当时快照,点击展示时会去堆栈里查找当前地址对应的数据

浏览器或者开发者工具(F12)为什么出现这种情况?

这个问题,在《你不知道的javascript中卷》第二部分异步和性能1.1节一部控制台部分有提及:

并没有什么规范或一组需求指定console.* 方法族如何工作——它们并不是JavaScript 正式的一部分,而是由宿主环境(请参考本书的“类型和语法”部分)添加到JavaScript 中的。因此,不同的浏览器和JavaScript 环境可以按照自己的意愿来实现,有时候这会引起混淆。 尤其要提出的是,在某些条件下,某些浏览器的console.log(..) 并不会把传入的内容立即输出。出现这种情况的主要原因是,在许多程序(不只是JavaScript)中,I/O 是非常低速的阻塞部分。 所以,(从页面/UI 的角度来说)浏览器在后台异步处理控制台I/O 能够提高性能,这时用户甚至可能根本意识不到其发生。

结论: console.log打印出来的内容并不是一定百分百可信的内容。点击展示的内容可能会被后面的程序改变。

爬坑地点:

1.el-dialog中使用close方法调用el-form的resetFields去重置表单和移除校验结果,表单会在点击提交时被重置,所以打印出来的是还没更改的值,而此时你发起请求的数据是你更改后的。

解决办法:

1.可以在打印时做一层拷贝,更换打印对象的地址, { ...obj } 或者 console.log(JSON.parse(JSON.stringify(obj)))

2.用debugger断点调试,或者在控制台打个断点进行数据查看

\