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 = false
    let _this = this
    function magic() {
      _this.unsubscribe(type, magic)

      if (!fired) {
        fired = true
        handler.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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据资产运营:快消品牌的新竞争力

在数字化浪潮的推动下,快消品行业正经历一场由数据驱动的变革。从消费者购买行为到市场动态,数据正在成为快消品牌创新和维持竞争优势的关键资源。本文将探讨如何通过高效的数据资产运营提升快消品牌的市场敏锐度和业务成效。 一、数据资产在快消品牌中的…

学习JavaEE日子 Day24 TreeSet,内置比较器,外置比较器,HashMap

Day24 TreeSet 1.TreeSet 1.1 TreeSet的使用 注意&#xff1a;TreeSet的使用和HashSet一样 public class Test01 {public static void main(String[] args) {//创建TreeSet集合的对象TreeSet<String> set new TreeSet<>();//添加元素set.add("麻生希"…

优先权的不同特征性质

目录 1.强占式&#xff0c;静态优先权&#xff0c;动态优先权 2.先来服务算法&#xff0c;高响应比优先算法&#xff0c;时间片轮转算法&#xff0c;非抢占式短任务优先 1.强占式&#xff0c;静态优先权&#xff0c;动态优先权 2.先来服务算法&#xff0c;高响应比优先算法&am…

day11_SpringCloud(Nacos注册中心,LoadBalancer,OpenFeign)

文章目录 Spring Cloud Alibaba1 系统架构演进1.1 单体架构1.2 微服务架构1.3 分布式和集群 2 Spring Cloud Alibaba概述2.1 Spring Cloud简介2.2 Spring Cloud Alibaba简介 3 微服务环境准备3.1 工程结构说明3.2 父工程搭建3.3 用户微服务搭建3.3.1 基础环境搭建3.3.2 基础代码…

Luajit 2023移动版本编译 v2.1.ROLLING

文章顶部有编好的 2.1.ROLLING 2023/08/21版本源码 Android 64 和 iOS 64 luajit 目前最新的源码tag版本为 v2.1.ROLLING on Aug 21, 2023应该是修正了很多bug, 我是出现下面问题才编的. cocos2dx-lua 游戏 黑屏 并报错: [LUA ERROR] bad light userdata pointer 编…

德人合科技|天锐绿盾加密软件——数据防泄漏系统

德人合科技是一家专注于提供企业级信息安全解决方案的服务商&#xff0c;提供的天锐绿盾加密软件是一款专为企业设计的数据安全防护产品&#xff0c;主要用于解决企事业单位内部敏感数据的防泄密问题。 www.drhchina.com PC端&#xff1a; https://isite.baidu.com/site/wjz012…

同时上内网和外网(笔记本自带的无线网卡和另外购置无线网卡)

同时上内网和外网 两无线网卡连接内外网插入新网卡后&#xff0c;重命名网卡名字信息收集IPv4属性设置永久路由 两无线网卡连接内外网 插入新网卡后&#xff0c;重命名网卡名字 两网卡同时连接网络&#xff0c;使用ipconfig /all 获取信息&#xff0c;整理如下&#xff1a; 下…

[BUUCTF]-PWN:starctf_2019_babyshell解析(汇编\x00开头绕过+shellcode)

查看保护 查看ida 这里就是要输入shellcode&#xff0c;但是函数会有检测。 在shellcode前面构造一个以\x00机器码开头的汇编指令&#xff0c;这样就可以绕过函数检查了。 完整exp&#xff1a; from pwn import* context(log_leveldebug,archamd64) pprocess(./babyshell)she…

CorelDRAW Standard2024适合业余爱好者和家庭企业的图形设计软件

CorelDRAW Standard 2024是一款功能强大的矢量图形设计软件&#xff0c;专为图形爱好者、家庭用户、微型企业和学生们设计。该软件在Windows平台上运行&#xff0c;并提供了智能对象、布局、插图和模板等功能&#xff0c;帮助用户快速创建高质量的设计作品。 CorelDRAW Standa…

npm install没有创建node_modules文件夹

问题记录 live-server 使用时 报错&#xff1a;live-server : 无法将“live-server”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。 npm install 安装 但是 这时npm install没有创建node_modules文件夹&#xff0c;只生成package-lock.json文件 方法一&#xff1a; 手…

JetPack入门

先导入依赖 implementation("androidx.lifecycle:lifecycle-extensions:2.2.0") 1.使用LifeCycle解耦页面与组件 Activity package com.tiger.lifecycle;import android.annotation.SuppressLint; import android.os.Bundle; import android.os.SystemClock; impo…

Halcon局部可变形模板匹配

文章目录 算子Halcon 使用局部变形算法案例 算子 create_local_deformable_model 创建局部可变形模板 prepare_direct_variation_model(RefImage, VarImage : : ModelID, AbsThreshold, VarThreshold : ) 以下是参数的解释&#xff1a;RefImage (输入对象)&#xff1a;对象的参…

Web核心

JavaWeb技术栈 B/S架构&#xff1a;Browser/Server &#xff0c; 浏览器/服务器 架构模式&#xff0c;其特点为&#xff0c;客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务器端。浏览器只需要请求服务器&#xff0c;获取Web资源&#xff0c;服务器把Web资源…

python编程从入门到实践

python编程从入门到实践 if语句1.条件测试&#xff1a;2.更多的条件测试&#xff1a;3.外星人颜色#1&#xff1a;4. 外星人颜色#2&#xff1a;5. 外星人颜色#3&#xff1a;6. 人生的不同阶段&#xff1a;7. 喜欢的水果&#xff1a;8. 以特殊方式跟管理员打招呼&#xff1a;9. 处…

专业140+总430+电子科技大学858信号与系统考研经验成电电子信息与通信工程,电科大,真题,大纲,参考书。

今年考研成绩出来&#xff0c;初试专业课858信号与系统140&#xff0c;总分430&#xff0c;其余各门分数都比较平稳&#xff0c;总分好于自己估分&#xff0c;应群里很多同学要求&#xff0c;我总结一下自己的复习经验。首先我是一个大冤种&#xff0c;专业课资料学长给了一套&…

2023年12月CCF-GESP编程能力等级认证Python编程七级真题解析

本文收录于专栏《Python等级认证CCF-GESP真题解析》,专栏总目录・点这里 一、单选题(每题 2 分,共 30 分) 第1题 假设变量 x 为 float 类型,如果下面代码输入为 100,输出最接近( )。 A.0 B.-5 C.-8 D.8 答案:B 第2题 对于下面动态规划方法实现的函数,以下选项中…

2022年 NOC大赛 Python编程 创客智慧编程赛项【初赛】 竞赛真题

第1题:【 单选题】 运行以下代码,终端区会出现什么内容? A:9 B:0 C:25 D:终端区会报错 【正确答案】: C 【试题解析】 :count 函数中有一个参数 a,运行函数时,函数会遍历传入的列表,并且将其中的元素装进变量i中,累加进 result 变量里在最后一行代码中,将 num_li…

【vue.js】文档解读【day 3】 | 条件渲染

如果阅读有疑问的话&#xff0c;欢迎评论或私信&#xff01;&#xff01; 文章目录 条件渲染前言&#xff1a;v-ifv-elsev-else-iftemplate中的v-ifv-showv-if vs v-show 条件渲染 前言&#xff1a; 在JavaScript中&#xff0c;我们知道条件控制语句可以控制程序的走向&#…

女子焦虑躯体化3年,感觉生活非常痛苦!

焦虑的躯体化是一种心理问题显现为身体症状的情况&#xff0c;常见于长期面临心理压力和情绪困扰的人群。在日常生活中&#xff0c;女性更容易出现焦虑的躯体化现象&#xff0c;她们可能因为职场竞争、家庭压力、人际关系等原因产生焦虑情绪&#xff0c;这些焦虑情绪在身体上表…

TQTT X310 软件无线电设备的FLASH固件更新方法--WIN和UBUNTU环境

TQTT X310 除了PCIE口全部兼容USRP 官方的X310&#xff0c;并配备两块UBX160射频子板以及GPSDO。TQTT X310可以直接使用官方的固件&#xff0c;但是不支持官方的固件升级命令。这篇BLOG提供烧写刷新FLASH的方法。 这里分别给出WIN下和UBUNTU下升级的软件和方法 WIN环境下烧写…