浏览器原理之浏览器机制

事件机制

一 事件是什么?事件模型?

事件 是浏览器或用户自身发出的某种特定交互的信号。这包括但不限于鼠标点击、按键操作、页面加载、滚动等。

事件模型 主要包括三个阶段:

  1. 捕获阶段:事件从文档根节点向下传递到目标节点,主要用于拦截事件。
  2. 目标阶段:事件到达目标节点。
  3. 冒泡阶段:事件从目标节点向上冒泡到文档的根节点。

二 如何阻止事件冒泡

在事件处理函数中调用event.stopPropagation()方法可以阻止事件冒泡。这会阻止事件进一步传播到父节点。

三 对事件委托的理解

事件委托 是一种利用事件冒泡原理来优化事件处理的技术。它基于这样一个事实:在冒泡阶段,事件会一路向上传播到父节点。因此,可以将事件监听器设置在父节点上,而不是每个子元素上。这样,当子节点上的事件被触发时,它会冒泡到父节点,并被那里的监听器捕获。

四 事件委托的使用场景

  • 大量元素的事件处理:例如,列表或表格中的每个项目如果都绑定事件处理器会导致内存占用过高。事件委托可以减少绑定的事件处理器数量。
  • 动态元素的事件处理:对于动态添加到页面的元素,如果它们的事件处理器是通过事件委托添加的,就无需在添加元素时反复绑定事件。

五 同步和异步的区别

  • 同步操作:调用某个函数后,必须等待这个函数执行完毕才能执行下一行代码。
  • 异步操作:调用非阻塞函数后,可以继续执行后续代码,而被调函数通常会在未来的某个时间点完成,不会立即返回结果。

六 对事件循环的理解

事件循环是一种程序结构,用于等待和发送消息和事件。一个简单的事件循环只需不断检查是否有事件发生,如果有,就取出事件并执行相应的逻辑。

七 宏任务和微任务分别有哪些

  • 宏任务:包括整体代码script,setTimeout,setInterval,setImmediate(Node.js 环境)。
  • 微任务:包括Promise,process.nextTick(Node.js 环境),MutationObserver(浏览器中的API)。

八 什么是执行栈

执行栈(调用栈),是一个按照先进后出的方式操作的栈结构,用于存储在代码执行期间创建的所有执行上下文。

九 Node 中的 Event Loop 和浏览器中的有什么区别?process.nextTick 执行顺序?

Node.js 和浏览器中的事件循环有核心的架构差异,主要体现在它们处理异步事件的方式以及各自的微任务和宏任务的调度上。下面详细解释这些差异:

Node.js 中的事件循环

Node.js 的事件循环由 libuv 库实现,它是设计来适应异步 I/O 的需求。Node.js 的事件循环分为几个不同的阶段,每个阶段都有自己的任务队列:

  1. timers 阶段:这一阶段执行 setTimeout 和 setInterval 回调。
  2. I/O callbacks 阶段:处理大部分非定时器的回调,如网络通信、文件操作等。
  3. idle, prepare 阶段:仅内部使用。
  4. poll 阶段:检索新的 I/O 事件; 执行与 I/O 相关的回调(除了关闭回调,定时器和 setImmediate() 之外的几乎所有回调); 节点将在适当的条件下阻塞在这里。
  5. check 阶段:setImmediate() 回调在这里执行。
  6. close callbacks 阶段:例如 socket.on(‘close’, …) 的回调。

浏览器中的事件循环

浏览器的事件循环相对简单,主要是为了处理用户界面事件。它不需要像 Node.js 那样处理大量的异步 I/O 操作。浏览器的事件循环通常包括以下几个部分:

  1. 宏任务队列:包括处理脚本(script)、setTimeout、setInterval、I/O、UI rendering等。
  2. 微任务队列:处理 Promise、MutationObserver。当执行栈为空时,会在下一个宏任务执行前,先执行所有微任务。

process.nextTick 执行顺序

在 Node.js 中,process.nextTick() 不是事件循环的一部分,而是一个独立于事件循环的机制。process.nextTick() 允许用户在当前操作完成后,任何 I/O 事件(包括定时器和 setImmediate)之前,立即执行回调。如果在事件循环各个阶段中多次调用 process.nextTick(),Node.js 将会在进入下一阶段之前立即执行这些回调。

总结

  • Node.js 的事件循环是为了支持高效的异步 I/O 操作而设计的,包含多个阶段和专门的队列。
  • 浏览器 的事件循环主要是为了处理用户界面的响应,有一个相对简单的模型,主要区分宏任务和微任务。
  • process.nextTick() 在 Node.js 中,总是在当前执行栈清空后和任何其他异步事件之前执行,这使其成为触发紧急或必要任务的一种方式。

十 事件触发的过程

事件触发基本遵循以下流程:

  1. 事件监听:首先需要有某种方式(如addEventListener)去监听事件。
  2. 事件触发:当相应的用户操作或浏览器操作(如点击、加载等)发生时,事件被触发。
  3. 事件对象生成:浏览器会生成一个事件对象,该对象包含所有与事件相关的信息。
  4. 事件传播:事件会按照特定的顺序(捕获->目标->冒泡)进行传播。
  5. 事件处理:当事件到达被监听的元素时,对应的处理函数会被调用,事件对象会被传入,以供访问和操作。
  6. 事件结束:一旦所有事件监听器执行完毕,或者事件传播被显式停止(如调用stopPropagation()),事件生命周期结束。

垃圾回收机制

一 V8的垃圾回收机制

V8 引擎是 Google 开发的 JavaScript 引擎,它被广泛应用在 Chrome 浏览器和 Node.js 环境中。V8 的垃圾回收机制是其核心功能之一,主要目的是自动管理内存,即自动分配内存及回收不再使用的内存。V8 的垃圾回收机制主要分为两部分,处理新生代(young generation)和老生代(old generation)对象的回收策略。

1. 新生代内存回收

新生代内存主要存储生命周期较短的小对象。V8 为新生代内存分配了相对较小的空间(在64位系统中通常是 32 MB,在32位系统中通常是 16 MB)。垃圾回收在新生代内存中频繁进行,使用的是 Scavenge 算法,具体实现策略是 Cheney 算法,这是一种典型的复制式垃圾回收技术。

  • Scavenge 算法:在新生代空间中,内存被分为两个等大的部分,一半是对象区(active),另一半是空闲区(inactive)。新分配的对象首先放入对象区,当对象区满时,垃圾回收开始工作。存活的对象会被复制到空闲区,非存活对象则被舍弃。完成复制后,对象区和空闲区的角色互换。

2. 老生代内存回收

老生代内存用于存储生命周期长或体积较大的对象。老生代的内存空间远大于新生代(在64位系统中可达到 1.4 GB)。老生代使用 Mark-Sweep(标记-清除)和 Mark-Compact(标记-压缩)算法。

  • Mark-Sweep(标记-清除):这一阶段,垃圾回收器遍历堆中所有对象,并标记存活的对象。之后,进行一次清扫,回收未被标记的对象所占用的内存。此算法的缺点是可能会导致 “内存碎片”。

  • Mark-Compact(标记-压缩):为了解决内存碎片问题,V8 会周期性地进行标记-压缩回收。在标记阶段之后,存活的对象会被向内存的一端压缩,从而减少碎片,优化内存分配效率。

性能考虑

垃圾回收过程会暂停 JavaScript 的执行(称为 “停顿时间”),这对于需要高性能和实时响应的应用可能产生影响。V8 持续优化垃圾回收算法以减少停顿时间,例如通过增量标记(incremental marking)和延迟清扫(lazy sweeping)等技术。

总之,V8 的垃圾回收机制是一个复杂但高效的内存管理系统,它通过新生代和老生代的不同策略,有效地回收内存,同时尽量减少对应用性能的影响。

二 哪些操作会造成内存泄漏?

内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存。在Web应用中,内存泄漏可能导致应用变慢甚至崩溃,特别是在长时间运行的应用中。下面是一些常见的造成内存泄漏的操作:

  1. 全局变量

    • 无意中创建的全局变量。例如,未声明就赋值的变量自动成为全局变量。
  2. 定时器

    • 未被清除的定时器或间隔调用(例如setInterval),特别是那些引用了DOM元素的定时器,可能会阻止这些DOM元素被回收。
  3. 闭包

    • 滥用闭包可能会导致父函数中的变量无法被释放,尤其是在闭包被长时间保持不释放时。
  4. DOM引用

    • 如果JavaScript持续保持对已从DOM中删除的元素的引用,那么这些元素不会被垃圾回收机制回收。
  5. 事件监听器

    • 未被正确移除的事件监听器可以导致内存泄漏,因为它们可能保持对DOM元素的引用,阻止这些元素被回收。
  6. 第三方库

    • 使用的第三方库如果有内存泄漏,也可能影响使用这些库的应用。

了解这些常见的内存泄漏来源并采用适当的策略可以帮助在开发过程中避免内存泄漏,提升应用的性能和稳定性。

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

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

相关文章

PyQt6实战7--文本编辑器

一个简单的文本编辑器 features: 1.open 一个文件夹作为项目 2.save 保存当前窗口的内容 3.退出 4.双击文件可以打开文件内容 5.简单的python高亮 6.双击相同文件,会找到之前打开过的文件 打开一个文件夹 打开项目,双击打开文件 保存 代码&#xf…

雷电模拟器+python

import os import time from compare import compare #上一段代码我存为了compare.pyclass Ldconsole: #请根据自己软件的路径来console rF:\leidian\LDPlayer9\dnconsole.exe ld rF:\leidian\LDPlayer9\ld.exeadb rF:\leidian\LDPlayer9\adb.exe #这个类其实不用写的&…

CSRF漏洞

文章目录 目录 文章目录 一.什么是CSRF 二.CSRF漏洞工作原理 一.什么是CSRF CSRF(Cross-Site Request Forgery)漏洞,也被称为跨站请求伪造漏洞,是一种Web应用程序安全漏洞。当受害者在已经登录了某个网站的情况下,访问…

密码学 | 数字签名方法:Schnorr 签名

⚠️原文:Introduction to Schnorr Signatures ⚠️写在前面:适用于有一点密码学基础的亲故,否则建议跑路。 1 Schnorr 签名的定义 假设你有密钥对 ( x , X x ∗ G ) ( x, X x * G ) (x,Xx∗G),那么消息 m m m 的 Schnor…

吴恩达机器学习笔记 三十五 异常检测与监督学习

什么时候选择异常检测? 正样本 ( y 1 ) 的数量非常少 负样本 ( y 0 ) 的数量非常多 有很多不同的异常,现有的算法不能从正样本中得知什么是异常,或未来可能出现完全没见过的异常情况。 例如金融欺诈,隔几个月或几年就有新的…

java+idea+mysql采用医疗AI自然语言处理技术的3D智能导诊导系统源码

javaideamysql采用医疗AI自然语言处理技术的3D智能导诊导系统源码 随着人工智能技术的快速发展,语音识别与自然语言理解技术的成熟应用,基于人工智能的智能导诊导医逐渐出现在患者的生活视角中,智能导诊系统应用到医院就医场景中&#xff0c…

jvm-接口调用排查

问题描述 线上碰到个问题,某个接口调用时间特别长,线上调用接口直接报gateway time out 分析处理 1、先关闭该功能 (该功能是非核心功能) 2、本地起服务连环境排查,发现本地正常。并且线上其他接口正常,…

机器学习笔记——浅析L2,1范数正则化的线性回归

前言 嘻嘻,刚开始搓逾期了快两周的线性回归实验报告,为了让报告稍微不那么平淡不得不啃论文。 本文从最基本的线性回归开始,对比不同正则化方法的特点和作用,推广到多任务问题并引出L2,1范数正则化,卑微小采购尝试去…

顺序表复习(C语言版)

数据结构是什么? 数据结构就是为了把数据管理起来,方便我们的增删查改 数据结构是计算机存储、组织数据的方式 数组就是一种最基础的数据结构 顺序表是什么? 顺序表就是数组 Int arr[100] {1,2,3,4,5,x,……} 修改某个数据&#xff1a…

【leetcode面试经典150题】56. 基本计算器(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主,题解使用C语言。(若有使用其他语言的同学也可了解题解思路,本质上语法内容一致&…

Mac下删除旧版本.net sdk

参照微软官网给的方法,Releases dotnet/cli-lab (github.com) 好像不能直接的解决问题,我做一下补充,希望对需要删除旧版本sdk的小伙伴们有所帮助 1:下载工具包 Releases dotnet/cli-lab (github.com) 2:打开终端,cd切换到该文件的制定目录 3:然后按照提示一步步执行…

mybatis使用

mybatis使用 一、添加配置文件 在application.properties配置文件文件中添加数据库连接信息 spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver spring.datasource.urljdbc:mysql://localhost:3306/your_database_name?useUnicodetrue&characterEncodingUTF-…

java核心类

一,String字符串 1.1,String字符串是引用类型,且不可变 String str1 "Hello";String str2 str1.concat(" World"); // 使用concat方法连接字符串,返回一个新的字符串对象System.out.println(str1); // 输出:Hello,原始…

C语言:复习

文章目录 思维导图数组和指针库函数的模拟实现判断大小端 最近知识学的差不多了,因此开始复习,本篇开始的是对于C语言的复习 思维导图 下面就依据下图,进行内容的整理 数组和指针 这个模块算是C语言中比较大的一个模块了,具体概…

IO——线程

1. 什么是线程 1.1概念 线程是一个轻量级的进程,为了提高系统的性能引入线程。 线程和进程都参与统一的调度。 在同一个进程中可以创建的多个线程, 共享进程资源。 (Linux里同样用task_struct来描述一个线程) 1.2进程和线程的区别 相同点…

【Vue】Vue中使一个div铺满全屏

在Vue中实现div全屏铺满的方式与纯CSS实现类似&#xff0c;只是在Vue组件中应用CSS的方式略有不同。 最近在项目开发中&#xff0c;就遇到了这个问题&#xff0c;特此记录一下&#xff0c;方便大伙避坑。 有这么一段代码&#xff1a; <template><div class"fu…

JS - 在JS中常用的运算符

学过编程语言的都知道一种大部分编程语言其实都存在许多相似的地方&#xff0c;比如数学中的四则运算&#xff0c;这个在JS中同样生效&#xff0c;不过在JS中&#xff0c;有进行部分拓展&#xff0c;这个也是其他语言中都有的&#xff0c;每个语言都有其功能和特性&#xff0c;…

流媒体协议--RTMP

文章目录 RTMP播放基本流程TCP握手过程RTMP握手过程connect连接createStream 创建流play 播放命令deleteStream删除流RTMP数据组成 RTMP(Real Time Messaging Protocol)是一个应用层协议&#xff0c;主要用于在Flash player和服务器之间传输视频、音频、控制命令等内容。 该协议…

类和对象-对象特性-类对象作为类成员

类对象作为类成员 #include<iostream> #include<string> using namespace std; class Phone{ public:Phone(string pName){m_pNamepName;}string m_pName; }; class Person{ public:Person(string name,string pName):m_Name(name),m_Phone(pName){}string m_Nam…

【笔试强训_Day06】

文章目录 1.字符串相乘 1.字符串相乘 题目链接 解题思路&#xff1a; 高精度乘法&#xff0c;注意要学会下面这种列式相乘的形式&#x1f34e; 注意细节❗&#xff1a; ① &#x1f34e; 首先把列式相乘的数据都存放到数组中去&#xff0c; 然后再对数组中的数据进行取余进…