返回

热点面试题: console.log() 同异步问题?

发布时间:2023-02-19 18:06:31 267
# javascript# java# java# 数据# 工具

前言

极度投入,深度沉浸,边界清晰

前端小菜鸡一枚,分享的文章纯属个人见解,若有不正确或可待讨论点可随意评论,与各位同学一起学习~

欢迎关注 ​​『前端进阶圈』​​ 公众号 ,一起探索学习前端技术......

公众号回复 ​​加群​​​ 或 ​​扫码​​, 即可加入前端交流学习群,长期交流学习......

公众号回复 ​​加好友​​,即可添加为好友

热点面试题:console.log()同异步问题?

  • eg:

var a = {
index: 1,
};

// 然后
console.log(a);

// 再然后
a.index++;

  • 以上代码在 ​​开发者工具控制台​​​ 和 ​​浏览器控制台​​ 的输出情况:
  • 开发者工具控制台
  • 浏览器控制台
  1. 展开前:
  2. 展开后

Q: 为什么会出现这个异常输出呢?

  • R:个人认为,在​​开发者工具控制台​​​ 和 ​​浏览器控制台​​输出结果是不同的,主要原因是在类型上。
  • 在 js 中对象是引用类型,每次使用对象时,都只是使用了对象在堆内存的引用。
  • 前述代码,在修改 ​​a.index++​​​后,​​a​​​ 在堆内存中 ​​index​​​ 值其他变成了 ​​2​​​,当不展开看的时候,​​console.log()​​​ 打印的是对象当时的快照,所以我们看到的 ​​index​​​ 值是修改之前的 ​​1​​​,当展开对象时,它实际上是重新去堆内存中读取对象的属性值了,因此当展开对象后看到的 ​​index​​​ 值为 ​​2​​。

在 ​​《你不知道的javascript中卷》​​ 书中,第二部分 异步和性能 -> 第一章 异步:现在与将来 -> 异步控制台 有说起:

并没有什么规范或一组需求指定`console.*方法族`如何工作——它们并不是JavaScript正式的一部分,而是由宿主环境(请参考本书的“类型和语法”部分)添加到JavaScript中的。

因此,不同的浏览器和JavaScript环境可以按照自己的意愿来实现,有时候这会引起混淆

尤其要提出的是,在某些条件下,某些浏览器的`console.log(..)`并不会把传入的内容立即输出。出现这种情况的主要原因是,在许多程序(不只是JavaScript)中,I/O是非常低速的阻塞部分。所以,(从页面/UI的角度来说)浏览器在后台异步处理控制台I/O能够提高性能,这时用户甚至可能根本意识不到其发生。

下面这种情景不是很常见,但也可能发生,从中(不是从代码本身而是从外部)可以观察到这种情况:
var a = {
index: 1,
};

// 然后
console.log(a);
console.log(a.index);

// 再然后
a.index+=1;

  • 我们通常认为恰好在执行到 ​​console.log(..)​​​ 语句的时候会看到a对象的快照,打印出类似于 ​​{ index: 1}​​​ 这样的内容,然后在下一条语句 ​​a.index++​​ 执行时将其修改,这句的执行会严格在a的输出之后。
  • 多数情况下,前述代码在 ​​开发者工具的控制台​​​ 中输出的对象表示与期望是一致的。但是,这段代码运行的时候,浏览器可能会认为需要把控制台I/O延迟到后台,在这种情况下,等到 ​​浏览器控制台​​​ 输出对象内容时,​​a.index++​​​可能已经执行,因此会显示​​{ index: 2 }​​。
  • 到底什么时候控制台I/O会延迟,甚至是否能够被观察到,这都是游移不定的。​​如果在调试的过程中遇到对象在 ​​​console.log(..)​​ 语句之后被修改,可你却看到了意料之外的结果,要意识到这可能是这种I/O的异步化造成的。​

书中建议:

  • 如果遇到这种少见的情况,最好的选择是在JavaScript调试器中使用断点,而不要依赖控制台输出。次优的方案是把对象序列化到一个字符串中,以强制执行一次“快照”,比如通过 ​​JSON.stringify(..)​​。

总结:

  • 综上所述,​​console.log()​​​ 打印出来的内容不能100%可信,但通常对于 ​​Number, String,Boolean, Null, Undefined​​​ 的打印内容是可信的,但对于 ​​Object​​ 等引用类型来讲,就会出现上述异常打印。
  • 建议:对于一般基本类型的调试,可使用 ​​console.log()​​​ 基本不会出现问题。但在调试对象时,最好使用打断点 ​​(debugger)​​ 来调试更好。
  • 回答问题,个人认为,在 ​​Number, String, Boolean, Null, Undefined​​​ 类型上,​​console.log()​​​ 是同步的,但在 ​​Object​​ 等引用类型上不好做评判。也欢迎大家在评论区讨论~

文章特殊字符描述:

  1. 问题标注 ​​Q(question)​
  2. 答案标注 ​​R(result)​
  3. 注意事项标准:​​A:(attention matters)​
  4. 详情描述标注:​​D:(detail info)​
  5. 总结标注:​​S:(summary)​
  6. 分析标注:​​Ana:(analysis)​
  7. 提示标注:​​T:(tips)​

往期回顾:

  • ​​热点面试题:进程系列问题?​​
  • ​​热点面试题:Node.js 中的垃圾回收机制?​​
  • ​​热点面试题:简述 http3.0~http1.0 分别有什么改进?​​
  • ​​JavaScript中的AMD和CMD规范​​
  • ​​Vue数据监听Object.definedProperty()方法的实现​​

最后:

  • 欢迎关注 ​​『前端进阶圈』​​ 公众号 ,一起探索学习前端技术......
  • 公众号回复 ​​加群​​​ 或 ​​扫码​​, 即可加入前端交流学习群,长期交流学习......
特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像
精选文章
thumb 中国研究员首次曝光美国国安局顶级后门—“方程式组织”
thumb 俄乌线上战争,网络攻击弥漫着数字硝烟
thumb 从网络安全角度了解俄罗斯入侵乌克兰的相关事件时间线