为何console.log()仅在刷新后才显示更新后的Array?
为什么
console.log()输出数组时,刷新页面才能看到更新后的内容? 这是浏览器控制台一个很容易踩坑的特性——对于引用类型(比如数组、对象),console.log默认不会立即生成数据快照,而是保存对该数据的引用。当你在控制台里点击展开这个数组的时候,浏览器才会去读取它当前的实际值,这时候你的数组已经被后面的forEach代码修改了,所以你看到的是修改后的结果,而不是执行console.log那一刻的状态。
咱们拆解下你的代码逻辑:
function getRandomIntInclusive(min, max) { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1)) + min; } function curveScore(original, curveAmount) { return original + curveAmount; } //Generate a random array const testScores = Array.from({ length: 20 }, () => getRandomIntInclusive(60, 100)); console.log(testScores); // 这里打印时,控制台只存储了数组的引用,没立即读取内容 // Updated testScores with curved scores testScores.forEach((el, i, curvedScores) => { curvedScores[i] = curveScore(el, 10); }); console.log(testScores); // 此时数组已经被修改,控制台同样存储引用
当你第一次打开控制台,点击第一个testScores的展开箭头时,数组早已经被forEach完成修改,所以你看到的是加了10后的分数,和第二个打印的结果完全一致。但刷新页面后,控制台会重新记录每一次打印的时机,如果你在代码执行过程中快速展开第一个数组(或者用下面的方法强制生成快照),就能看到修改前的原始分数了。
解决方法:看到console.log执行时的真实状态
有几种实用的办法可以避开这个坑:
- 强制生成快照:把数组转换成副本或字符串,比如
console.log([...testScores])(创建新数组副本)或者console.log(JSON.stringify(testScores, null, 2))(转成格式化字符串),这样打印的是执行那一刻的静态内容,不会受后续修改影响。 - 使用调试断点:在
console.log(testScores)那一行加个断点,当代码停在断点时,数组还没被修改,这时候查看控制台就能看到原始状态。 - 开启控制台“Preserve log”功能:勾选后页面刷新会保留之前的日志,配合刷新可以对比前后打印的状态,但不如前两种方法直接。
本质上这不是你的代码逻辑有问题,只是控制台的引用延迟求值特性在“搞事情”~
内容的提问来源于stack exchange,提问作者CodeFinity
相关产品推荐
相关产品推荐

