网站首页 > 技术文章 正文
我们今天来说说javaScript中的代码执行顺序问题,这是一道非常经典的面试题。
这里我们需要知道的一个知识点是:javascript是一门单线程的脚本语言,代码的执行顺序是自上而下执行的,我们来看一下下面这段代码的执行结果:
console.log(1);
console.log(2);
console.log(3);
//执行结果:1;2;3;
这段代码是自上而下执行的。
我们再看下面这段代码的执行结果:
console.log(1);
setTimeout(function () {
console.log(2);
}, 0);
console.log(3);
// 执行结果:1;3;2;
这段代码的setTimeout里面的代码是在最后才执行的。这是因为setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式(W3CSchool对SetTImeout的定义)。按照定义来看,执行结果也应该是1;2;3; ,然而实际结果却是1;3;2;。这是为什么呢?这就要从浏览器对代码的执行机制来说起了。
那么,来看看下图:
(上图转自Philip Roberts的演讲《Help, I'm stuck in an event-loop》)
我们来看几个摘自MDN的专业术语
heap(堆):对象被分配在堆中,堆是一个用来表示一大块(通常是非结构化的)内存区域的计算机术语。
stack(栈):函数调用形成了一个由若干帧组成的栈。
WebAPIS:囊括 Web 强大脚本能力的每个 API 参考资料, 包括 DOM 、所有相关的 APIs 及可以用来构建 Web 的相关接口。
队列(event queue):一个 JavaScript 运行时包含了一个待处理消息的消息队列。每一个消息都关联着一个用以处理这个消息的回调函数。
—— 摘自MDN
因为javascript是单线程的脚本语言,代码自上而下执行,代码在执行时会被压入执行栈(stack)中,当遇到setTimeout时会将setTimeout函数交给Web API来维护,当异步任务(比如:setTimeout)执行完成后会将对应的回调函数推入事件队列(event queue)中,当执行栈中任务全部执行完成之后浏览器会读取任务队列,把对应的回调函数再压入执行栈中,然后循环执行。这就是所谓的EventLoop。我们再来看看下图,执行结果会是怎样的呢?
执行结果:1;2;3;7;5;4;6;
为什么会得到这样的执行结果呢?为什么不是1;2;3;7;4;5;6;呢?这里涉及到了Macrotask 和 Microtask,即宏任务队列和微任务队列。setTimeout属于Macrotask,而Promise属于Microtask,从上图执行结果可以看出Microtask优先级高于Macrotask,当执行栈全部为空时,先询问是否有微任务,如果有,先执行为任务,全部执行完成后再执行宏任务。
我们再来看看下面这段代码的执行结果:
执行结果:1;2;3;8;5;6;4;7;
与Macrotask有所不同的是,Microtask中的任务不会一个一个压入执行栈中,而是直接压入执行栈,从上图执行结果可以得到佐证。Promise即使放入另外一个Promise的回调函数里,也会先执行Promise的回调,再执行setTimeout的回调。
- 上一篇: 今年最常见的前端面试题,你会做几道?
- 下一篇: 前端百题斩之两个角度一个实战了解事件循环
猜你喜欢
- 2025-01-09 前端百题斩之两个角度一个实战了解事件循环
- 2025-01-09 今年最常见的前端面试题,你会做几道?
- 2025-01-09 这些前端面试题你答对?(附答案解析)
- 2025-01-09 前端面试:关于promise的10个高频面试题(上) #前端面试
你 发表评论:
欢迎- 501℃几个Oracle空值处理函数 oracle处理null值的函数
- 495℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 494℃Oracle分析函数之Lag和Lead()使用
- 482℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 473℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 468℃【数据统计分析】详解Oracle分组函数之CUBE
- 453℃Oracle有哪些常见的函数? oracle中常用的函数
- 449℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 最近发表
-
- Directus 火了!无代码 SQL 数据的协作应用利器!
- PHP和NodeJS的代码执行效率比较(php和nodejs的区别)
- 工商银行获得发明专利授权:“基于数据库映射动态接口的前端页面应用开发方法及装置”
- FAISS和Chroma:两种流行的向量数据库的比较
- 什么是数据库的索引?(数据库索引的定义和作用)
- Vercel和Neon“首次”推出用于前端云的无服务器SQL数据库
- 记一次前端逻辑绕过登录到内网挖掘
- 学Access好还是MySQL好?(access与mysql的语句区别)
- 惬意!清晨慢品 HTML canvas 标签题,面试知识轻松 get
- 前端实现知识图谱-force(d3.js)(前端知识树)
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端react (48)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端富文本编辑器 (47)
- 前端路由 (55)
- 前端数组 (65)
- 前端定时器 (47)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle 中文 (51)
- oracle链接 (47)
- oracle的函数 (57)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)