20240309-2-校招前端面试常见问题-NodeJS

校招前端面试常见问题【6】——NodeJS

在这里插入图片描述

NodeJS

Q:NodeJS 的 IO 模型特点是什么?与多线程同步 IO 有什么不同?

NodeJS 的 IO 模型(更准确的说是 js 的执行环境,也就是 v8)的特点是“单线程异步非阻塞”。

而与多线程同步 IO,两者各有优劣,应该根据实际应用场景来做取舍。

在传统的观点里,异步 IO 的好处是 IO 本身并不需要占用太多的资源,缺点在于非线性代码带来的复杂度和难以理解维护,而多线程同步 IO 的缺点在于性能资源的开销和线程管理的问题。

所以很显然,在相同的机器资源里面,异步 IO 的并发量肯定是要高于多线程同步 IO 的;但是服务器程序本身肯定不只是由 IO 组成,还有逻辑运算的部分,过重的逻辑运算依旧会影响性能。换句话说,密集型 CPU 任务会阻塞 js 的执行,导致异步 IO 得不到处理,极大地影响到 node 处理响应的时间。

总之,node 的 IO 模型更适合处理 IO 密集型的任务。多线程同步 IO 更适合处理计算密集型的任务。

Q:V8 引擎垃圾回收机制是什么样的?

1、如何判断是否可以回收
(1)标记清除
当变量进入环境(例如,在函数中声明一个变量)时,就将这个变量标记为“进入环境”。从逻辑上讲,永远不能释放进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就可能会用到它们。而当变量离开环境时,则将其标记为“离开环境”。

具体做法:
垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记(当然,可以使用任何标记方式)。
然后,它会去掉运行环境中的变量以及被环境中变量所引用的变量的标记
此后,依然有标记的变量就被视为准备删除的变量,原因是在运行环境中已经无法访问到这些变量了。
最后,垃圾收集器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。

(2)引用计数
引用计数的含义是跟踪记录每个值被引用的次数。
当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是 1。
如果同一个值又被赋给另一个变量,则该值的引用次数加 1。
相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数减 1。
当这个值的引用次数变成 0 时,就可以将其占用的内存空间回收回来,这样,当垃圾收集器下次再运行时,它就会释放那 些引用次数为零的值所占用的内存。
但这样会有循环引用的问题。

2、V8 垃圾回收策略
将内存分为两个生代:新生代(new generation)和老生代(old generation)。
新生代中的对象为存活时间较短的对象,老生代中的对象为存活时间较长或常驻内存的对象,分别对新老生代采用不同的垃圾回收算法来提高效率,对象最开始都会先被分配到新生代(如果新生代内存空间不够,直接分配到老生代),新生代中的对象会在满足某些条件后,晋升到老生代。

新生代主要使用 Scavenge 进行管理,将内存平均分为两块,使用空间叫 From,闲置空间叫 To,新对象都先分配到 From 空间中,在空间快要占满时将存活对象复制到 To 空间中,然后清空 From 的内存空间,此时,调换 From 空间和 To 空间,继续进行内存分配,当满足晋升条件时对象会从新生代晋升到老生代。

对象晋升的条件主要有两个:
如果一个对象是第二次经历从 From 空间复制到 To 空间,那么这个对象会被移动到老生代中。
当要从 From 空间复制一个对象到 To 空间时,如果 To 空间已经使用了超过 25%,则这个对象直接晋升到老生代中。(设置 25%这个阈值的原因是当这次 Scavenge 回收完成后,这个 To 空间会变为 From 空间,接下来的内存分配将在这个空间中进行。如果占比过高,会影响后续的内存分配)

老生代主要采用 Mark-Sweep 和 Mark-Compact 算法,一个是标记清除,一个是标记整理。两者不同的地方是,Mark-Sweep 在垃圾回收后会产生碎片内存,而 Mark-Compact 在清除前会进行一步整理,将存活对象向一侧移动,随后清空边界的另一侧内存,这样空闲的内存都是连续的,但是带来的问题就是速度会慢一些。在 V8 中,老生代是 Mark-Sweep 和 Mark-Compact 两者共同进行管理的。

Q:实现一个 EventEmitter?

实现:

class EventEmitter {constructor() {this._events = {}}subscribe(type, handler) {if (this._events.hasOwnProperty(type)) {this._events[type].push(handler)} else {this._events[type] = [handler]}}unsubscribe(type, handler) {if (this._events.hasOwnProperty(type)) {const index = this._events[type].indexOf(handler)if (index > -1) {this._events[type].splice(index, 1)}}}once(type, handler) {let fired = falselet _this = thisfunction magic() {_this.unsubscribe(type, magic)if (!fired) {fired = truehandler.apply(_this, arguments)}}this.subscribe(type, magic)}emit(type, args) {if (this._events.hasOwnProperty(type)) {this._events[type].forEach((fn) => fn(args))}}
}module.exports = EventEmitter

使用:

const EventEmitter = require('./myEventEmitter')const eventEmitter = new EventEmitter()const fn = (args) => {console.log('good args', args)
}
const fn2 = (args) => {console.log('good args 2', args)
}
const fn3 = (args) => {console.log('good args 3', args)
}eventEmitter.subscribe('good', fn)
eventEmitter.subscribe('good2', fn2)eventEmitter.emit('good', 11111)
eventEmitter.emit('good2', 22222)eventEmitter.unsubscribe('good', fn)eventEmitter.emit('good2', 22222)eventEmitter.once('good3', fn3)
eventEmitter.emit('good3', 33333)eventEmitter.emit('good3', 33333)
Q:es6 模块化、commonjs 模块化的区别?

es6 模块化:

在es6规范中,使用import和export可以使js文件模块化。
每个import的js文件都是单例,如果再次import,就直接在内存中进行读取。导出方式1:
//lib.js 文件
let foo = "stringFoo";
let fn0 = function() {console.log("fn0");
};
export{foo, fn}//main.js文件
import {foo, fn} from "./lib";
console.log(bar+"_"+foo);

commonjs 模块化:

Node 应用由模块组成,采用 CommonJS 模块规范。每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。如果要定义全局变量,需要global属性。CommonJS规范规定,每个模块内部,module变量代表当前模块。
这个变量是一个对象,它的exports属性(即module.exports)是对外的接口。加载某个模块,其实是加载该模块的module.exports属性。
为了方便,Node为每个模块提供一个exports变量,指向module.exports。例如:
var test = function () {console.log(123);
};
module.exports.test = test;使用require('XXX')加载模块。
require命令的基本功能是,读入并执行一个JavaScript文件,然后返回该模块的exports对象。如果没有发现指定模块,会报错。

NodeJS 相关框架

Q:请简述一下 Koa 的洋葱模型?

koa 洋葱模型是指 koa 中每个中间件的执行顺序。
koa 在执行多个中间件中的逻辑时,会先执行第一个中间件的逻辑,执行到 next()函数后会执行第二个中间件的逻辑,以此类推,直到最后一个中间件。当最后一个中间件执行完毕后,会跳回执行倒数第二个中间件 next()函数后面的代码,以此类推,直到第一个中间件 next()函数后面的代码执行完毕。

举例来说:

const Koa = require('koa')const app = new Koa()
const PORT = 3000// #1
app.use(async (ctx, next) => {console.log(1)await next()console.log(1)
})
// #2
app.use(async (ctx, next) => {console.log(2)await next()console.log(2)
})app.use(async (ctx, next) => {console.log(3)
})app.listen(PORT)
console.log(`http://localhost:${PORT}`)

访问 http://localhost:3000,控制台打印:

1
2
3
2
1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/732056.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux学习-共用体和枚举,位运算

目录 共用体 ​编辑枚举 位运算 共用体 定义和访问都和结构体类似;区别在于共用体所有的成员变量共享同一片空间,内存空间就是其最大数据类型所占内存的大小; 如果给成员变量2的值,那么成员变量1的值就会被覆盖;主…

实现鼠标移动el-select下拉框的label上面显示出table悬浮窗

首先是对vue代码 实现思路就是在el-option里面放一个span来包裹el-popover&#xff0c;里面在放tabe实现悬浮表格 <el-form-item label"原理图编号"><el-select v-model"data.number" placeholder"请选择" clearable multiple collaps…

外包干了30天,我后悔了。。。

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 这次来聊一个大家可能也比较关心的问题&#xff0c;那就是就业城…

枚举赋值及强制转换问题

对枚举进行字符赋值&#xff0c;需要进行强制类型转换之后&#xff0c;才能得到想要的值&#xff0c;如下 typedef enum data {DIRECTION_X X,DIRECTION_Y Y,DIRECTION_Z Z,DIRECTION_T T }NumData;int main() {NumData numdata DIRECTION_Y;count <<"num is&…

第九篇 – 过程发现(Process Discovery)是如何赋能数字化市场营销全过程?- 我为什么要翻译介绍美国人工智能科技巨头IAB公司

IAB平台&#xff0c;使命和功能 IAB成立于1996年&#xff0c;总部位于纽约市。 作为美国的人工智能科技巨头社会媒体和营销专业平台公司&#xff0c;互动广告局&#xff08;IAB- the Interactive Advertising Bureau&#xff09;自1996年成立以来&#xff0c;先后为700多家媒体…

电路板故障的四大原因--芯片级维修

电路板是我们日常使用的技术的核心。 手机、电视、车辆、路灯和大量其他物品都依赖于电路板&#xff0c;这就是为什么故障可能具有高度破坏性。 电路板出现故障的原因有多种&#xff0c;与潮湿、高温和污垢等常见因素有关。 了解电路板故障的原因可以让您避免未来的故障&#x…

波奇学Linux: 信号捕捉

sigaction:修改信号对应的handler方法 act输入型参数&#xff0c;oldact输出型参数 void (*sa_handler) (int) //修改的自定义函数 sigset_t sa_mask // void handler(int signo) {cout<<"catch a signal, signal number: "<<signo<<endl; } int …

WindTerm的安装及远程连接Linux系统步骤

文章目录 WindTerm下载WindTerm远程连接Linux WindTerm下载 官网下载链接 WindTerm网盘下载链接 WindTerm不需要安装&#xff0c;将下载的压缩包解压后直接找到WindTerm.exe执行文件&#xff0c;双击即可运行 WindTerm远程连接Linux 1.先获取你的Linux的IP地址&#xff0c;…

【高效开发工具系列】Windows 系统下将 Windows 键盘的 ctrl 和 alt 互换

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Mysql深入学习 基础篇 Ss.06 事务

青青子衿&#xff0c;悠悠我心 纵我不往&#xff0c;子宁不嗣音 —— 24.3.9 事务&#xff1a; 事务简介 事务操作 事务四大特性 并发事务问题 事务隔离级别 一、事务简介 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整…

【蓝桥杯-单片机】LED和按键小练习:Led彩灯控制系统

文章目录 【蓝桥杯-单片机】LED和按键小练习&#xff1a;Led彩灯控制系统01 题目描述02 题目解答03 本题总结整体逻辑框架&#xff08;详细版&#xff09;整体逻辑框架&#xff08;缩略版&#xff09;按键读取模块按键消抖模块流水灯显示模式&#xff08;1&#xff09;从上向下…

基于SVM模型的网络入侵检测模型训练与评估(NSL-KDD数据集)

简介 针对网络安全领域的NSL-KDD数据集进行分类任务的预处理和模型训练、以及超参数调优。 数据预处理 读取并解析数据集&#xff1b;检查并删除指定列&#xff08;outcome&#xff09;的缺失值&#xff1b;对类别型特征&#xff08;protocol_type, service, flag&#xff0…

GPT-4 等大语言模型(LLM)如何彻底改变客户服务

GPT-4革命&#xff1a;如何用AI技术重新定义SEO策略 在当今快节奏的数字时代&#xff0c;客户服务不再局限于传统的电话线或电子邮件支持。 得益于人工智能 (AI) 和自然语言模型 (NLM)&#xff08;例如 GPT-4&#xff09;的进步&#xff0c;客户服务正在经历革命性的转变。 在这…

【Python】成功解决NameError: name ‘a‘ is not defined

【Python】成功解决NameError: name ‘a’ is not defined &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; 希望得到您的订…

gensim 实现 TF-IDF;textRank 关键词提取

目录 TF-IDF 提取关键词 介绍 代码 textRAnk 提取关键词 这里只写了两种简单的提取方法&#xff0c;不需要理解上下文&#xff0c;如果需要基于一些语义提取关键词用 LDA&#xff1a;TF-IDF&#xff0c;textRank&#xff0c;LSI_LDA 关键词提取-CSDN博客 TF-IDF 提取关键词…

MySQL中批量修改某个字段的一部分字符,可以使用UPDATE语句结合REPLACE函数

示例语句 UPDATE your_table_name SET your_column_name REPLACE(your_column_name, old_string, new_string) WHERE your_column_name LIKE %old_string%; 原因&#xff1a; 项目用了一个服务上传地址原来是http开头&#xff0c;数据库存的地址也是http&#xff0c;后来加了…

基于java EE医疗机械设备采购管理系统设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 系统开发相关技术 3 1.1 J2EE技术简介 3 1.2 SSH框架技术 3 1.3 JQuery技术 3 1.4 CSS技术 3 1.5 XML技术 3 1.6 Ajax技术 4 1.7 MySQL数据库 4 1.8 本章小结 4 2 系统分析 5 2.1 概要分析 5 2.2 功能需求分析 6 2.3 功能初步设计 6 2.4 …

COMSOL热应力仿真

热应力 热膨胀子节点 热膨胀输入类型 假如直接知道热膨胀大小&#xff0c;可以直接对热应变进行赋值。 约束与载荷 对于自由膨胀&#xff0c;可以添加抑制刚体运动。 案例分析 在参数部分&#xff0c;设定体积参考温度Tref&#xff0c;假定在25[degC]模型无热应变。 APP开发器-…

vue 使用 PrintJs 实现打印pdf效果

一、print.js介绍 Print.js主要是为了帮助我们直接在应用程序中打印PDF文件&#xff0c;而无需离开界面&#xff0c;并且不使用嵌入。对于用户不需要打开或下载PDF文件的特殊情况&#xff0c;他们只需要打印它们。 例如&#xff0c;当用户请求打印在服务器端生成的报告时&…

IRLINK(红外遥控器)

工具 1.Proteus 8 仿真器 2.keil 5 编辑器 原理图 讲解 简介 红外遥控&#xff1a;是利用红外线进行通信的设备&#xff0c;由红外LED调制后的信号发出&#xff0c;由专用的红外接头进行解调&#xff1b; 通信方式&#xff1a;单工、异步&#xff1b; 红外LED波长&#x…