- Node
- 1.node引入模块的过程是什么?(来自深入浅出nodejs)
- 2.nodejs有哪些全局对象?
- 3.process常用方法?
- 4.nodejs的事件循环?
- 5.有使用过buffer吗?
- 6.nodejs同步和异步怎么理解?
- 7.如何防止程序奔溃?
- 8.怎么调试nodejs?
- 9.node网络模块有哪些?
- 10.npm作用?
- 11.nodejs导入模块和导入js文件有什么区别?
- 12.有使用过stream流吗?
- 13.fs模块常用?
- 14.nodejs优缺点?
- 15.nodejs模块加载和使用规则是什么?=》cjs
- 16.常见npm命令?
- 17.什么是前后端分离?
- 18.v8垃圾回收机制(v8限制64位机器内存最大约1.4G,32机器0.7G。node v14版本的内存为2G,V8自身是用C++)=》完整
- 内存分配机制?
- 19.express和koa区别?
- 20.有哪些常用模块?
- 21.node是单线程单进程如何高效利用多核CPU?
- 22.什么是IPC?
- 23.//TODO
- 24.//TODO
- 25.// TODO
- 26.nodejs和js区别是什么?
- 27.npm i与npm ci的区别是什么?
- 28.node中循环引用会发生什么?
- 29.v8如何执行js代码?
- 30.node中如何读取可读流的内容?
- 31.如何读取大文件内容?
- 32.如何查看文件状态/文件最后修改时间?
- 33.说说对BFF?
- 34.koa-router实现原理?
- 35.node如何调用c++?
- 36.什么是中间件-举例?
- 37.fs-extra有使用过吗?
- 38.如何监控文件的变动?
- 39.node --max-old-space-size=4096什么意思?
# Node
# 1.node引入模块的过程是什么?(来自深入浅出nodejs)
路径分析(分析是node的核心模块,如http,还是文件路径或者是第三方依赖) ->文件定位(后缀优先级js>json>node) ->编译执行
- node会对引入过的模块进行缓存,缓存的是编译执行后的对象。从缓存加载不需要这三步。
- node模块分为两类:node提供的核心模块,用户编写的文件模块。
- 核心模块加载速度比文件模块快(因为有部分模块在node进程启动时就被直接加载进内存,这部分文件不需要再进行文件定位和编译执行)。
# 2.nodejs有哪些全局对象?
global,process,console,module,export
# 3.process常用方法?
process.env process.argv process.exit
# 4.nodejs的事件循环?
(执行中是IO事件,setImmediate在当前队列中立即执行,setTimeout/setInterval把执行定时到下一个队列 process.nextTick在当前队列执行完,下次遍历前执行)
- 顺序:IO事件->setImmediate->setTimeout/setInterval->process.nextTick
- 总共是6个阶段,
- 从poll开始,这个阶段会检查是否有io事件,执行io相关回调
- 到check阶段,这个阶段会执行setImmediate的回调
- 到close callback 这个阶段执行关闭的回调函数
- 到timer 这个阶段会执行setTimeout和setInterval的回调
- 到pending callback这个阶段执行之前延迟的回调
- 到idle,prepare阶段,这个是node系统内部使用的
- 回到poll开始新的循环。 (微任务会在每个阶段执行完立即执行,nextTick队列,会优先于其他微任务执行)
# 5.有使用过buffer吗?
buffer主要处理二进制数据,在文件上传有用到。=》支持for...of buffer实例类似整型数组,但buffer的大小是固定的无法改变(V8堆外分配内存),全局变量不需要require
# 常用api
- Buffer.concat(list,[length])返回一个合并了list中所有buffer的新buffer
- Buffer.from(array)使用数组创建buffer
- Buffer.alloc(size)创建一个buffer空间
- Buffer.isBuffer(obj)判断是否是buffer
# 说说typedArray和unit8Array
引入typedArray之前,js没有读取获操作二进制数据的机制,typeArray用来实现Uint8Array=》8位无符号整型数组,typedArray是统称
# 6.nodejs同步和异步怎么理解?
- 同步会阻塞IO,所以一般只在项目启动时使用,用来加载配置文件,初始化各种中间件。
- 异步是通过一次次循环事件队列来实现
# 7.如何防止程序奔溃?
通过try catch捕获异常(可以设置一个全局异常处理器,捕获程序抛出的异常,捕获到把异常打印到控制台)
# 8.怎么调试nodejs?
node-- debug 文件名
# 9.node网络模块有哪些?
常用HTTP、NET
# 10.npm作用?
是包管理器,可以管理项目的依赖及依赖版本号
# 11.nodejs导入模块和导入js文件有什么区别?
导入模块按名称导入,导入文件按路径导入
# 12.有使用过stream流吗?
主要用在读写文件。=》流可读,可写,或者可读可写 =》fs.createReadStream('a.txt') fs.createWriteStream('a.txt')
# buffer和stream之间如何转换?
=》stream to buffer 通过stream.on(data, data=>buffer.push(data))把每个buffer插入buffers数组,然后再通过buffer.concat把这些buffer组合到一起 =》buffer to stream 可以通过duplex(可读可写流)把缓存push到stream中 let stream = new Duplex() stream.push(buffer)
# buffer和stream区别?
buffer是取完数据一次性操作,stream是边取边操作
# 13.fs模块常用?
- 文件流 fs.createReadStream('a.txt') fs.createWriteStream('a.txt')
- 同步文件读写 fs.readFileSync() fs.writeFileSync()
- 异步文件读写 fs.readFile() fs.writeFile()
# 14.nodejs优缺点?
- 非阻塞IO,适合IO密集型的场景(CPU密集型给node主要挑战是:如果有长时间的计算将导致CPU时间片不能释放,使后续IO无法发起。IO阻塞的性能浪费远比CPU小)
- 单进程,单线程。不用担心锁和线程同步的问题(js部分是单线程,但是底层IO操作用到了libuv,这块不是单线程) (缺点:一旦一个地方崩溃,整个系统都崩溃) *node跨平台是通过libuv库,事件循环也是这个库实现的
# 15.nodejs模块加载和使用规则是什么?=》cjs
- 遵循commonjs规范,使用require加载文件 使用exports/module.export导出文件 =》cjs不能直接在浏览器使用 (amd代表库是require.js,早期commonjs代表库是sea.js,由淘宝玉伯开发) (现在统一为nodejs遵循commonjs规范,浏览器遵循esm规范(es6才有的,早期用amd))
# exports和module.export区别
本质无区别,最终暴露的都是module.export。但不能直接对exports赋值,没有任何效果
# 16.常见npm命令?
npm install | npm uninstall | npm init | npm config set
# 17.什么是前后端分离?
前端通过ajax调用后端提供的接口进行数据交互
# 18.v8垃圾回收机制(v8限制64位机器内存最大约1.4G,32机器0.7G。node v14版本的内存为2G,V8自身是用C++)=》完整
(64位新生代空间64M,老生代1400MB 32位新生代空间32M,老生代700M) V8采用分代式垃圾回收=》对象生命周期长短不一,不同回收机制能有更好的效果
- 分代式垃圾回收机制,将内存区分成老年代和新生代。(新生代内存占用小可以用复制的方式,老生代内存占用大不能用)
- 新生代中存放的是生存时间短的对象,老生代中存放的是生存时间长的对象。
- 新生代回收使用scavenge算法(牺牲空间换时间,具体实现采用了cheney算法):通过将存活对象在两个semiSpace空间中复制来实现垃圾回收。
- cheney算法:它将堆内存一分为二,每个部分称为semiSpace,只有一个在使用中,使用中的是from,空闲的是to空间。 分配对象会在from空间进行分配,回收会检查from存活的对象,非存活对象会被释放,存活对象会复制到to空间,然后清空from空间,最后from,to交换 =》拷贝和交换from,to空间主要是为了让内存空间保持连续
- scavenge算法缺点是只能使用堆内存的一半,由划分空间和复制机制决定的。但因为它只复制存活的对象,而对于生命周期短的场景来说存活对象只占少部分,所以由时间效率上的优势。 (scavenge算法有很大的空间开销。所以老生代不适合,会浪费大量内存)
# 一开始都在新生代中,达到对象晋升条件后晋升为老生代
- 对象经历过一次Scavenge回收
- To空间已经使用超过25%(To空间对象会很快移动到老年代,防止新生代的空间被耗尽)
# 为什么是25%?
当这次scavenge回收完成后,会发生角色交换,如果占比过高,会影响后续的内存分配
# 老年代使用什么算法?
老年代回收使用标记清除+标记整理算法 第一次扫描标记存活的对象,第二次扫描清除未被标记的对象 将存活对象往内存的一端移动(整理操作,保证存活对象内存空间连续),清除掉存活对象外的内存
# 老生代为什么还要用标记整理?
因为进行一次清除后,内存空间会出现不连续的情况(会对后续内存分配造成影响)。所以需要整理碎片空间(使内存空间变得连续)
# 全停顿问题(全停顿影响性能)
垃圾回收时需要将应用逻辑先暂停下来,等执行完垃圾回收再继续执行应用逻辑,这就是全停顿,对新生代影响较小,但对老生代影响大。 老生代引入增量标记,将标记阶段分成若干个步骤,每运行一段时间就让程序执行一会,再进行标记(主线程停顿进行垃圾回收然后继续执行主线程然后再垃圾回收)
# 三色标记法(黑白灰):
黑色表示被GC ROOT引用,而且子节点已经标记完成 灰色表示被GC ROOT引用,但是子节点还没被处理 白色表示这个节点没有被访问到,如果本轮垃圾回收结束,节点还是白色,说明是垃圾数据,对应内存会被回收 增量回收是并发进行的,增量回收条件: 不能让黑色节点指向白色节点。 通常使用写屏障(Write-barrier)机制来实现这个约束条件: 当发生了黑色节点引用了白色节点的情况,写屏障会强制将被引用的白色节点变成灰色,这种方法也被称为强三色不变性
# 对象如何释放?
可达性算法。将GC ROOT对象作为起始点,向下搜索,搜索经过的路径称为引用链。当对象到起始点没有任何引用链就是不可用。 即使不可达的对象,也不是立即释放,会先进行标记,然后进行筛选,会被放进一个队列中依次进行回收 如果又有对象引用,就不会被回收。如果一个新生代对象经过多次复制后还存活,会晋升到老年代 对象From空间复制到To空间,如果To空间超过25%,也会直接晋升到老年代 (新生代用全停顿问题不大,因为新生代垃圾回收速度快)
# 内存分配机制?
- 分配你需要的内存
- 使用分配到的内存读/写
- 不需要的时候释放
- (C语言可以通过代码手动分配和手动释放,即手动垃圾回收。这两个java和js都默认处理,即自动垃圾回收)
# 19.express和koa区别?
- express内置了许多中间件。koa没有
- express包含路由,视图渲染等特性,koa只有http模块
- express主要通过回调实现异步函数,koa主要通过async,await的方式来处理异步
# 20.有哪些常用模块?
http、fs、path、os、url(用于解析url)
# 21.node是单线程单进程如何高效利用多核CPU?
node提供了child_process,通过启动多进程的方式来高效利用
# 22.什么是IPC?
IPC指InterProcess Communication,即进程间通信
# 23.//TODO
# 24.//TODO
# 25.// TODO
# 26.nodejs和js区别是什么?
- nodejs是运行环境,js是语言(执行js可以在浏览器也可以在nodejs上。因为都内置了js引擎)
- js在浏览器有dom,bom等浏览器相关对象,nodejs有文件系统,网络系统等
# 27.npm i与npm ci的区别是什么?
- npm ci会删除node_modules文件夹
- npm ci要求项目中必须有package-lock.json否则不起作用,npm i不要求
# 28.node中循环引用会发生什么?
在cjs中,遇到require时,会执行require模块中的代码,并缓存执行结果。下次再加载就会直接去取缓存结果,所以不会出现无限循环引用的情况
# 29.v8如何执行js代码?
parser生成抽象语法树=>Ignition生成字节码(字节码不能直接在处理器上运行,需要解释器转成机器码)=>编译器TuiboFan来编译成机器码
# 怎么知道v8版本号?
console.log(process.versions)
# 30.node中如何读取可读流的内容?
// 通过stream流
let data = "";
stream.on("data", (chunk) => (data += chunk));
stream.on("end", () => console.log(data));
2
3
4
# 31.如何读取大文件内容?
import { createReadStream } from "fs";
const stream = createReadStream("bigfile.json");
2
# 32.如何查看文件状态/文件最后修改时间?
node stats
# 33.说说对BFF?
- BFF层可以对前端的数据进行处理再给后端
- 优点:后端改动,只需改动BFF层,无需去改前端代码
# 34.koa-router实现原理?
正则匹配=》采用的是path-to-regexp库
# 35.node如何调用c++?
通过napi
# 36.什么是中间件-举例?
比如路由中间件,全局异常捕获中间件,权限中间件
# 37.fs-extra有使用过吗?
是fs的扩展,继承了fs的所有方法,扩展了更多的功能,给fs的方法添加了promise的支持
# 38.如何监控文件的变动?
node有提供一个fs.watch
# 39.node --max-old-space-size=4096什么意思?
最大内存4G