第 7 卷
| 14 | setTimeout(() => {//宏任务(timers阶段) |
|---|---|
| 15 | console.log('宏任务setTimeout');// 5.执行宏任务 |
| 16 | }, 0); |
17 18console.log('同步任务2'); // 同步任务,立即执行
19 20// 最终执行结果:
21// 同步任务1 → 同步任务2 → nextTick1 → nextTick2 → 普通微任务Promise → 宏任务 setTimeout
process.nextTick的使用场景与注意事项
- 适用场景
- 确保回调函数在当前同步任务执行完后,立即执行(如修改全局变量后,立即执行依赖该变量的回
调);
- 解决异步回调的执行顺序问题,强制插队执行;
- 避免I/O操作的延迟,提升执行效率。
- 注意事项(禁止滥用)
- 避免递归调用process.nextTick(),会导致nextTick队列无限循环,阻塞事件循环,无法执行宏任
务和普通微任务;
- nextTick队列执行耗时过长,会阻塞I/O操作和定时器,影响服务性能;
- 优先使用 queueMicrotask()(ES6标准微任务)替代,兼容性更好,避免Node.js专属API的
耦合。
核心总结
process.nextTick() 是Node.js微任务的最高优先级,执行顺序:
同步任务 > process.nextTick() > 普通微任务(Promise) > 宏任务。
- 什么是垃圾回收机制,并且它是如何在现代编程语言中管理内存的?
垃圾回收机制(Garbage Collection,GC)的定义
垃圾回收机制是编程语言的自动内存管理技术,由垃圾回收器自动完成内存分配、内存使用、内存回收的全流程,无需开发者手动申请/释放内存,解决内存泄漏、内存溢出问题,提升开发效率,降低内
计算机内存是有限资源,程序运行时会申请内存存储数据(变量、对象、函数),若数据不再使用,内存未及时释放,会导致:
- 内存泄漏:无用内存持续占用,内存占用率越来越高,程序运行变慢;
- 内存溢出:内存占用超过系统分配的上限,程序崩溃;
- 手动管理风险:C/C++需手动 malloc() 申请、 free() 释放内存,易出现忘记释放、重复释
放、野指针等问题。
垃圾回收机制的核心原理
- 内存分配:程序创建变量/对象时,垃圾回收器自动向操作系统申请内存,分配给对应数据;
- 可达性分析:垃圾回收器定期扫描内存中的数据,判断数据是否可达(是否有引用指向该数据);
- 可达对象:有变量/函数/对象引用,仍在使用,需保留内存;
- 垃圾对象:无任何引用指向,不再使用,标记为垃圾,等待回收;
- 垃圾回收:垃圾回收器释放垃圾对象的内存,将内存归还给操作系统,供后续数据使用;
- 内存碎片整理:回收内存后,整理内存空间,减少内存碎片,提升内存分配效率。
现代编程语言中GC的核心实现方式(3种主流)
- 1. 引用计数法(Reference Counting)
原理
为每个内存对象维护一个引用计数器,记录对象被引用的次数:
- 对象被创建/引用时,计数器**+1**;
- 对象的引用被销毁/赋值时,计数器**-1**;
- 计数器为0时,标记为垃圾,立即回收内存。
优点
- 回收及时,计数器为0时立即回收,无内存占用延迟;
- 实现简单,垃圾回收器逻辑轻量。
缺点
- 无法解决循环引用问题:两个对象互相引用,计数器永远不为0,无法回收,导致内存泄漏;
- 计数器的增减操作有性能开销,高并发场景影响效率;
- 频繁回收小对象,导致内存碎片增多。
原理(GC的基础算法,主流语言核心)
分为标记阶段和清除阶段,基于可达性分析实现,解决循环引用问题:
- 标记阶段:从根对象(如JS的全局对象、Java的GC Roots)出发,递归扫描所有可达对象,标记
为「存活对象」;
- 清除阶段:扫描整个内存空间,将未被标记的「垃圾对象」的内存释放,归还给操作系统;
- 可选:整理阶段:将存活对象移动到内存连续区域,减少内存碎片(标记-整理法 Mark-
Compact)。
优点
- 解决循环引用问题:循环引用的对象无根引用,会被标记为垃圾,正常回收;
- 适用场景广,支持复杂数据结构(对象、数组、链表);
- 性能优于引用计数法,回收频率可控。
缺点
- 标记/清除阶段会暂停程序执行(STW:Stop The World),导致程序卡顿,大内存场景更明显;
- 清除后产生内存碎片,连续内存不足时,需整理内存,增加开销。
应用语言
JavaScript(V8引擎)、Java(HotSpot引擎)、Go、Python(现代版本)。
- 3. 分代回收法(Generational GC)
原理(现代GC的主流优化方案,基于标记-清除法升级)
根据对象的存活时间,将内存分为新生代和老生代,对不同代采用不同的回收策略,提升回收效率:
- 新生代(Young Generation):存储存活时间短的对象(如临时变量、局部对象),特点是创建
快、销毁快,占用内存小;
◦ 回收策略:复制算法(Copying),将新生代分为2个相等区域,存活对象复制到空闲区域,直
接清空原区域,无内存碎片,回收速度极快;
- 老生代(Old Generation):存储存活时间长的对象(如全局变量、常驻内存的对象),特点是创
建少、销毁慢,占用内存大;
- 回收策略:标记-清除法/标记-整理法,减少复制开销,兼顾回收效率和内存碎片;
- 回收频率:新生代回收频率高(毫秒级),老生代回收频率低(秒/分钟级),降低STW卡顿。
全站分卷索引 · 10 卷
- 1第 1 卷
- 2第 2 卷
- ◦ 处理样式优先级(!important > 行内样式 > ID选择器 > 类/伪类/属性选择器 > 标签/伪元素选择
- 关键特性
- 6. 详述浏览器加载和执行JavaScript文件的机制
- JS加载执行核心机制(单线程+阻塞特性)
- • 浏览器解析HTML时,遇到 <script> 标签,立即暂停后续HTML解析,发起HTTP请求加载JS文
- • 可通过属性优化加载:
- ◦ async:异步加载,加载完成后立即执行(执行顺序不确定,不阻塞HTML解析,阻塞渲
- ◦ defer:异步加载,HTML解析完成后、DOMContentLoaded事件前执行(执行顺序与标签
- ◦ type="module":ES6模块加载,默认异步,遵循 defer 规则,支持按需加载、作用域隔
- • V8引擎采用即时编译(JIT):将AST转换为字节码,再将热点代码(频繁执行)编译为机器码,
- 关键特性
- • 异步JS(async/defer/module)仅解除对HTML解析的阻塞,仍会阻塞 DOMContentLoaded 事
- 3第 3 卷
- 4第 4 卷
- 5第 5 卷
- 6第 6 卷
- ✅ 2. 微任务的优先级和执行时机不同
- ✅ 3. 宏任务的类型和优先级不同
- ✅ 4. 页面渲染的差异
- • Node.js事件循环:无页面渲染环节,Node.js是服务端运行环境,无需渲染页面,专注于I/O处
- ✅ 5. 异步API的支持差异
- • 浏览器:支持DOM事件、AJAX、requestAnimationFrame、MutationObserver等前端专属异步
- • Node.js:支持文件I/O、网络I/O、child_process、setImmediate、process.nextTick等服务端专
- ✅ 6. 任务队列的数量差异
- ✅ 核心差异总结表
- 17. 描述process.nextTick在Nodejs事件循环中的执行顺序及其与微任务
- 的关系
- process.nextTick的定义
- 7第 7 卷
- 8第 8 卷
- 9第 9 卷
- 10第 10 卷
- • 不再使用的全局变量,手动置空释放:`window.data = null`(浏览器)、`delete global.data`
- • 避免闭包长期引用大对象,若必须引用,业务结束后手动清空闭包引用:`persistentClosure =
- • DOM元素移除前,通过`removeEventListener`移除对应的事件监听(注意:监听函数必须与绑
- • 组件生命周期销毁时(如React的`componentWillUnmount`、Vue的`beforeUnmount`),批
- • 定时器/计时器使用后,务必通过`clearTimeout`/`clearInterval`清理,尤其是在组件销毁、页
- • 将定时器ID存储在实例属性中,便于后续清理:`this.timer = setTimeout(...)`,销毁时执行
- • 避免在JS中长期缓存DOM元素,优先通过`document.querySelector`动态获取,减少不必要的
- • 异步任务(Promise/AJAX)确保完成:无论成功/失败,都调用`resolve/reject`;使用
- • 内存缓存设置上限和过期机制:使用`lru-cache`等成熟缓存库(自动淘汰最近最少使用的缓
- • 优先使用`WeakMap/WeakSet`作为缓存:它们的键是弱引用,当键对应的对象无其他引用时,会
- • 浏览器端:使用Chrome开发者工具(Memory面板),通过HeapSnapshot(堆快照)对比内存
- • Node.js端:使用`--inspect`参数启动服务,通过Chrome开发者工具调试;使用`clinic.js`、