Node.js 高频面试题及详细答案(职场真实版)_第1页
Node.js 高频面试题及详细答案(职场真实版)_第2页
Node.js 高频面试题及详细答案(职场真实版)_第3页
Node.js 高频面试题及详细答案(职场真实版)_第4页
Node.js 高频面试题及详细答案(职场真实版)_第5页
已阅读5页,还剩3页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Node.js高频面试题及详细答案(职场真实版)一、Node.js基础认知1.说说你对Node.js的理解,它和浏览器JS有什么区别?答案:Node.js是一个基于ChromeV8引擎的服务端JavaScript运行时环境,不是一门语言,也不是框架。它让JS可以脱离浏览器,在服务器、本地终端运行,实现后端开发、脚本开发、工程化工具开发等能力。和浏览器JS的核心区别主要有三点:运行环境不同:浏览器端有DOM、BOMAPI,用来操作页面、窗口;Node.js没有DOM/BOM,内置文件、网络、进程、路径等服务端API。全局对象不同:浏览器全局是window;Node.js全局是global,现在更推荐用globalThis统一兼容。应用场景不同:浏览器JS专注页面交互、视图渲染;Node.js专注服务端接口、文件处理、爬虫、构建工具、中间层服务等。2.Node.js的单线程你是怎么理解的?是真的只有一个线程吗?答案:Node.js主线程是单线程,也就是事件循环、JS代码执行、回调执行都在同一个主线程完成,这也是它高并发、低开销的核心原因。但整体运行时并不是单线程:V8引擎自身有后台线程,负责垃圾回收、编译优化;Node.js内置libuv线程池,默认4个线程,专门处理文件IO、DNS、加密等耗时操作;网络IO是操作系统层面的异步事件,不占用线程池。总结:JS业务执行单线程,底层IO多线程并行,适合IO密集型场景,不适合CPU密集型场景。3.为什么Node.js适合IO密集,不适合CPU密集?答案:Node.js依靠事件循环+异步非阻塞IO实现高并发:遇到IO操作会立刻交出主线程,去处理其他请求,等IO完成后再执行回调,极大提升了并发处理能力,完美适配接口请求、文件读写、数据库查询等IO密集场景。而CPU密集场景(大量计算、循环、数据处理)会持续占用主线程,导致事件循环阻塞,所有后续请求、回调、定时器都无法执行,服务直接卡顿,吞吐量急剧下降。CPU密集解决方案:开启多进程、worker_threads子线程、拆分计算任务、交给Go/Java服务处理。二、模块化与CommonJS1.CommonJS和ESModule的区别?答案:CommonJS是Node.js传统模块化规范,ESModule是官方标准模块化规范,二者核心差异如下:加载方式:CommonJS是运行时同步加载;ESModule是编译时静态加载。导出导入:CommonJS用module.exports/require;ESModule用import/export。值的特性:CommonJS导出的是值的拷贝,原模块值修改后,导入方不会更新;ESModule导出的是值的引用,原模块值变化,导入方同步更新。循环依赖:CommonJS循环依赖会加载已执行的部分,不会报错;ESModule循环依赖处理更严谨,但书写不当易报错。文件后缀:CommonJS可省略后缀、默认找index文件;ESModule必须写完整后缀。2.CommonJS的模块加载机制、缓存机制是什么?答案:模块加载机制:首次require一个模块时,会依次判断路径:内置模块>node_modules模块>相对/绝对路径文件,读取文件后编译执行,导出module.exports。缓存机制:Node.js模块加载后会永久缓存,缓存键是模块的绝对路径。后续再次require同一个模块,不会重新执行代码,直接读取缓存结果,大幅提升加载性能。如果需要手动刷新缓存,可以删除require.cache[模块绝对路径]。3.module.exports和exports的区别?答案:模块初始化时,exports=module.exports,二者指向同一个内存地址。exports是简写变量,只能用来追加属性,比如exports.xxx=xxx;不能直接赋值exports={},会切断和module.exports的指向,导致导出失效;module.exports是真正的导出对象,可以直接赋值覆盖,是最终向外导出的内容。业务开发中,统一使用module.exports更稳妥,避免出错。三、事件循环(核心高频)1.详细说一下Node.js事件循环的执行流程答案:Node.js事件循环分为6个阶段,会按顺序循环执行,每个阶段执行完当前队列所有任务后,再进入下一个阶段:执行顺序:timers>pendingcallbacks>idle,prepare>poll>check>closecallbackstimers阶段:执行setTimeout、setInterval到期的回调pendingcallbacks:执行延迟的I/O回调idle、prepare:系统内部调用,开发基本不用关注poll阶段(核心):执行绝大多数I/O回调、等待新事件,是最繁忙的阶段check阶段:专门执行setImmediate回调closecallbacks:执行关闭类回调,如socket.close另外,事件循环执行每个阶段前,都会优先清空微任务队列。2.Node.js微任务、宏任务的执行优先级?和浏览器有什么区别?答案:Node.js任务优先级:process.nextTick>微任务(Promise/async/await)>宏任务宏任务优先级:timers>poll>check...和浏览器的核心区别:浏览器:执行一个宏任务,清空一轮微任务,再执行下一个宏任务;Node.js:执行完一个完整阶段的所有宏任务,再统一清空所有微任务,且nextTick优先级高于普通微任务。3.setTimeout和setImmediate谁先执行?答案:分两种场景:全局直接执行:顺序不确定。因为setTimeout默认最小延迟1ms,Node启动有初始化耗时,初始化快则setTimeout先执行,初始化慢则setImmediate先执行。在I/O回调内部执行:setImmediate一定先执行。I/O回调执行在poll阶段,下一阶段就是check阶段(setImmediate),而timers阶段需要下一轮循环。四、异步编程与Promise、Async/Await1.Node.js异步编程的发展历程答案:整体迭代顺序:回调函数>Promise>Generator>async/await回调函数:最原始,简单场景可用,多层嵌套会产生回调地狱,代码难以维护、无法统一异常处理;Promise:解决回调嵌套问题,支持链式调用,统一异常捕获,但是代码依然有链式冗余;Generator:依靠迭代器实现同步写法的异步,需要手动封装执行器,成本高,业务很少直接用;async/await:基于Promise的语法糖,完全同步写法,代码最简洁、可读性最高,是目前Node异步开发主流方案。2.说说Promise的三种状态及特点答案:Promise有三种状态:pending(等待)、fulfilled(成功)、rejected(失败)。状态一旦改变不可逆,只能从pending变为成功或失败,无法二次修改;状态改变后会缓存结果,后续所有.then/.catch都能拿到最终结果;支持链式调用,每次调用返回新Promise,解决回调嵌套问题。3.async/await的错误处理方式答案:主流两种方式,适配不同场景:try/catch:最常用,适合单个或少量异步任务,精准捕获异常;await后加.catch():适合简洁写法、独立异步请求,无需包裹try/catch。注意:await只会捕获Promisereject的错误,同步代码报错依然需要try/catch捕获。五、核心内置模块1.简述fs模块同步、异步、Promise三种用法,以及适用场景答案:同步fs.readFileSync:阻塞主线程,适合启动初始化、配置读取(仅执行一次),不适合接口运行时使用;异步回调fs.readFile:非阻塞,老旧写法,容易嵌套,现在基本不用;fs/promises异步Promise写法:配合async/await,代码简洁无阻塞,是业务开发首选。2.path模块常用API及区别答案:path.resolve():从当前目录拼接绝对路径,常用拼接项目路径、文件路径;path.join():单纯拼接路径,不区分绝对相对,不会自动补全绝对路径;path.dirname/path.basename/path.extname:分别获取目录、文件名、文件后缀。业务中路径拼接统一用path.resolve,兼容性更好,避免路径层级出错。3.stream流的理解,常用四种流答案:stream是Node处理大文件、大数据的核心机制,核心是分段读写、边读边写,不用一次性将全部数据载入内存,避免内存溢出,适合大文件上传、下载、压缩、解析等场景。四种基础流:Readable:可读流,读取数据(文件读取、接口响应)Writable:可写流,写入数据(文件写入、接口返回)Duplex:双向流,既可读又可写(TCP连接)Transform:转换流,读写过程中可以修改数据(压缩、加密、转码)常用管道方法:pipe(),自动处理数据流、背压机制。六、网络与HTTP服务1.手写一个简单Node原生HTTP服务答案:javascript

consthttp=require('http')

constserver=http.createServer((req,res)=>{

res.writeHead(200,{

'Content-Type':'application/json;charset=utf-8'

})

res.end(JSON.stringify({code:200,msg:'success'}))

})

server.listen(3000,()=>{

console.log('服务启动在3000端口')

})2.HTTP长连接和短连接的区别?Node如何实现长连接?答案:短连接:一次请求响应后立刻断开TCP连接,每次请求都要重新握手,开销大,适合普通接口请求;长连接:TCP连接建立后持续复用,多次请求共用一个连接,减少握手开销,提升性能。Node长连接实现:HTTP1.1默认开启Connection:keep-alive,底层自动复用连接;实时通信场景可使用WebSocket实现双向长连接。七、进程与线程、性能优化1.进程和线程的区别?答案:进程:操作系统资源分配的最小单位,相互独立,内存不共享,创建销毁开销大;线程:CPU调度的最小单位,隶属于进程,同进程内线程共享内存,创建销毁开销小。Node单进程单线程为主,可通过child_process、cluster、worker_threads实现多进程、多线程。2.cluster多进程原理,为什么能提升并发?答案:cluster可以根据CPU核心数,开启多个子进程,每个子进程都是独立的Node实例,都能独立处理请求,充分利用多核CPU资源,解决单线程无法利用多核、CPU利用率低的问题。核心原理:主进程监听端口,统一分发请求给各个子进程,子进程并行处理任务,大幅提升服务并发能力。3.Node服务常见性能优化方案答案:利用多核:使用cluster开启多进程,榨干CPU性能;避免阻塞事件循环:剥离复杂计算、同步代码、大循环,防止主线程阻塞;合理使用缓存:模块缓存、接口缓存、静态资源缓存,减少重复计算和IO;流处理大数据:大文件、大接口数据用stream分段处理,避免内存溢出;异常捕获兜底:全局捕获异常、防止进程崩溃,增加服务稳定性;日志与监控:监控内存、CPU、事件循环延迟,及时发现性能瓶颈。八、工程化与常见问题1.npm、yarn、pnpm的区别,为什么现在推荐pnpm?答案:npm:官方默认包管理,早期嵌套依赖,冗余多、安装慢、占用空间大;yarn:解决npm早期缺陷,速度更快、锁文件更稳定,但依然存在依赖冗余问题;pnpm:采用硬链接+软链接机制,全局存储依赖,多个项目共用同一个依赖包,极大节省磁盘空间,安装速度最快,依赖结构更严谨,杜绝幽灵依赖,是目前主流首选。2.什么是幽灵依赖?pnp

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论