【前端面试复习系列文章】
【导读】本文总结了前端面试中经常问到的HTTP和浏览器高频面试题,仅供参考。
下图为思维导图:
1.GET和POST有什么区别?
GET和POST是HTTP协议中的两种请求方法,它们之间存在一些重要的区别,主要体现在以下方面:
- 请求参数的位置:GET请求的请求参数会附加在URL之后,参数之间使用"&"连接,多个参数将会造成URL长度增加。而POST请求的请求参数则包含在请求体中,不会在URL中显示。
- 请求长度的限制:由于GET请求的参数附加在URL之后,因此其请求长度受限于浏览器对URL长度的限制(通常浏览器对URL的长度有限制,而服务器对URL的长度限制更为宽松)。而POST请求则没有这个问题,请求参数包含在请求体中,因此可以传输大量数据。
- 安全性:GET请求的参数会暴露在URL中,因此不能用于传输敏感信息,如密码等。而POST请求的参数在请求体中,不会在URL中显示,相对更加安全。然而,这并不意味着POST请求就一定比GET请求更安全,因为安全性还需要依赖于其他因素,如SSL/TLS加密等。
- 幂等性:GET请求是幂等的,即多次执行同一GET请求,服务器将返回相同的结果。而POST请求则不是幂等的,因为每次提交都会创建新的资源。
- 缓存:GET请求可以被缓存,而POST请求则不会,除非在响应头中包含适当的Cache-Control或Expires字段。
- 后退/刷新按钮的影响:GET请求可以被浏览器缓存,因此可以通过点击后退按钮或刷新按钮来重复执行。而POST请求则不会,因为这些操作对POST请求没有实际意义。
总的来说,GET和POST请求各有其特点和适用场景。GET请求通常用于请求数据,而POST请求则常用于提交数据。在选择使用哪种请求方法时,需要考虑到安全性、请求长度、幂等性等因素。
2.HTTP2相对于HTTP1.x有什么优势和特点?
HTTP/2相对于HTTP/1.x具有显著的优势和特点,主要体现在以下几个方面:
- 二进制分帧层:HTTP/2不再使用文本格式来传输数据,而是将所有传输的信息分割为更小的消息和帧(frame),并以二进制格式进行编码。这有助于更高效地解析HTTP消息,并减少了解析错误的可能性。
- 多路复用:HTTP/2引入了多路复用技术,允许在单个TCP连接中并行处理多个请求和响应。这消除了HTTP/1.x中的队头阻塞问题,极大地提高了网络性能和资源利用率。
- 头部压缩:HTTP/2使用了头部压缩技术,通过共享头部信息,可以显著减少传输的数据量。这有助于减少延迟和网络带宽的消耗,特别是在传输大量小请求时效果更为显著。
- 服务器推送:HTTP/2允许服务器主动向客户端推送资源,而无需等待客户端的请求。这有助于减少往返时间,并提高网页加载速度。
- 流量控制:HTTP/2通过流控制、消息控制和窗口控制等机制,实现了对流量的精细控制,有助于防止网络拥塞和资源浪费。
总的来说,HTTP/2相对于HTTP/1.x在传输效率、安全性、网络性能等方面都有显著的提升。这些优势使得HTTP/2成为现代Web应用中广泛采用的协议标准。
3.https是怎么保证安全的,为什么比http安全
HTTPS之所以比HTTP更安全,主要是通过以下几种机制来保证其安全性:
- 加密传输:HTTPS使用SSL/TLS协议对HTTP报文进行加密,使得敏感数据在网络传输过程中不容易被窃听和篡改。这种加密过程结合了对称加密和非对称加密,确保数据的保密性和完整性。
- 身份验证:HTTPS通过数字证书进行身份验证,确保通信双方的真实性。在建立HTTPS连接时,服务器会提供数字证书来证明自己的身份。如果验证通过,客户端就可以信任服务器,并继续与其进行安全的数据传输。这有效防止了被恶意伪装的服务器攻击。
- 数据完整性保护:在传输数据之前,HTTPS会对数据进行加密,并使用消息摘要(hash)算法生成一个摘要值。在数据到达接收端后,接收端会使用相同的算法对接收到的数据进行摘要计算,并与发送端的摘要值进行比较。如果两者一致,说明数据在传输过程中没有被篡改。如果不一致,通信双方应重新进行验证或中断连接。
这些机制共同作用,使得HTTPS在数据传输、身份验证和数据完整性保护等方面都优于HTTP,从而提供了更高的安全性。因此,对于涉及用户个人隐私和敏感信息的网站,如银行、电商等,使用HTTPS协议可以有效保护用户的账号、密码等信息,提高用户信息的安全性。
4.HTTP的状态码有哪些?并代表什么意思?
HTTP状态码是由三位数字组成的代码,用于表示客户端向服务器发起请求后,服务器对请求的响应状态。这些状态码可以大致分为五类,包括信息性状态码、成功状态码、重定向状态码、客户端错误状态码和服务器错误状态码。
以下是一些常见的HTTP状态码及其代表的意思:
-
1xx(信息性状态码):
- 100 Continue:客户端应继续其请求。
-
2xx(成功状态码):
- 200 OK:请求成功。
- 201 Created:请求已经被实现,并因此创建了一个新的资源。
- 204 No Content:服务器成功处理了请求,但没有返回任何内容。
-
3xx(重定向状态码):
- 301 Moved Permanently:请求的资源已被永久移动到新的URL上。
- 302 Found:请求的资源现在临时从不同的URL响应请求。
- 304 Not Modified:客户端已经执行了GET请求,但文件未发生变化。
-
4xx(客户端错误状态码):
- 400 Bad Request:服务器无法理解请求。
- 401 Unauthorized:请求要求进行身份验证。
- 403 Forbidden:服务器理解请求,但拒绝执行它。
- 404 Not Found:服务器无法找到请求的资源。
- 405 Method Not Allowed:请求中指定的方法不被允许。
-
5xx(服务器错误状态码):
- 500 Internal Server Error:服务器遇到了一个未曾预料的情况,导致其无法完成对请求的处理。
- 501 Not Implemented:服务器不支持当前请求所需要的某个功能。
- 503 Service Unavailable:由于临时的服务器维护或者过载,服务器当前无法处理请求。
这些状态码为客户端和服务器之间的通信提供了丰富的反馈机制,使得双方可以更好地理解请求的处理情况和可能存在的问题。
5.post请求为什么会多发送一次option请求
POST
请求前发送的 OPTIONS
请求实际上是 HTTP 的一种特性,称为"预检请求"(Preflight request)。这主要发生在跨域请求(CORS, Cross-Origin Resource Sharing)的场景中,尤其是当请求涉及一些可能不太安全的方法(如 PUT
、DELETE
或 POST
)或使用了一些自定义的 HTTP 头部时。
预检请求的目的是检查服务器是否允许来自不同源(域、协议或端口)的请求进行某些操作。这样做可以确保客户端在发送实际请求之前,先得到服务器的明确许可。
以下是 OPTIONS
预检请求的主要特点和原因:
- 安全性 :HTTP 协议中的某些方法(如
GET
、HEAD
、POST
)被认为是"安全"的,因为它们不会导致服务器上资源的状态发生变化。但是,其他方法(如PUT
、DELETE
等)可能会导致资源的创建、修改或删除。因此,在发送这些"非安全"请求之前,浏览器会先发送一个OPTIONS
请求来询问服务器是否允许这样的操作。 - 自定义头部 :如果请求中包含了某些自定义的 HTTP 头部,浏览器也会发送
OPTIONS
请求来询问服务器是否接受这些头部。 - CORS 配置 :服务器在响应
OPTIONS
请求时,可以通过Access-Control-Allow-Methods
、Access-Control-Allow-Headers
等头部来告诉浏览器它允许哪些方法和头部。如果服务器的响应中包含了这些头部,并且允许了客户端想要执行的操作,那么浏览器才会继续发送实际的POST
请求。
总之,OPTIONS
预检请求是浏览器和服务器之间的一种协商机制,用于确保跨域请求的安全性和合规性。当浏览器认为有必要进行这种检查时,它就会在发送实际请求之前先发送一个 OPTIONS
请求。
6.http的请求和响应报文分别是什么样的?
HTTP的请求报文和响应报文具有特定的格式和结构,它们共同构成了HTTP通信的基础。
HTTP请求报文主要由请求行、请求头部、空行和请求正文组成。请求行包含了HTTP方法(如GET、POST等)、请求的URI(资源的标识符)以及HTTP的版本号。请求头部则包含了若干与请求相关的信息,如Accept-Charset(浏览器可接受的字符集)、Accept-Encoding(浏览器能够进行解码的数据编码方式)、Accept-Language(浏览器所希望的语言种类)等。空行用于分隔请求头部和请求正文,而请求正文则包含了需要发送给服务器的数据。
HTTP响应报文则主要由状态行、响应头部和响应正文组成。状态行包含了HTTP版本、状态码以及状态码的描述,用于描述请求的处理结果。响应头部包含了与响应相关的元信息,如Content-Type(响应体的媒体类型)、Content-Length(响应体的长度)等。响应正文则包含了服务器返回给客户端的数据。
需要注意的是,无论是请求报文还是响应报文,它们的格式都需要严格遵循HTTP协议的规定,以确保通信的正确性和可靠性。同时,具体的字段和值也会根据实际的HTTP方法和请求的资源类型而有所不同。
综上所述,HTTP的请求报文和响应报文通过特定的格式和结构,实现了客户端和服务器之间的有效通信和数据传输。
7.同样是重定向307,303,302的区别?
重定向307、303和302之间的主要区别体现在以下方面:
- 临时性与永久性:307和302都是临时重定向,意味着请求的资源临时移到了不同的位置。客户端在将来的请求中可以继续使用原始URL,因为这个重定向只是暂时的。而303虽然也属于临时重定向,但其语义稍有不同,它主要用于将请求重定向到另一个URI,同时保留客户端的会话状态。
- 请求方法的改变:302允许各种各样的重定向,但并不能确保POST请求会重定向为POST。而303只允许任意请求重定向到GET,这意味着不论原始请求的方法是什么,重定向后的请求都会使用GET方法。至于307,它与302类似,但不允许POST请求被重定向为GET请求,即它会保持原有的请求方法不变。
- 浏览器兼容性:由于部分浏览器不能识别307响应,因此响应中需要包含必要的信息,如指向新的URI的超链接及简短说明,以便用户能够理解并向新的URI发出访问请求。而302和303则没有这方面的特殊要求。
- 协议版本:302和301是HTTP 1.0中的内容,而303、307等则是HTTP 1.1中引入的。
综上所述,重定向307、303和302在临时性与永久性、请求方法的改变、浏览器兼容性和协议版本等方面存在显著的差异。在实际使用中,应根据具体的需求和场景选择合适的重定向状态码。
8.HTTP的keep-alive是干什么的?
HTTP的keep-alive,也称为HTTP长连接,是一种通过重用TCP连接来发送和接收多个HTTP请求的机制。其主要作用包括:
- 减少连接建立开销:在没有keep-alive的情况下,每次HTTP请求都需要经过TCP三次握手建立连接,这会导致较大的延迟和资源消耗。而使用keep-alive,可以在一个TCP连接上发送多个HTTP请求,从而减少了建立连接的开销。
- 降低网络负载:每次建立和关闭连接时,都会消耗网络带宽和服务器资源。通过保持持久连接,可以减少连接的频繁建立和关闭,从而降低了网络负载和服务器负载。
- 提高性能和响应时间:由于避免了连接建立和关闭的开销,keep-alive可以提高请求的响应时间和整体性能。客户端可以在同一个连接上连续发送请求,而服务器也可以在保持连接的情况下更快地响应这些请求。
- 支持HTTP管道化:HTTP管道化是允许客户端在同一TCP连接中连续发送多个请求而无需等待每个请求的响应的技术。当与keep-alive结合使用时,可以进一步提高性能。
需要注意的是,keep-alive机制在HTTP/1.0和HTTP/1.1协议中都有支持。在HTTP/1.0中,需要在请求头中显式添加"Connection: keep-alive"来启用该机制;而在HTTP/1.1中,keep-alive是默认启用的。
总的来说,HTTP的keep-alive机制通过重用TCP连接和优化请求处理流程,提高了HTTP通信的性能和效率。
9.从输入URL到看到页面发生的全过程
从输入URL到看到页面,这一过程涉及了多个步骤和组件之间的交互。以下是这个过程的大致概述:
- 用户输入URL:用户首先在浏览器地址栏中输入想要访问的网站的URL。
- 浏览器解析URL:浏览器内部代码会解析这个URL。它首先会检查本地hosts文件,看是否有对应的域名。如果有,浏览器就会直接向该IP地址发送请求。如果没有,浏览器会将域名发送给DNS服务器进行解析,将域名转换成对应的服务器IP地址。
- 建立TCP连接:浏览器得到IP地址后,会通过TCP协议与服务器建立连接。TCP/IP协议是Internet的基础,它负责确保数据在网络中的可靠传输。这一过程中会进行三次握手,确保双方都已准备好进行通信。
- 发送HTTP请求:TCP连接建立后,浏览器会向服务器发送HTTP请求。这个请求包含了请求行(如GET方法、请求的URI、HTTP版本等)、请求头部(如Accept-Charset、Accept-Encoding等)以及可能存在的请求正文。
- 服务器处理请求:服务器收到请求后,会根据请求的内容进行相应的处理。这可能包括查询数据库、生成动态内容等。
- 发送HTTP响应:服务器处理完请求后,会发送一个HTTP响应给浏览器。这个响应包含了状态行(如HTTP版本、状态码、状态描述等)、响应头部(如Content-Type、Content-Length等)以及响应正文(即实际要显示的页面内容)。
- 浏览器解析和渲染页面:浏览器收到响应后,会解析响应正文中的HTML代码,并下载所需的CSS、JavaScript等资源文件。然后,浏览器会根据这些资源来渲染页面,最终将页面呈现给用户。
需要注意的是,这个过程可能还涉及到其他的步骤和组件,如重定向、缓存、代理服务器等,具体取决于网络环境和浏览器设置。此外,对于HTTPS协议,还涉及到SSL/TLS加密和证书验证等步骤,以确保数据传输的安全性。
总的来说,从输入URL到看到页面是一个复杂且多步骤的过程,涉及了用户、浏览器、DNS服务器、服务器等多个实体之间的交互和通信。
10.浏览器缓存的优先级?
浏览器缓存的优先级主要遵循以下顺序:
-
Service Worker 缓存:由于其可以完全控制网络请求,因此具有最高的优先级,即使是强制缓存也可以被它所覆盖。Service Worker是运行在浏览器背后的独立线程,一般可以用来实现缓存功能。但请注意,由于Service Worker中涉及到请求拦截,所以必须使用HTTPS协议来保障安全。
-
Memory Cache(内存缓存) :这是内存中的缓存,主要包含的是当前页面中已经抓取到的资源,如样式、脚本、图片等。当我们访问过页面以后,再次刷新页面,可以发现很多数据都来自于内存缓存。
-
HTTP Cache(HTTP缓存)
:这包括强制缓存和协商缓存。
- 强制缓存:在有效时间内,不会向服务器发送请求,直接从缓存中读取资源。控制强制缓存的字段分别是Expires和Cache-Control,其中Cache-Control的优先级高于Expires。
- 协商缓存:当强制缓存失效后,浏览器会携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存。控制协商缓存的字段有Last-Modified/If-Modified-Since和Etag/If-None-Match。
-
Disk Cache(磁盘缓存) :存储在硬盘中的缓存,读取速度较慢,但胜在容量和存储时效性上。
-
Push Cache(推送缓存) :这是HTTP/2中的内容,当以上四种缓存都没有命中时,它才会被使用。
总结来说,浏览器在查找缓存时,会按照上述优先级顺序进行查找,如果某一层级的缓存命中,就不会继续查找下一层级的缓存。这样的设计有助于优化网络性能,减少不必要的网络请求,提高网页加载速度。
11.为什么会存在跨域及常见跨域的解决办法?
跨域问题的存在主要是因为浏览器的同源策略限制。同源策略是浏览器的一种安全机制,旨在防止一个域的脚本与另一个域的内容进行交互,以保护用户免受诸如跨站脚本攻击(XSS)和跨站请求伪造(CSRF)等安全威胁。所谓同源,指的是两个页面具有相同的协议(如http或https)、主机(域名或IP地址)和端口号。当这三个条件中任何一个不匹配时,就会触发跨域问题。
为了解决跨域问题,有多种常见的解决方案:
- JSONP :利用
标签不受同源策略限制的特性,通过动态插入
标签来请求不同源的数据。JSONP只支持GET请求,并且需要在服务器端进行相应的配合。 - CORS(跨域资源共享) :CORS 是一种 W3C 规范,它定义了一种浏览器和服务器交互的方式来确定是否允许跨源请求。通过服务器端设置相应的HTTP头部信息,如
Access-Control-Allow-Origin
,来允许跨域请求。CORS 支持各种HTTP请求方法,并且更加灵活和安全。 - 代理服务器:通过搭建一个代理服务器来转发请求,使得前端可以通过代理服务器来间接访问不同源的资源。这样,前端请求实际上是发往同源的代理服务器,再由代理服务器去请求不同源的资源。
- 使用window.postMessage:window.postMessage是HTML5引入的一个新的API,允许来自不同源的脚本进行通信。通过监听window对象的'message'事件,可以接收其他窗口发送过来的消息。
- 设置document.domain :如果两个页面属于同一个顶级域名下的不同子域名,可以通过设置
document.domain
为相同的顶级域名来实现跨域。但是,这种方式存在限制,并且可能引入其他安全风险。
在选择跨域解决方案时,需要根据具体的业务场景、安全需求以及技术栈来综合考虑。同时,无论采用哪种方案,都应注意保护用户数据的安全和隐私。
12.浏览器的渲染机制是怎样的?
浏览器的渲染机制是一个复杂且精细的过程,主要涉及到解析HTML、CSS,构建DOM树和CSSOM树,然后合并它们以构建渲染树,再进行布局和绘制,最终将页面内容展示给用户。以下是详细步骤:
- 解析HTML并构建DOM树:当浏览器接收到HTML文档后,它会解析HTML标签,将标签转换为DOM(文档对象模型)节点,并按照文档的结构将这些节点组织成一棵树形结构,即DOM树。DOM树是浏览器内部表示网页内容的一种方式,它包含了网页中所有的元素和属性。
- 解析CSS并构建CSSOM树:与此同时,浏览器也会解析CSS代码,将样式规则转换为CSSOM(CSS对象模型)节点,并构建成CSSOM树。CSSOM树描述了HTML文档中每个元素的样式信息。
- 构建渲染树:接下来,浏览器会将DOM树和CSSOM树合并成渲染树(Render Tree)。渲染树只包含需要显示的节点和样式信息,不包括隐藏的元素或不可见的样式。这一步是渲染过程中的关键步骤,因为它决定了哪些元素将被渲染以及如何渲染。
- 布局:在构建完渲染树后,浏览器会根据渲染树的信息计算每个节点的位置和大小,生成布局。这个过程也称为重排或回流,它涉及到对元素的位置和尺寸进行精确计算,以确保页面元素能够正确地显示在屏幕上。
- 绘制:布局完成后,浏览器会将每个节点的样式信息转换为像素,然后绘制到屏幕上。这个过程也称为重绘,它涉及到将元素的视觉表现绘制出来。
需要注意的是,当页面内容发生变化时(如用户交互、JavaScript操作等),浏览器会重新执行上述过程,进行重绘和回流。重绘和回流是浏览器渲染过程中比较耗时的操作,因此优化这些过程是提高页面性能的关键。
此外,现代浏览器还采用了一些优化策略来提高渲染性能,如GPU加速、懒加载、异步处理等。这些技术可以帮助浏览器更高效地处理大量数据,减少渲染工作量,提高页面的响应速度和用户体验。
总的来说,浏览器的渲染机制是一个复杂且精细的过程,它涉及到多个步骤和组件的协同工作。了解这个过程有助于我们更好地优化网页性能,提升用户体验。
13.什么是重绘和回流及怎么减少重绘和回流?
重绘和回流是浏览器渲染页面时的两个重要概念。
重绘(Repaint):当页面中元素样式的改变不影响布局时,浏览器将只会重新绘制受影响的元素,这个过程称为重绘。例如,改变一个元素的背景色或文字颜色,但不影响其位置和大小,就会触发重绘。
回流(Reflow 或 Relayout):也称为重排,当页面布局或几何属性发生变化时,浏览器需要重新计算元素的几何属性,并重新构建渲染树,这个过程称为回流。例如,改变元素的宽度、高度、位置等属性,或者添加、删除DOM节点,都会触发回流。
减少重绘和回流的方法:
- 避免频繁操作样式:尽量一次性修改多个样式属性,而不是逐一修改,以减少浏览器的重绘和回流次数。
- 利用CSS3动画:CSS3动画和过渡不会触发回流,因为它们是通过GPU进行渲染的,这可以大大提高性能。
- 避免使用table布局:table布局在发生变化时可能需要多次计算,这会增加回流次数。尽量使用flexbox或grid等现代布局技术。
- 批量修改DOM:如果需要添加、删除或修改多个DOM节点,可以考虑使用DocumentFragment或离线节点,这样可以在一次回流中完成所有操作。
- 使用绝对定位:绝对定位的元素不会触发其父元素及后续元素的回流,因为它们已经脱离了正常的文档流。
- 避免使用内联样式:内联样式会增加重绘和回流的可能性,因为它们会直接修改元素的样式。尽量使用外部CSS文件来管理样式。
- 优化图片加载:使用合适的图片格式和大小,避免使用大量的图片,以减少页面的渲染负担。
- 利用浏览器的缓存机制:对于不经常变动的资源,可以利用浏览器的缓存机制来减少请求次数,从而加快页面加载速度。
综上所述,通过优化CSS样式、减少DOM操作、利用浏览器缓存等方式,可以有效地减少页面的重绘和回流次数,提高页面的渲染性能。
14.浏览器的事件机制
浏览器的事件机制主要涉及到事件的触发、传播和处理。当用户在浏览器中进行某些操作,如点击按钮、移动鼠标或输入文本时,会触发相应的事件。这些事件被封装为event对象,包含了事件的属性和方法,供开发者在事件处理函数中使用。
事件的传播过程分为三个阶段:捕获阶段、目标阶段和冒泡阶段。在DOM2级事件模型中,事件首先在最外层HTML元素上开始捕获,然后向下传递到事件的目标元素,沿途触发所有设置了捕获事件处理器的元素。接着,事件处理器在事件的目标元素上执行,这是事件处理的核心阶段。最后,事件从目标元素向上回溯,触发所有设置了冒泡事件处理器的元素,完成冒泡阶段。这种机制允许开发者在事件传播的不同阶段拦截并处理事件。
常见的事件类型包括鼠标事件(如click、mouseover、mousedown等)、键盘事件(如keydown、keyup、keypress等)以及表单事件(如submit、input、change等)。这些事件为开发者提供了丰富的交互能力,可以响应用户的各种操作并相应地更新页面内容。
在事件处理过程中,浏览器还维护一个事件队列。一旦事件队列中的事件得到处理,它就会被移除。此外,浏览器还支持宏任务和微任务的概念,用于管理异步执行的任务。例如,setTimeout、setInterval等是常见的宏任务,而Promise的回调则是微任务。这些任务的执行顺序和优先级也是事件机制的一部分。
总的来说,浏览器的事件机制是一个复杂而精细的系统,它确保了用户与网页之间的交互能够正确、高效地执行。通过理解并合理利用事件机制,开发者可以创建出更加动态和响应式的网页应用。
15.浏览器的事件循环和node的事件循环区别
浏览器的事件循环和Node.js的事件循环虽然都用于处理异步操作和事件驱动编程,但在实现方式和具体细节上存在一些区别。
首先,从执行环境来看,浏览器中的事件循环主要运行在Javascript引擎和渲染引擎之间,这可能会导致线程阻塞,尤其是在渲染进程和事件循环共享同一个线程时。而Node.js中的事件循环是运行在单独的线程中,基于事件驱动模型,通过事件循环来处理和派发事件,以及执行相应的回调函数。这种设计使得Node.js可以处理大量的并发请求。
其次,在宏任务和微任务的处理上,两者也有所不同。在浏览器中,宏任务和微任务是通过HTML5规范中定义的消息队列来实现的。所有的异步任务都被分为宏任务和微任务两种类型,并依次加入到对应的队列中。当当前的宏任务执行完毕后,会立即执行所有的微任务,然后再选择下一个宏任务执行。而Node.js使用libuv库提供的事件循环机制来管理宏任务,并使用process.nextTick()方法来实现微任务。在Node.js的事件循环中,所有的宏任务都被分为6个不同的阶段,每个阶段会执行一些同步和异步的操作。
另外,两者处理的事件类型也有所区别。浏览器中的事件循环主要用于处理用户交互事件(例如点击、滚动等)和网络请求等异步任务。而Node.js的事件循环则主要用于处理I/O操作(例如文件操作、网络请求等)和自定义的事件。
总的来说,浏览器的事件循环和Node.js的事件循环在执行环境、宏任务和微任务的处理方式以及处理的事件类型等方面存在明显的区别。这些区别使得它们各自在不同的应用场景中都能发挥出最佳的性能和效果。
16.浏览器的垃圾回收机制
浏览器的垃圾回收机制是浏览器管理内存、确保资源有效利用的关键部分。当变量、对象或其他资源不再被使用时,垃圾回收机制会自动释放它们所占用的内存,从而防止内存泄漏。
JavaScript具有自动垃圾回收机制,会定期对不再使用的变量、对象进行清理。这主要通过两种实现方式:标记清除和引用计数。其中,标记清除是js中最常用的垃圾回收方式。当变量进入环境时,例如在一个函数中声明一个变量,这个变量会被标记为"进入环境"。而当变量离开环境时,它会被标记为"离开环境",随后被垃圾回收机制回收。
此外,垃圾回收过程中还需要处理全局变量和局部变量。全局变量的生命周期会持续到页面卸载,而局部变量在函数执行结束后就不再被使用,它们的内存空间会被释放。但值得注意的是,当局部变量被外部函数使用时(如闭包情况),它们依然会被视为在使用中,因此不会被回收。
浏览器的垃圾回收机制虽然可以自动管理内存,但开发者仍需注意避免不必要的内存占用和潜在的内存泄漏。通过优化代码、减少全局变量的使用、及时解除不必要的引用等方式,可以有效提高应用的性能和稳定性。
总的来说,浏览器的垃圾回收机制是确保浏览器高效、稳定运行的重要机制之一。它通过自动管理内存,减少了开发者手动管理内存的复杂性,提高了开发效率。同时,开发者也需要注意合理使用内存,避免潜在的内存问题。
17.进程和线程的区别?
进程和线程的主要区别体现在以下几个方面:
- 资源占用:进程是系统分配资源的基本单位,它包含独立的地址空间、资源表、堆栈、程序计数器等,每个进程都有独立的内存空间和系统资源。而线程是进程的一个实体,是CPU调度和分派的基本单位,线程只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
- 并发性:由于线程共享进程的内存空间和资源,因此线程间的切换开销小,有利于并发执行。而进程间的切换需要涉及系统资源(如内存、打开的文件等)的分配与回收,开销较大。
- 独立性:进程是独立运行的,拥有独立的系统资源,包括内存、CPU时间、磁盘空间等。而线程只是进程的一个执行路径,共享进程的资源,因此线程之间没有独立的地址空间,一个线程死掉就等于整个进程死掉。
- 系统开销:由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、I/O设备等,所付出的开销远大于创建或撤销线程时的开销。同样,在进行进程切换时,涉及当前执行进程CPU环境的保存、新调度进程CPU环境的设置、各种进程资源状态的更改(如内存管理中的数据段、堆栈段和指针的更改)等,而线程切换只需保存和设置少量寄存器内容,不涉及存储管理等方面的操作。
总结来说,进程和线程在资源占用、并发性、独立性和系统开销等方面都存在显著的区别。进程是资源分配的基本单位,而线程是CPU调度的基本单位。进程拥有独立的地址空间和资源,而线程共享进程的资源。在并发性和系统开销方面,线程较进程具有更高的效率和更低的开销。
18.浏览器渲染进程有哪些线程
浏览器的渲染进程主要包含五种线程:
- GUI渲染线程:这个线程负责渲染浏览器页面,解析HTML、CSS,构建DOM树、CSSOM树、渲染树,以及绘制页面。当界面需要重绘或由于某种操作引发回流时,该线程就会执行。值得注意的是,GUI渲染线程和JS引擎线程是互斥的,当JS引擎执行时,GUI线程会被挂起,GUI更新会被保存在一个队列中,等待JS引擎空闲时立即执行。
- JS引擎线程:也称为JS内核,这个线程负责处理Javascript脚本程序,解析Javascript脚本,并运行代码。JS引擎线程一直在等待任务队列中任务的到来,然后进行处理。在一个Tab页中,无论什么时候都只有一个JS引擎线程在运行JS程序。
- 定时器线程:浏览器定时器(如setTimeout、setInterval)内部的实现就是由这个线程来控制的。当定时器的时间到达时,会将回调任务推送到任务队列中等待JS引擎线程执行。
- 事件触发线程:当一个事件被触发时,例如用户点击了一个按钮,这个线程就会将这个事件添加到待处理事件队列的尾部,等待JS引擎线程的处理。
- 异步http请求线程:在XMLHttpRequest在连接后(包括请求发出和请求完成),是由这个线程来通知事件触发线程,然后事件触发线程将回调函数添加到待处理事件队列中,等待JS引擎线程的执行。
这些线程协同工作,确保浏览器的渲染进程能够高效、准确地处理各种任务和事件。
19.web安全攻击方式及防御方法
1、SQL注入
SQL注入是一种常见的Web应用安全漏洞,攻击者通过在Web应用的输入参数中注入恶意的SQL代码,从而执行未经授权的数据库操作。这种类型的攻击允许攻击者访问,删除或修改数据库中的数据。
防御方法:使用参数化查询、输入验证和限制数据库权限等方法来防止SQL注入攻击。移除或转义特殊字符,如单引号等,防止恶意SQL代码的执行。为数据库用户分配最小必要的权限,以减少攻击者能够利用SQL注入漏洞对数据库进行的操作。使用ORM(对象关系映射)框架可以减少直接操作数据库的需求,并且ORM通常有内置的参数化查询等安全特性。定期进行安全审计和漏洞扫描,以及对Web应用程序进行安全测试,确保及时发现和修复潜在的SQL注入漏洞。
2、跨站脚本攻击 (XSS)
是一种常见的网络安全漏洞,攻击者通过在网页上注入恶意脚本,以获取用户的敏感信息或劫持用户的会话。XSS攻击通常分为存储型XSS、反射型XSS和DOM型XSS。
防御方法:对用户输入的数据进行严格的验证和过滤,移除或转义潜在的恶意脚本。在把用户输入的数据输出到网页时,进行适当的编码,以防止恶意脚本的执行。通过设置CSP(Content Security Policy) HTTP头部,限制网页可以加载的资源和执行的脚本,防止XSS攻击。选择使用经过安全审计和有良好安全记录的框架和库,以减少XSS攻击的风险。对敏感信息进行加密存储和传输,防止泄露。
3、跨站请求伪造 (CSRF)
攻击者利用受害者在已登录的情况下身份验证的权限,对受害者进行操作。攻击者通过伪装的请求来执行未经授权的操作,比如修改密码、发送电子邮件或进行资金转账等。
防御方法:使用CSRF令牌,验证referer头部信息,将CSRF令牌存储在Cookie中,并同时将该令牌作为参数发送给服务器。服务器将比较这两个值是否匹配,从而验证请求的合法性。在每个请求中添加一个随机或不可预测的参数,攻击者无法获得该参数的值,因此无法伪造有效请求。通过使用CSP,可以帮助防止恶意脚本的注入和执行,从而减少CSRF攻击的风险。
4、未经授权的访问
可能导致未经授权的个人或实体获取敏感信息、系统功能或资源。
防御方法:加强身份认证,实施访问控制和权限管理,强化密码策略,强化操作系统和应用程序安全。定期对系统进行审计和监控,以及实时监控系统日志,以检测异常操作和未经授权的访问尝试。使用网络防火墙来限制流量,阻止未经授权的访问,并使用IDS来检测和响应来自未经授权用户的攻击。
5、重定向攻击
这种在一些钓鱼网站中经常见到,一般会发送给用户一个合法链接,这个链接被用户点击的时候,导向进入一个非法网站,从而达到骗取用户信任、窃取用户资料的目的。
避免攻击:一般来说我们需要审核重定向的网址,通过加入黑白名单的方式监控。
6、文件上传漏洞
恶意用户通过应用程序的文件上传功能,将恶意文件(如病毒、木马、恶意脚本等)上传到服务器上,从而导致网站安全漏洞和潜在的安全威胁。
防御方法:严格限制上传文件类型和大小,对上传的文件进行合理的检查和过滤,设定合理的文件权限。在服务器端对上传的文件进行扩展名检查,以确保上传的文件扩展名与其真实类型一致,防止对文件伪装的攻击。使用安全的文件内容检测工具,对上传的文件进行扫描和检测,以确保文件不包含恶意代码。如果发现恶意代码,立即将文件视为不安全并予以阻止或删除。
7、目录遍历攻击
通过输入恶意构造的文件路径来获取未经授权的文件或目录访问权限。
防御方法:限制用户访问权限,严格控制访问文件路径,过滤用户输入的目录遍历字符。对URL进行编码处理,以防止用户输入中包含恶意路径分隔符,从而避免目录遍历攻击。确保关闭不必要的文件和目录访问权限,避免出现目录遍历漏洞。
8、代码执行漏洞
应用程序在处理输入时未正确进行过滤和验证,导致恶意用户能够向应用程序提交恶意代码,从而在服务器上执行任意指令。这种漏洞很容易被黑客利用,造成严重的安全风险。
防御方法:将应用程序运行在沙盒环境中,对用户输入进行严格过滤和验证,限制用户的执行权限,定期对代码进行安全审计。
9、点击劫持攻击
攻击者创建一个透明的图层,并在上面放置一个看似吸引人的元素,例如按钮、链接或表单,然后诱使用户在不知情的情况下点击这个看似无害的元素,实际上用户的点击被重定向到攻击者想要的网页或执行特定的操作。点击劫持攻击可能导致用户执行意外的操作,例如在未经许可的情况下购买商品或泄露个人敏感信息。
防御方法:使用X-Frame-Options头部,限制网页被嵌套,并提示用户外部引用。在网页上增加一层透明的DIV,并检查用户点击的位置是否在预期范围内。在编写网页时,需要对用户的操作做合适的限制和验证,确保用户的点击不会被误导到其他页面或执行危险的操作。
10、cookie攻击
主要是利用JavaScript能够在当前域名下获取网站cookie的特性来攻击(javascript:alert(doucment.cookie)),一般来说可以配合XSS和CSRF来进行攻击,
避免攻击:现在主流浏览器都支持在cookie上加上HttpOnly的属性,这样cookie就无法通过Java Script来取得,如果能在关键cookie上打上这个标记,对cookie的安全性的提高有很大作用。
11、DOS攻击
拒绝服务攻击(denial-of-service attack, DoS)亦称洪水攻击,这也是网络安全领域不得不提到的一个攻击,主要攻击方式为不断的向目标服务器进行强烈多次的攻击,这种攻击及其消耗服务器的带宽和资源,最终使得服务器资源耗尽而崩塌。
避免攻击:这种攻击一般可以通过一些防火墙策略和报警机制来解决,同时配上人为监控。简单的讲可以对访问过多的IP进行封禁。深入一点讲,可以做一些流量清洗方案。采用抗 DDoS 软件,将正常流量和恶意流量区分开。
20.浏览器存储数据方式有哪些
浏览器存储是指浏览器在本地计算机上保存数据的方式,以便在用户访问网站时能够更快地加载内容,提供更好的用户体验。浏览器存储主要有以下几种方式:
- Cookie:Cookie是一种小型的文本文件,存储在客户端的浏览器中。它主要用于存储用户的身份认证、会话状态等信息。Cookie的大小通常受到浏览器和服务器的限制,一般不超过4KB。每次向同一个域名下发送请求时,都会携带相同的Cookie,这样服务器就能识别客户端的身份信息。然而,由于Cookie的大小限制,它只能用来存储少量的信息。
- Web Storage:Web Storage是HTML5引入的一种新的存储方式,主要包括Local Storage和Session Storage两种类型。
- Local Storage:这种存储方式类似于电脑或手机上的下载功能,可以永久保存数据。除非用户主动删除,否则数据会一直存在。
- Session Storage:与Local Storage不同,Session Storage只在当前会话下有效。当页面关闭时,存储的数据就会被删除。这种方式常用于存储一些临时性的信息,如网页微博之类的密码保存。
- IndexedDB:IndexedDB是一种浏览器本地数据库,可以在客户端浏览器中存储大量的结构化数据。它支持事务操作、索引查询等功能,存储空间相对较大,通常限制为几百MB到几GB。与Web Storage相比,IndexedDB的存储方式更为复杂,但提供了更强大的数据操作能力。
总的来说,浏览器存储提供了多种方式来保存数据,以便在用户访问网站时提供更好的体验。不同的存储方式有各自的特点和适用场景,开发者可以根据实际需求选择适合的存储方式。
21.如何实现浏览器内多个标签页之间的通信
在浏览器中实现多个标签页之间的通信通常涉及几种不同的技术。以下是一些常见的方法:
-
使用localStorage事件 :
localStorage
API 提供了在多个标签页之间共享数据的能力,并且通过监听storage
事件,一个标签页中的更改可以通知到其他标签页。javascript// 在一个标签页中设置localStorage localStorage.setItem('key', 'value'); // 在另一个标签页中监听storage事件 window.addEventListener('storage', function(event) { if (event.key === 'key') { console.log('Value changed to:', event.newValue); } });
需要注意的是,
storage
事件只会在其他标签页(或窗口)修改localStorage
时触发,而且不会在当前触发修改的标签页中触发。 -
使用BroadcastChannel API :
BroadcastChannel
API 提供了一种简单的方式来在浏览器中的不同上下文(如标签页、iframe 或 worker)之间发送和接收消息。csharp// 创建一个新的BroadcastChannel实例 const bc = new BroadcastChannel('my-channel'); // 发送消息 bc.postMessage('Hello, world!'); // 接收消息 bc.onmessage = event => { console.log('Received', event.data); };
每个标签页都需要使用相同的频道名称来创建
BroadcastChannel
实例,然后它们就可以相互发送和接收消息了。 -
使用Service Workers: Service Workers 是一种在浏览器后台独立于网页运行的脚本,它们可以用来接收推送通知、管理缓存等。Service Workers 可以作为多个标签页之间的通信中介。
javascript// 注册Service Worker navigator.serviceWorker.register('/service-worker.js').then(function(registration) { console.log('Service Worker Registered'); }).catch(function(err) { console.log('Service Worker Registration Failed: ', err); }); // 在Service Worker中发送消息 self.clients.matchAll().then(function(clients) { clients.forEach(function(client) { client.postMessage('Hello from Service Worker!'); }); }); // 在页面中接收消息 navigator.serviceWorker.onmessage = function(event) { console.log('Received message from Service Worker:', event.data); };
通过 Service Workers,你可以发送消息到所有关联的标签页,或者只发送到特定的标签页。
-
使用SharedArrayBuffer和Atomics: 这些API使得在Web Workers之间共享内存成为可能,这对于需要进行高性能计算或并行处理的应用来说是非常有用的。然而,这通常用于Web Workers之间的通信,而不是直接用于标签页之间的通信。但你可以通过Service Workers或其他中介来桥接标签页和Web Workers。
-
使用WebSocket或Server-Sent Events: 这些技术涉及与服务器建立长连接,并通过服务器来中转消息。虽然这不是直接的标签页间通信,但它允许跨多个浏览器实例和设备的通信。
选择哪种方法取决于你的具体需求,比如通信的复杂性、消息的大小、是否需要跨浏览器实例通信等。在大多数情况下,BroadcastChannel
或 localStorage
事件可能就已经足够满足简单的标签页间通信需求了。
22.tcp和udp的区别
TCP(传输控制协议)和UDP(用户数据报协议)都是传输层协议,但它们之间存在明显的区别。以下是TCP和UDP之间的主要差异:
- 连接与无连接:TCP是面向连接的协议,它在数据发送之前需要首先建立连接,这通常通过三次握手来实现。连接建立后,数据可以在连接上进行可靠的传输。而UDP则是无连接的协议,它不需要建立连接,每个数据报都是独立的,因此它被称为"面向数据报"的协议。
- 可靠性:TCP提供了可靠的数据传输服务。它使用序列号、确认和重传机制来确保数据包的顺序和完整性。如果数据包在传输过程中丢失或损坏,TCP会负责重新发送这些数据包。相比之下,UDP不保证数据包的可靠传输。它不会检查数据包是否已经到达,也不会确认数据包是否按序到达。因此,UDP可能会出现丢包或乱序的情况。
- 效率:由于UDP是无连接的,并且没有复杂的控制机制,因此它在处理数据时通常比TCP更高效。UDP的头部开销也较小,适用于对实时性要求较高的应用,如视频流、实时游戏等。而TCP由于需要建立连接并进行复杂的控制,所以在处理数据时可能会产生较大的延迟。
- 流量控制:TCP具有流量控制功能,可以根据接收方的处理能力来发送数据,避免发送方发送速度过快导致接收方无法处理。而UDP没有流量控制功能,发送方可能会以超过接收方处理能力的速度发送数据,导致数据丢失。
- 应用场景:TCP通常用于需要可靠传输的场景,如文件传输、电子邮件等。而UDP则适用于对实时性要求较高、对丢包容忍度较高的场景,如视频直播、在线游戏等。
总的来说,TCP和UDP各有其优缺点,适用于不同的应用场景。在选择使用哪种协议时,需要根据具体需求进行权衡。
23.简述tcp三次握手和4次挥手的过程
TCP(传输控制协议)的三次握手和四次挥手是TCP建立连接和释放连接的重要过程。
三次握手过程:
- 客户端发送SYN包到服务器:客户端首先向服务器发送一个SYN包,这个包中包含客户端的初始序列号。这个步骤的目的是客户端向服务器请求建立连接。
- 服务器发送SYN+ACK包到客户端:服务器在收到客户端的SYN包后,会发送一个SYN+ACK包作为响应。这个包中包含了服务器的初始序列号,并对客户端的SYN进行确认。
- 客户端发送ACK包到服务器:客户端收到服务器的SYN+ACK包后,会发送一个ACK包作为最后的确认。这个ACK包中包含了对服务器SYN的确认。
通过这三次握手,客户端和服务器就成功地建立了一个TCP连接,可以进行数据的传输。
四次挥手过程:
- 客户端发送FIN包到服务器:当客户端想要关闭连接时,会首先发送一个FIN包给服务器,表示客户端已经完成了数据的发送,并希望关闭连接。
- 服务器发送ACK包到客户端:服务器收到客户端的FIN包后,会发送一个ACK包作为确认。此时,连接处于半关闭状态,即客户端不再发送数据,但服务器仍可以发送数据。
- 服务器发送FIN包到客户端:当服务器也完成了数据的发送,并希望关闭连接时,会发送一个FIN包给客户端。
- 客户端发送ACK包到服务器:客户端收到服务器的FIN包后,会发送一个ACK包作为最后的确认。至此,TCP连接被完全关闭。
需要注意的是,在四次挥手的过程中,客户端和服务器都有可能先发起关闭请求,而且为了确保数据能够可靠地传输,某些步骤中还会涉及到等待时间(如TIME-WAIT状态)的设置。
总结来说,TCP的三次握手和四次挥手过程确保了TCP连接的建立和释放的可靠性,为数据的传输提供了坚实的基础。
24.tcp/ip协议包含哪几层
TCP/IP协议族是一个网络通信模型,它包含了四层结构,从低到高依次为:网络接口层、网络层、传输层和应用层。这四层的功能和组成部分如下:
- 网络接口层:有时也称数据链路层或链路层,通常包括操作系统中的设备驱动程序和计算机中对应的网络接口卡。它们一起处理与电缆(或其他任何传输媒介)的物理接口细节。网络接口层为数据端点提供数据传送的通道,数据端点可以是网络适配器(网卡)或其他的物理设备端口。
- 网络层:有时也称互联网层,处理分组在网络中的活动,例如分组的选路。在TCP/IP协议族中,网络层协议包括IP(网际协议)、ICMP(Internet互联网控制消息协议)、IGMP(Internet组管理协议)以及ARP(地址解析协议)。
- 传输层:主要为两台主机上的应用程序提供端到端的通信。在TCP/IP协议族中,有两个互不相同的传输协议:TCP(传输控制协议)和UDP(用户数据报协议)。TCP为两台主机提供高可靠性的数据通信。它所做的工作包括把应用程序交给它的数据分成合适的小块交给下面的网络层,确认接收到的分组,设置发送最后确认分组的超时时钟等。由于运输层提供了高可靠性的端到端的通信,因此应用层可以忽略所有这些细节。而另一方面,UDP则为应用层提供一种非常简单的服务。它只是把称作数据报的分组从一台主机发送到另一台主机,但并不保证该数据报能到达另一端。任何必需的可靠性必须由应用层来提供。
- 应用层:负责处理特定的应用程序细节。几乎各种不同的TCP/IP实现都会提供下面这些通用的应用程序:Telnet远程登录、FTP文件传输协议、SMTP简单邮件传送协议、SNMP简单网络管理协议和DNS域名系统。
这四层结构共同构成了TCP/IP协议族的基础,使得不同的计算机和网络设备能够进行通信和数据传输。
另外作者也在找工作,欢迎公司有HC的同学内推,base地:深圳、广州或长沙。