前端面试拼图-原理源码

摘要:最近,看了下慕课2周刷完n道面试题,记录下...

1. JS内存泄漏如何检测?场景有哪些?

1.1 垃圾回收 GC

        垃圾回收是一种自动管理内存的机制,它负责在运行时跟踪内存的分配和使用情况,并在不再需要的对象上进行自动内存释放,常用的垃圾回收算法:

        标记清除 (Mark-and-Sweep):最常用的垃圾回收算法,垃圾回收器会从根对象(如全局对象、调用栈)出发,标记所有可以访问到的对象,扫描整个堆内存,清除那些未被标记的对象;

        引用计数 (Reference Counting):通过记录对象的引用次数来判断对象是否可达。当对象的引用次数为零时,该对象被视为垃圾并进行回收。引用计数算法的缺点是难以解决循环引用问题。

JS闭包属于内存泄漏吗?

        内存泄漏是指不再需要的对象(非预期的对象)仍然占用内存,导致系统资源浪费和性能下降。严格意义上说闭包并不算内存泄漏,使用闭包是预期相关对象会继续存在在内存中,闭包的数据不能被垃圾回收更合适,因为它依然保持对外部变量的引用。

1.2 JS内存泄漏如何检测

        主要有如下途径:

  • 利用浏览器开发者工具,如Chrome DevTools包含 Memory 面板,可以监控内存使用情况、快照内存状态、查看对象分配情况等;
  • 借助的第三方工具,如 Heap Profiler 工具可以捕获 JavaScript 堆栈中的快照,并分析对象的分配情况、引用关系等,从而发现潜在的内存泄漏问题;
  • 当然也可以在开发过程中手动检测,避免导内存泄漏的情况出现,例如监听时间处理函数未处理、循环引用的存在等。
1.3 至于内存泄漏的场景(Vue为例

        被全局变量、函数引用,组件销毁时未清除

        被全局事件、定时器引用,组件销毁时未清除

        被自定义事件引用,组件销毁时未清除

扩展:WeakMap WeakSet

        WeakMap和WeakSet是JavaScript的内置对象,它们提供了一种存储对象的弱引用的机制,被广泛用于解决内存泄漏和垃圾回收的问题。他们的特点类似:

WeakMap:

  • 一种键值对的集合,其中键必须是对象,值可以是任意类型。键是对象的弱引用,即当对象没有其他引用时,垃圾回收机制可以自动清理该键值对(Vue 3的响应系统中也是用了WeakMap这一特性避免内存泄漏);
  • 没有提供遍历方法,也不能获取其大小或键列表;
  • 由于键是弱引用,所以 WeakMap 是不可迭代的,也不支持常规的对象方法,如 size、forEach 等;
  • 主要用于存储额外的数据或元数据,这些数据与对象的生命周期相关,当对象被销毁时,与之关联的额外数据也会被自动清除。

WeakSet:

  • 一种存储对象的集合,其中的对象是弱引用,同样在没有其他引用时,垃圾回收机制可以自动清除对象。 只能存储对象,不能存储原始值;
  • 不可迭代,也没有提供查询大小、遍历等功能;
  • 主要用于存储一组对象,并且需要确保这些对象不会产生内存泄漏;
  • 与 Set 不同,WeakSet 中的对象是弱引用,因此它们不会阻止垃圾回收器销毁这些对象。

2. 浏览器和node.js的事件循环有什么区别?

2.1 浏览器事件循环

        JS是单线程的(无论浏览器还是nodejs),浏览前中JS执行和DOM渲染共用一个线程,这就需要使用异步编程模型,实现非阻塞的操作,提高程序的性能和响应速度。这就需要使用事件循环机制来处理异步操作,这些异步任务又被分为宏任务和微任务。

        宏任务是一个独立的、完整的任务单元,比如setTimeout SetInterval 网络请求

        微任务通常是一些更小粒度的任务,如Promise async/await

        微任务会被插入到微任务队列(microtask queue)中,在每个宏任务执行完成后,事件循环会检查微任务队列,然后依次执行微任务,直到微任务队列为空

console.log('start')
setTimeout(() => {console.log('timeout')
})
Promise.resolve().then(() => {console.log('promise then')
})
console.log('end')
// start
// end
// promise then
// timeout// 微任务在页面渲染前触发,宏任务是在页面渲染之后触发
const p = document.createElement('p')
p.innerHTML = 'new paragraph'
document.body.appendChild(p)
const list = document.getElementsByTagName('p')
console.log('length----', list.length)console.log('start')
setTimeout(() => {      // 渲染之后触发const list = document.getElementsByTagName('p')console.log('length on timeout----', list.length)alert('阻塞 Timeout')
})
// DOM 渲染
Promise.resolve().then(() => {  // 渲染前触发const list = document.getElementsByTagName('p')console.log('length on promise.then----', list.length)alert('阻塞 promise')
})
console.log('end')
// length---- 67
// start
// end
// length on promise.then---- 67
// length on timeout---- 67

        参考下图,浏览器事件循环机制首先执行左上角的同步代码,遇到异步任务会放入Callback Queue(现在已经分为Macro Queue 和Micro Queue)中,等同步代码执行完成之后,通过Event Loop机制执行队列中的任务

2.2 Node.js事件循环

        Nodejs同样使用ES语法,也是单线程,也需要异步;异步任务也分为:宏任务 + 微任务

        Node.js中事件循环实现是依靠libuv 引擎事件循环中表现得状态与浏览器大致相同。Node.js事件循环的大致执行流程也是先执行同步代码,再执行微任务(process.nextTick),按顺序执行6个类型的宏任务(每当开始之前都执行当前的微任务)

        但是,Node.js的宏任务和微任务,分不同类型,有不同的优先级

        Node.js中宏任务的类型和优先级(由高到低):

  • Timers - setTimout setInterval
  • I/O callbacks - 处理网络、流、TCP的错误回调(执行延迟到下一个循环迭代的I/O回调)
  • Idle,prepare - 闲置状态(Node.js内部使用)
  • Poll轮询 - 执行poll中的I/O队列
  • Check检查 - 存储setImmediate回调
  • Close callbacks - 关闭回调,如socket.on('clos')

        Node.js 微任务类型和优先级:

        包括: Promise,async/await,process.nextTick,其中process.nextTick优先级最高

        总之,在一次事件循环中,先执行当前执行栈中的代码,然后检查是否有微任务需要执行,如果有,则依次执行微任务,直到微任务队列为空;接着从宏任务队列中提取下一个宏任务进行执行。这样的设计保证了微任务能够在宏任务执行结束之后立即得到执行,从而更及时地处理异步操作的结果。

注:

        MDN上最新描述已经不再使用宏任务,沿用它是为了更容易理解

在 JavaScript 中通过 queueMicrotask() 使用微任务 - Web API 接口参考 | MDN一个微任务(microtask)就是一个简短的函数,当创建该微任务的函数执行之后,并且只有当 Javascript 调用栈为空,而控制权尚未返还给被用户代理用来驱动脚本执行环境的事件循环之前,该微任务才会被执行。事件循环既可能是浏览器的主事件循环也可能是被一个 web worker 所驱动的事件循环。这使得给定的函数在没有其他脚本执行干扰的情况下运行,也保证了微任务能在用户代理有机会对该微任务带来的行为做出反应之前运行。icon-default.png?t=N7T8https://developer.mozilla.org/zh-CN/docs/Web/API/HTML_DOM_API/Microtask_guide

        Node.js新版本,推荐使用setImmediate代替process.nextTick。

3. 遍历数组,for和forEach那个更快?

        先上代码验证下,结论是用for通常会比forEach更快

const arr = []
for(let i = 0; i < 100*10000 ; i++) {arr.push(i)
}
const length = arr.lengthconsole.time('for')
let n1 = 0
for (let i = 0; i < length; i++) {n1++
}
console.timeEnd('for')  // 3.838134765625 msconsole.time('forEach')
let n2 = 0
arr.forEach(() => n2++) 
console.timeEnd('forEach')  // 14.0830078125 ms

        forEach每次都要创建一个函数来调用(函数需要对立的作用域,会有额外的性能开销),而for不会创建函数。

        除此之外,使用for的优点还有:

  • 更多控制:使用for循环可以更灵活地控制循环过程,可以通过控制索引来实现跳过、中断、反向等操作。
  • 可中断性:for循环可以通过break语句或return语句随时中断循环,而forEach方法不支持中断循环,只能通过抛出异常来模拟中断。 虽然for循环在性能上可能更快,但在某些情况下,使用forEach方法可能更具可读性和简洁性

3. 虚拟DOM(vdom)真的很快吗?

        虚拟DOM(virtual dom) 一种用于简化 UI 更新和渲染逻辑的技术, 主要优点在于简化了对真实 DOM 的频繁操作。我们知道Vue React等框架的核心价值在于实现了数据视图分离,数据驱动视图。这样前端程序员coding实只关注业务数据,而不用再关心DOM变化,它们实现数据驱动视图的技术方案就是vdom。

        实际上,vdom并不快,JS直接操作DOM才是最快的;但是"数据驱动视图"需要合适的技术方案,不能全部DOM重建;vdom就是目前最合适的技术方案(并不是因为它快,而是合适)。

扩展:svelte框架就不用vdom

5. Node.js如何开启多进程?进程如何通讯?

        进程(Process) VS 线程 (Thread)

        进程,OS进行资源分配和调度的最小单位,有独立的内存空间

        线程,OS进行运算调度的最小单位,共享进程内存空间

        JS是单线程的,但是可以开启多个进程执行,如WebWorker

        为何需要多进程?

        多核CPU,更适合处理多进程

        内存较大,多个进程才能更好的利用(单进程有内存上限,一般2G左右)

        总之,"压榨"机器资源,更快,更节省

        通过child_process.fork开启子进程

/**
* 主进程
*/
const http = require('http')
const fork = require('child_process').forkconst server = http.createServer(() => {if(req.url === '/get-sum') {console.info('主进程 id', process.pid)// 开启子进程const computeProcess = fork('./computer.js')computeProcess.send('开始计算')computeProcess.on('message', data => {console.info('主进程接收到信息:', data)res.end('sum is ' + data)})computeProcess.on('close', data => {console.info('主进程因报错而退出')computeProcess.kill()res.end('error')})}})
server.listen(3000, () => {console.info('localhost: 3000')
})/**
* computed.js 子进程,计算
*/
function getSum() {let sum = 0for (let i = 0; i <10000; i++) {sum += i}return sum
}
//子进程可以通过这种自定义事件的方式来监听
process.on('message', data => {console.log('子进程 id', process.pid)console.log('子进程接收到的信息‘, data)const sum = getSum()// 发送消息给主进程process.send(sum)
})//localhost: 30000
// 主进程 id: 80780
// 子进程 id: 80781
// 子进程接收到的信息: 开始计算
// 主进程接收到的信息: 49995000

未完待续……

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

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

相关文章

理解CAE

用于自监督表示学习的上下文自动编码器 摘要 我们提出了一种新的掩模图像建模(MIM)方法&#xff0c;上下文自编码器(CAE)&#xff0c;用于自监督表示预训练。我们通过在编码的表示空间中进行预测来预训练编码器。预训练任务包括两个任务:掩模表示预测—预测掩模块的表示&…

专业145+总分410+西工大西北工业大学827信号与系统考研经验电子信息与通信工程,海航,真题,大纲,参考书。

经过一年的努力&#xff0c;分数终于出来。今年专业课827信号与系统145&#xff08;很遗憾差了一点点满分&#xff0c;没有达到Jenny老师的最高要求&#xff09;&#xff0c;数一130&#xff0c;英语和政治也都比较平衡&#xff0c;总分410分&#xff0c;当然和信息通信考研Jen…

C及C++每日练习(2)

1.选择&#xff1a; 1.使用printf函数打印一个double类型的数据&#xff0c;要求&#xff1a;输出为10进制&#xff0c;输出左对齐30个字符&#xff0c;4位精度。以下哪个选项是正确的&#xff1f; A.%-30.4e B.%4.30e C.%-30.4f D.%-4.30 在上一篇文章中&#xff0c;提到了…

变老特效哪个app可以拍?深入探索变老效果的应用

随着科技的进步和智能手机的普及&#xff0c;各种摄影应用如雨后春笋般涌现&#xff0c;为我们提供了前所未有的创意拍摄体验。其中&#xff0c;变老特效因其独特的魅力&#xff0c;吸引了众多用户的关注。这种特效能够让我们在短时间内看到自己老去的模样&#xff0c;既有趣又…

JavaWeb HTTP 请求头、请求体、响应头、响应体、响应状态码

J2EE&#xff08;Java 2 Platform Enterprise Edition&#xff09;是指“Java 2企业版”&#xff0c;B/S模式开发Web应用就是J2EE最核心的功能。 Web是全球广域网&#xff0c;也称为万维网(www)&#xff0c;能够通过浏览器访问的网站。 在日常的生活中&#xff0c;经常会使用…

强大的ps 命令 -o 自定义输出内容选项

强大的ps 命令 -o 自定义输出内容选项 1、ps命令介绍和作用2、问题描述 1、ps命令介绍和作用 ps 是一个 Unix 和类 Unix 操作系统中常用的命令&#xff0c;用于显示当前运行的进程信息。ps 命令的作用包括&#xff1a; 查看进程信息&#xff1a; ps 命令可以列出当前系统中正…

数据结构之顺序表及其实现!

目录 ​编辑 1. 顺序表的概念及结构 2. 接口的实现 2.1 顺序表的初始化 2.2 检查顺序表容量是否已满 2.3 顺序表的尾插 ​编辑 2.4 顺序表的尾删 2.5 顺序表的头插 2.6 顺序表的头删 2.7 顺序表在pos位置插入 2.8 顺序表在pos位置删除 2.9 顺序表的查找 2.10 顺…

考研数学——高数:多元函数微分法及其应用

因为复习阶段全篇很细节的写下来一来比较费时间&#xff0c;二容易导致为了记笔记而记。 接下来的内容只会保留上课中比较有意义的地方&#xff0c;以及有自己助于理解的想法 全微分 助记&#xff1a; 证明是否可微&#xff0c;首先判断两个偏导数是否存在&#xff0c;不存在则…

中文版国产Figma简单好上手

在过去的两年里&#xff0c;国内外协同办公室发展迅速。一方面&#xff0c;它是由突如其来的疫情推动的&#xff0c;另一方面&#xff0c;它是科学技术不断进步的必然结果。在市场的推动下&#xff0c;市场上出现了越来越多的协同办公软件&#xff0c;使工作场所的工作更加高效…

插入排序和归并排序

插入排序&#xff0c;Insertion Sort. 给出伪代码 for i 1,2,...,n-1Insert A[i] into Sorted array A[0:i-1]by swaping down to the correct position. 冒泡排序 冒泡排序就是一种插入排序算法。 i ← 1 while i < length(A)j ← iwhile j > 0 and A[j-1] > A…

CorelDRAW2024专业级图形设计矢量图形设计软件

CorelDRAW2024是一款功能强大的矢量图形设计软件&#xff0c;适用于专业级图形设计作品的设计师和创作者。它提供了智能对象、布局、插图和模板等功能&#xff0c;可以帮助用户快速创建高质量的设计作品。 这款软件的用户界面直观且易于使用&#xff0c;允许用户快速访问和管理…

184基于matlab的相关向量机(RVM)回归和分类算法

基于matlab的相关向量机&#xff08;RVM&#xff09;回归和分类算法。该算法基于贝叶斯稀疏核⽅法&#xff0c;避免了支持向量机&#xff08;SVM&#xff09;的主要局限性。RVM关键是为每个权参数 都引入一个单独的超参数 &#xff0c;而不是一个共享超参数。程序已调通&#x…

力扣hot100:42.接雨水(双指针/动态规划/贪心)

什么时候能用双指针&#xff1f; &#xff08;1&#xff09;对撞指针&#xff1a; ①两数和问题中可以使用双指针&#xff0c;先将两数和升序排序&#xff0c;可以发现规律&#xff0c;如果当前两数和大于target&#xff0c;则右指针向左走。 ②接雨水问题中&#xff0c;左边最…

【Web】浅聊JDBC的SPI机制是怎么实现的——DriverManager

目录 前言 分析 前言 【Web】浅浅地聊JDBC java.sql.Driver的SPI后门-CSDN博客 上篇文章我们做到了知其然&#xff0c;知道了JDBC有SPI机制&#xff0c;并且可以利用其Driver后门 这篇文章希望可以做到知其所以然&#xff0c;对JDBC的SPI机制的来源做到心里有数 分析 先是…

Python 弱引用全解析:深入探讨对象引用机制!

目录 前言 弱引用的概述 弱引用的原理 使用 WeakRef 类创建弱引用 使用 WeakValueDictionary 类创建弱引用字典 实际应用场景 1. 解决循环引用问题 2. 对象缓存 总结 前言 在Python编程中&#xff0c;弱引用&#xff08;Weak Reference&#xff09;是一种特殊的引用方式…

(文末送书)《低代码平台开发实践:基于React》

最近&#xff0c;我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念&#xff0c;而且内容风趣幽默。我觉得它对大家可能会有所帮助&#xff0c;所以我在此分享。点击这里跳转到网站。 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&am…

PCM会重塑汽车OTA格局吗(2)

目录 1.概述 2. PCM技术视角下的OTA 3.小结 1.概述 上一篇文章&#xff0c;我们着重讲解了OTA的概述内容&#xff0c;和意法半导体推出的跨域融合MCU的四大特征&#xff0c;其中就包含了OTA技术。 他们针对OTA做了比较创新的设计&#xff0c;在总的可用memory容量不变情况…

2024最新Android开发面试解答,学海无涯

一个程序员&#xff0c;如果不想35 岁被淘汰&#xff0c;请把它当成一种信仰&#xff01; 25岁&#xff0c;一个北漂程序员&#xff0c;入职三年&#xff0c;Android中级工程师&#xff0c;月薪15k&#xff0c;965的工作经常干成996&#xff0c;比起老家的同龄人&#xff0c;我…

15-Linux部署HBase集群

Linux部署HBase集群 简介 HBase 是一种分布式、可扩展、支持海量数据存储的 NoSQL 数据库。 和Redis一样&#xff0c;HBase是一款KeyValue型存储的数据库。 不过和Redis设计方向不同 Redis设计为少量数据&#xff0c;超快检索HBase设计为海量数据&#xff0c;快速检索 HB…

数据结构:排序算法+查找算法

一、概念 程序数据结构算法 1.算法的特性和要求 特性&#xff1a; 确定性&#xff08;每次运行相同的输入都是同样的结果&#xff09;、有穷性、输入、输出、可行性 设计要求&#xff1a; 正确性、高效率、低存储、健壮性、可读性 2.时间复杂度 3.常见排序算法的时间复杂…