☰
前端面试八股文别当背诵材料:从HTTP到BFC的排查手册
2026/10/14 6:40:40 网站建设 项目流程

简介:这是一份系统性整理的前端面试知识点汇总,主要面向前端初学者、求职者以及希望巩固基础的一线研发人员。内容围绕核心高频考点展开,包括HTTP与HTTPS的区别及工作原理、TCP三次握手与四次挥手、粘包问题、缓存机制、页面加载全过程,并逐一解析DOM操作、CSS盒模型、BFC、浮动布局,以及Flex、Rem、百分比等布局方式的适用场景。资料以单个PDF文件提供,压缩包约1020KB,内容精炼,便于快速浏览和反复查阅。目前已有680人学习下载,适合自学复习,也适合团队内部培训使用。整体结构清晰,重点突出,既便于考前冲刺,也可作为日常开发参考;通过原理讲解与要点归纳,读者能理解常见问题背后的网络与渲染机制,补全前端知识体系,提升面试应答和实际开发中的排错与优化能力。

1. 前端面试八股文:别当背诵材料,当排查手册用

这份前端面试八股文的知识点汇总,覆盖面和一般面试题不同:它没把重心放在框架API背诵上,而是用了大量篇幅讲HTTP/HTTPS、TCP三次握手与四次挥手、浏览器缓存、重排重绘、跨域方案、粘包治理,以及盒模型与BFC这些底层基础。我拆完这份资料最大的感受是,它更像一份“线上问题排查索引”——页面加载慢、接口跨域、样式错位、请求缓存不生效,都能在对应章节里直接找到答案。适合两类人:一类是准备面试、需要系统过一遍底层的初学者;另一类是工作了两三年、发现自己对网络协议和浏览器原理回答得不够严谨的熟手。下面按我自己的阅读顺序拆开讲。

2. 网络协议三座山:HTTP/HTTPS、TCP握手挥手与可靠性细节

2.1 HTTP 与 HTTPS:加密通道、默认端口与握手六步

先说基本概念。HTTP是一个客户端和服务器端请求和应答的标准(基于TCP),用于从WWW服务器传输超文本到本地浏览器的超文本传输协议。HTTPS是以安全为目标的HTTP通道,也就是HTTP下加入SSL层进行加密。它解决两个问题:一是建立一个信息安全通道,确保数据在传输过程中不被窃取和改变;二是确保网站的真实性。这个“网站真实性”对应的是CA证书体系,后面会讲到。

面试最常问的区别,资料整理得比较完整,我按参数表重新梳理了一遍:

对比项HTTPHTTPS
传输方式明文传输SSL加密传输,防止数据被窃取、改变,确保完整性
默认端口80443
连接特点简单、无状态握手阶段费时,页面加载时间延长约50%,增加10%~20%耗电
缓存效率缓存高效缓存不如HTTP高效,增加数据开销
证书不需要需要CA证书,功能越强费用越高
IP绑定无限制SSL证书需绑定IP,同一IP不能绑定多个域名,IPv4资源难以支撑

需要注意安全性描述的边界。资料原文写得很克制:这种安全性并非绝对的,更深层的Web安全问题暂且不表。我理解是HTTPS保证传输链路上的机密性和完整性,但业务层的XSS、注入这类问题不在它保护范围内。面试时主动说出这个边界,比单纯背一句“HTTPS更安全”得分高很多。

HTTPS的工作原理,原文拆成了六个步骤,我按客户端视角整理成可复述的顺序:

  1. 客户端使用HTTPS URL访问服务器,要求Web服务器建立SSL链接。
  2. Web服务器收到请求后,将网站证书(证书中包含公钥)传输给客户端。
  3. 客户端和Web服务器协商SSL链接的安全等级,也就是加密等级。
  4. 客户端根据双方协商一致的安全等级建立会话密钥,用网站公钥加密会话密钥,并传送给服务器。
  5. Web服务器通过自己的私钥解密出会话密钥。
  6. Web服务器通过会话密钥加密与客户端之间的通信。

这个流程的记忆点是四个关键词:证书(含公钥)、协商加密等级、会话密钥、私钥解密。面试官往下追问“为什么用公钥加密会话密钥,而不是直接用公钥传数据”时,常见做法是回答对称加密性能好、非对称加密解决密钥分发问题,所以先用非对称交换会话密钥,后续通信用对称加密,效率和安全性兼顾。这是这份资料没写、但属于这个场景下最标准的技术延伸。

2.2 TCP 三次握手与四次挥手:状态机与序号规则

三次握手是前端面试网络部分几乎必考的题。原文把过程和状态写得很细,我重新整理成可记忆的节奏:

第一次握手:客户端发送SYN包(syn=j)到服务器,进入SYN_SENT状态,等待服务器确认。SYN全称是Synchronize Sequence Numbers,同步序列编号。

第二次握手:服务器收到SYN包,确认客户的ACK(ack=j+1),同时发送自己的SYN包(syn=k),也就是SYN+ACK包,此时服务器进入SYN_RECV状态。

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1)。此包发送完毕,客户端和服务器都进入ESTABLISHED状态,TCP连接成功。

有一个关键细节资料特意强调了:握手过程中传送的包里不包含数据,三次握手完毕后客户端与服务器才正式开始传送数据。很多面试者把第三次握手答成“顺便把HTTP请求带过去了”,这是对“第三次握手之后紧接着发HTTP请求”的误解,我在避坑章节再展开。

四次挥手的细节比三次握手多。原文用六步描述(把撤销TCB的步骤单独拆出来了),我按状态流转整理成表格:

步骤发送方动作发送方状态接收方状态关键字段
第一次客户端发连接释放报文,停止发送数据FIN-WAIT-1CLOSE-WAITFIN=1, seq=u
第二次服务器发确认报文FIN-WAIT-2CLOSE-WAITACK=1, ack=u+1, seq=v
第三次服务器发完最后数据后发连接释放报文FIN-WAIT-2LAST-ACKFIN=1, seq=w
第四次客户端发确认报文,进入TIME-WAITTIME-WAITCLOSEDACK=1, ack=w+1

这里有个容易忽略的知识点:TCP规定,FIN报文段即使不携带数据也要消耗一个序号。这就是为什么释放连接时客户端序号是u而不是更小的值——FIN自己占了一个序号位。后半段同样重要:客户端要经过2*MSL(最长报文段寿命)时间,撤销TCB后才进入CLOSED状态;服务器只要收到客户端确认,立即进入CLOSED状态。所以服务器结束TCP连接的时间比客户端早。

面试追问“为什么TIME-WAIT要等2MSL”的标准答法是:一是保证最后一个ACK能到达对方,如果ACK丢失,对方会重发FIN,客户端还有时间再确认一次;二是防止旧连接中的报文段出现在新连接里。这两个理由在实战排错里也有对应——服务端大量TIME-WAIT连接堆积时,调整的是MSL相关参数,而不是盲目缩短超时。

2.3 TCP 可靠传输:ACK、超时重传与CRC校验

TCP/IP保证数据包传输有序可靠的核心机制,原文总结为一句话:对字节流分段并编号,然后通过ACK回复和超时重发两个机制来保证。展开是四个动作,我按发送方和接收方分开记:

发送方侧:已发送的数据包必须保留在缓冲区;为每个已发送的数据包启动一个超时定时器;如果在定时器超时之前收到对方的应答信息(可能是对本包的应答,也可以是对本包后续包的应答),就释放该数据包占用的缓冲区;否则重传该数据包,直到收到应答或重传次数超过规定的最大次数。

接收方侧:收到数据包后先做CRC校验,如果正确则把数据交给上层协议,然后给发送方发送一个累计应答包,表明该数据已收到。如果接收方正好也有数据要发给发送方,应答包可以捎带在数据包中一起过去。

面试时值得主动补充的一点是“累计应答”的含义:接收方回复ack=某个序号,表示该序号之前的所有字节都收到了,不需要对每个包单独确认。这是TCP在可靠性和传输效率之间做的关键权衡。线上排查一个常见问题是“为什么TCP重传这么多”,排查路径一般从三个方向走:确认是否触发快速重传、看接收窗口是否为零、查中间链路是否存在丢包。这些属于资料之外的实战延伸,但答案都建立在ACK和超时重传这两个机制之上。

2.4 再问TCP与UDP:无连接、多播与头部开销

TCP和UDP的区别是一道对照题,资料给的维度比较全:

对比维度TCPUDP
连接面向连接,需三次握手面向无连接
传输方式仅支持单播支持单播、多播、广播
可靠性三次握手、ACK、超时重传保证可靠无连接、不可靠,不发送确认信号,发送端不知道数据是否正确接收
头部开销较大更小
速率/实时性相对较低数据传输速率更高,实时性更好

实际选型我习惯用一句话总结:TCP用来传文件、HTTP这类不能丢的数据;UDP用来传视频流、游戏帧这种丢一点能接受但延迟必须低的实时数据。面试时说完表格内容,再用这句话收尾,基本就闭环了。再被追问“HTTP/3为什么改用QUIC”,回答方向就往UDP的低延迟和连接迁移特性上靠,同时补一句QUIC在应用层自己实现了可靠性和拥塞控制——这个知识资料里没写,但属于现在网络题的高频延伸点。

3. 浏览器从URL到渲染:DNS、缓存、重排重绘的完整链路

3.1 URL输入后的九步:从DNS解析到页面绘制

资料把“浏览器从输入URL到页面加载”拆成了十几个动作,我压缩成九步,方便面试时按顺序复述:

  1. 浏览器输入URL。
  2. 查找缓存:浏览器缓存、系统缓存、路由缓存,命中则显示页面内容。
  3. DNS域名解析:浏览器向DNS服务器发起请求,解析域名对应的IP地址。DNS服务器基于UDP,所以会用到UDP协议。
  4. 建立TCP连接:解析出IP地址后,根据IP和默认80端口与服务器建立TCP连接。
  5. 发起HTTP请求:浏览器发起读取文件的HTTP请求。
  6. 服务器响应请求并返回结果:把对应的HTML文件发送给浏览器。
  7. 关闭TCP连接:通过四次挥手释放。
  8. 浏览器解析HTML并渲染:词法分析后解析成DOM树,生成CSS规则树,Web浏览器将DOM和CSSOM结合构建渲染树,布局计算每个节点在屏幕中的位置,最后遍历渲染树用UI后端层绘制每个节点。
  9. JS引擎解析执行:JS的解释、预处理、执行阶段生成执行上下文、VO、作用域链、回收机制。

DNS缓存层级值得单独背:浏览器缓存会记录DNS一段时间,所以最先查;浏览器缓存没有记录,系统调用操作系统获取DNS记录;再不行找路由器缓存;都失败才向ISP搜索。答“DNS解析过程”时把这四个层级按顺序报出来,信息量比一句“DNS服务器解析”完整得多。

第9步JS引擎解析有一个易错点:预编译阶段浏览器会寻找全局变量声明,作为window的属性加入并赋值为undefined;寻找全局函数声明,作为window的方法加入并赋值为函数体。匿名函数不参与预编译,因为它是变量。变量提升的“不合理”在ES6里用let/const解决了,但函数提升仍然存在。这句话可以作为“变量提升”题的标准收尾。

3.2 强制缓存与协商缓存:缓存标识怎么定优先级

浏览器与服务器的通信是应答模式:浏览器发起HTTP请求,服务器响应该请求。第一次请求后,浏览器根据响应报文HTTP头的缓存标识决定是否缓存结果,是则将请求结果和缓存标识存入浏览器缓存。两条基础结论:浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果和缓存标识;浏览器每次拿到返回结果,都会将结果和缓存标识存入浏览器缓存。

强制缓存就是向浏览器缓存查找请求结果,并根据缓存规则决定是否使用缓存结果的过程。控制强制缓存的字段是Expires和Cache-Control,Cache-Control优先级比Expires高。Expires受限于本地时间,用户改了本地时间就可能失效;Cache-Control的max-age指定最大生命周期,相对可控。强制缓存命中的三种情况:

  1. 不存在缓存结果和缓存标识,强制缓存失效,直接向服务器发起请求,和第一次请求一致。
  2. 存在缓存结果和缓存标识,但结果已失效,强制缓存失效,进入协商缓存。
  3. 存在缓存结果和缓存标识,结果尚未失效,强制缓存生效,直接返回该结果。这时状态码仍然返回200,但不会请求数据,浏览器里能看到from cache字样。

协商缓存是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。控制字段是Last-Modified/If-Modified-Since和ETag/If-None-Match,其中ETag优先级比Last-Modified高。协商缓存生效返回304,失效返回200和请求结果。

我按这个顺序回答“304是怎么产生的”:

  1. 浏览器请求资源,先看Expires和Cache-Control,强缓存未失效直接用本地缓存。
  2. 强缓存失效,进入协商缓存,先验证ETag。服务器根据请求头If-None-Match判断资源是否变化,未变化命中缓存。
  3. ETag没命中或没有ETag,进入Last-Modified/If-Modified-Since阶段:第一次请求时服务端返回Last-Modified时间,再次请求时请求头带If-Modified-Since,服务器根据资源最后修改时间判断是否命中。
  4. 命中返回304,未命中返回200和完整请求结果。

3.3 重排与重绘:触发条件、性能代价与合成层

重排(回流,Reflow)是指DOM变化影响了元素的几何信息,浏览器需要重新计算元素的几何属性,将其安放在界面中的正确位置,表现为重新生成布局、重新排列元素。重绘(Repaint)是指元素外观改变但没有改变布局,重新把外观绘制出来。两者关系口诀:重绘不一定会重排,重排必然会出现重绘。重排性能影响更大,无法避免时宁可选择代价更小的重绘。

触发条件资料列得很全,我按类别整理:

  • 结构变化:添加、删除、更新DOM节点。
  • 显隐切换:display:none隐藏节点,触发重排和重绘;visibility:hidden隐藏节点,只触发重绘,没有几何变化。
  • 位置动画:移动或给DOM节点添加动画。
  • 样式变更:添加样式表、调整样式属性。
  • 用户行为:调整窗口大小、改变字号、滚动。

避免重排的常见手段,按资料顺序记七条:集中改变样式,不要一条一条修改DOM样式;不要把DOM节点属性值放在循环里当成循环变量;动画元素用fixed或absolute定位,修改它们的CSS不会reflow;不用table布局,因为很小的改动可能造成整个table重新布局;尽量只修改position为absolute或fixed的元素,对其他元素影响不大;动画开始加速,使用GPU变化、translate 3D;把元素提升为合成层。

合成层是性能优化里比较关键的概念:合成层的位图会交由GPU合成,比CPU处理快;当需要repaint时只repaint本身,不会影响其他层;transform和opacity效果不会触发layout和paint。提升合成层的最好方式是CSS的will-change属性。这个知识点是“重排重绘”延伸到项目实战的桥,面试官听到will-change基本会认定你有真实性能优化经验,而不是只在背概念。

3.4 进程、线程与协程:并发模型的概念辨析

资料把三者的定义写得很标准:

进程是具有一定独立功能的程序在一个数据集上的一次动态执行过程,是操作系统进行资源分配和调度的独立单位,是应用程序运行的载体。线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。一个进程可以有一个或多个线程,线程之间共享程序的内存空间。协程是建立在线程之上、比线程更轻量级的存在,由程序员自己写程序来管理,被称为“用户空间线程”,对内核不可见。

进程和线程的区别,四个维度:

  • 调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位。
  • 并发性:进程之间可以并发执行,同一进程的多个线程也可并发执行。
  • 拥有资源:进程是拥有资源的独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源。
  • 系统开销:创建或撤销进程时系统要分配回收资源,开销明显大于线程。但进程有独立地址空间,一个进程崩溃在保护模式下不会影响其他进程;线程没有单独地址空间,一个进程死掉等于所有线程死掉。多进程比多线程健壮,但进程切换耗费资源较大,效率差一些。

联系部分资料也给得很完整:一个线程只能属于一个进程,一个进程可以有多个线程但至少有一个;资源分配给进程,同一进程的所有线程共享该进程的所有资源;处理机分给线程,真正在处理机上运行的是线程。面试追问“JS为什么是单线程”时,标准思路是往浏览器DOM操作互斥和事件循环上引,这个资料里没有展开,属于浏览器原理章节的常见延伸。

3.5 HTML5语义化:标签选型与SEO权重

HTML5新特性里最核心的考点是语义化。语义化指的是合理正确地使用语义化标签来创建页面结构,资料的说法叫“正确的标签做正确的事”。语义化标签包括header、nav、main、article、section、aside、footer。

语义化的优点资料列了四点:没有CSS样式的情况下,页面整体也会呈现很好的结构效果;代码结构清晰,易于阅读,利于开发和维护;方便其他设备解析,比如屏幕阅读器可以根据语义渲染网页;有利于搜索引擎优化,搜索引擎爬虫会根据不同标签赋予不同权重。

我自己的回答习惯是补一个具体例子:导航用nav而不是div加class,爬虫和屏幕阅读器能直接识别页面导航区域;正文主体用main,侧栏用aside,文章内容用article。这个例子比单纯背标签列表更能体现工程上的理解。标签选型的边界也值得说一句:section和article的区别在于内容是否能独立成篇,能独立用article,只是一个区块用section。

4. 跨域与本地存储:JSONP、CORS、代理方案与存储边界

4.1 跨域方案演进:JSONP的局限到proxy代理

跨域的本质是浏览器的同源策略。资料的说法很清晰:浏览器不能执行其他网站的脚本,这是由浏览器的同源策略造成的安全限制。只要协议、域名、端口任何一个不同,都被当作不同的域。跨域方案做的事,就是用各种方式避开浏览器的安全限制。

JSONP是最早接触的方案,原理是:ajax请求受同源策略影响不允许跨域请求,但script标签src属性里的链接可以访问跨域的js脚本。利用这个特性,服务端不返回JSON格式的数据,而是返回一段调用某个函数的js代码,在src中调用,从而实现跨域。

JSONP的操作流程四步:

  1. 创建一个script标签。
  2. script的src属性设置接口地址。
  3. 接口参数必须带一个自定义函数名,否则后台无法返回数据。
  4. 通过定义函数名接收返回的数据。

JSONP的缺点资料明确写了:只支持get,因为script标签只能使用get请求;需要后端配合返回指定格式的数据。资料还提到了document.domain(基础域名相同、子域名不同时用,把两个页面document.domain设为相同主域)和window.name(利用浏览器窗口内载入的所有域名共享一个window.name)两种方案,适用范围都比较有限。

现在项目里最常用的方案是代理。资料原话是:在开发中使用proxy,在服务器上使用nginx代理,这样开发过程中彼此都方便,效率也高。这个思路值得展开:开发时的webpack dev server proxy和线上的nginx代理是同一套跨域思路的两种落地——让服务端去请求目标接口,浏览器只和本域通信,自然不存在跨域。CORS是最标准的后端支持方案,原理是服务器设置Access-Control-Allow-Origin响应头之后,浏览器允许跨域请求。H5新特性window.postMessage()解决的是窗口间通信场景,iframe跨域和多窗口数据传递都能用。

四类方案的优先级,我的选择逻辑是:能用CORS用CORS,因为它标准、支持POST、支持携带凭证;项目工程链路用proxy,开发和线上都不用改前端代码;老接口临时救急用JSONP,前提是GET且后端愿意配合回调格式;窗口通信用postMessage。这个优先级在实际项目里经过验证,比单纯记概念可靠。

4.2 Cookie、sessionStorage、localStorage:容量与生命周期

三者相同点是都存储在客户端,区别资料给得很清楚:

对比项CookiesessionStoragelocalStorage
容量不能超过4k比cookie大得多,可达5M+同sessionStorage
生命周期设置的过期时间之前一直有效当前浏览器窗口关闭后自动删除永久存储,浏览器关闭后不丢失,除非主动删除
传输行为数据自动传递到服务器数据保存在本地,不传服务器数据保存在本地,不传服务器

工作中最容易混淆的是sessionStorage和localStorage的使用场景。我一般按这个标准选:临时表单数据、页面间传一次性状态用sessionStorage,窗口关了就该清掉;用户偏好、长期登录态这类需要跨会话保留的数据用localStorage。Cookie的定位是“给服务器用的”——只要数据需要随每个请求自动发给后端,才放Cookie;否则优先用后两者,能省请求头体积。还有个容易被忽略的点:Cookie容量4k的限制和请求头携带的开销,是很多团队最终把登录态迁移到localStorage加自定义请求头的动力,但迁移时要考虑XSS风险,这是另一个层面的安全问题。

4.3 TCP粘包:成因、三种对策与残余风险

TCP粘包指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接前一包数据的尾。出现原因很简单:TCP是流传输,没有消息边界;UDP不会出现粘包,因为它有消息边界。粘包有两种情况:粘在一起的包都是完整的数据包,或者粘在一起的包里有不完整的包。

资料给了三种对策,同时也指出了各自的不足:

  1. 发送方强制发送:TCP提供强制数据立即传送的push操作指令,发送方收到指令后立即将本段数据发出去,不必等发送缓冲区满。代价是关闭了优化算法,降低网络发送效率,影响应用性能,一般不建议使用。
  2. 接收方优化:精简接收进程工作量、提高接收进程优先级,使其及时接收数据。只能减少粘包出现的可能性,发送频率较高或网络突发时,接收方仍可能来不及接收。
  3. 接收方按结构字段分多次接收再合并:人为控制按一包数据的结构字段分多次接收,然后合并。避免了粘包但应用效率低,不适合实时应用场景。

资料推荐的周全做法是:接收方创建预处理线程,对接收到的数据包进行预处理,将粘连的包分开,资料说实验证明这种方法高效可行。这个方案的前端相关场景一般是WebSocket或Node TCP服务。前端面试问粘包,考的就是“你是否理解TCP流式传输没有消息边界”这一点,答到“UDP不粘包是因为有消息边界”再补一句“应用层需要自己定义帧格式”就完整了。

5. 避坑清单:八股文背熟了还会翻车的五个细节

5.1 from cache 与 304 不是一回事

现象:面试问浏览器缓存命中怎么表现,有候选人回答“from cache就是返回304”。

原因:混淆了强缓存和协商缓存的阶段,把“没有走网络请求”和“服务器确认资源未变”当成同一个过程。

解决:from cache是强缓存命中,浏览器压根没发请求,Network面板里显示from memory cache或from disk cache;304是协商缓存命中,请求发出去了,服务器通过If-None-Match或If-Modified-Since判断资源没变,返回304且不带响应体。判断口径很简单:看请求有没有发出去。浏览器Cache-Control有效期内根本不会发请求,自然也不存在304的状态码。我把“from cache”和“304”当成两条独立的缓存链路记忆,就不会再混。

5.2 HTTPS安全成本的量化数字记不准

现象:回答HTTPS和HTTP区别时,能说出端口和证书,但问到“HTTPS多了哪些代价”就只说“慢一点”。

原因:没有记资料里给的量化数据,回答停留在定性描述层面。

解决:记两个数字:握手阶段比较费时,会使页面加载时间延长50%,增加10%~20%的耗电。再说两个定性项:缓存不如HTTP高效,增加数据开销;CA证书费用高且SSL证书绑定IP,同一IP上不能绑定多个域名,IPv4资源支持不了这样的IP消耗。数字一出口,回答的颗粒度立刻不一样。我一般会把“50%加载时间延长”放在第一个说,因为它是几个代价里唯一有具体数字的时间成本。

5.3 visibility:hidden 到底触发重排还是重绘

现象:把“隐藏元素”统一答成“重排加重绘”。

原因:没有区分不同隐藏方式对几何信息的影响。

解决:display:none不分配空间,触发重排和重绘;visibility:hidden保留空间,没有几何变化,只触发重绘。判定标准只看一点:有没有改变元素的几何信息。另外注意事件差异:visibility:hidden隐藏后不会触发已绑定的事件,opacity:0虽然视觉上隐藏但不会改变布局,点击该区域仍能触发click事件。这条在“隐藏元素的方法”和“重排重绘”两个章节同时能用上,属于串联考点。

5.4 JSONP 能跨域的代价:GET、回调、后端配合

现象:平时用axios用习惯了,回答JSONP时认为它可以发POST请求。

原因:没记住JSONP的原理是script标签加载,script只能发GET,没有请求体可以承载POST内容。

解决:跨域选型时先排除JSONP的POST可能性。GET且数据量小的轻量场景可以JSONP;要POST、要安全、要带文件,直接CORS或proxy。JSONP还有一个隐性坑是必须带自定义函数名参数,否则后台无法返回数据,且需要后端配合返回指定格式的js代码——接口不在自己手里时,沟通成本往往比换成CORS高得多。资料里的工程经验是开发用proxy、服务器用nginx代理,这是目前前后端协作效率最高的方式,应该优先记住这条。

5.5 三次握手的包能不能携带数据

现象:把“浏览器发起HTTP请求”说成“作为TCP三次握手的第三次数据发送给服务器”。

原因:把应用层请求和传输层握手混在一起。三次握手完成之后紧接着就是HTTP请求的发送,时间上紧密,容易被误认为同一个包。

解决:资料原文写得很明确:握手过程中传送的包里不包含数据,三次握手完毕后客户端与服务器才正式开始传送数据。第三次握手是客户端发出的ACK确认包,作用是确认双方同步完成,不是用来捎带HTTP请求的。附带记一个细节:FIN报文段即使不携带数据也要消耗一个序号。这两个知识点属于“协议报文的载荷边界”这一类,面试官追问“哪些包能带数据哪些不能”时,答案都在这里。

6. 从盒模型到BFC:一套能救急的CSS布局排查习惯

6.1 先确认box-sizing,再谈宽度计算

CSS盒模型包括margin、border、padding、content。标准盒模型(content-box)里width指content宽度,一个块的总宽度=width+margin+padding+border;IE盒模型(border-box)里width指content+padding+border的总和,总宽度=width+margin。

我在项目里遇到的“宽度对不上”问题,九成是全局样式里没统一box-sizing,两个盒模型混用,百分比计算差出几个像素,肉眼很难发现。排查布局问题的第一个动作,我习惯是确认目标容器是content-box还是border-box,再谈宽度计算。

6.2 BFC:三种布局问题的统一解法

BFC(Block Formatting Context)是块级格式化上下文,一个独立的渲染区域,规定了内部Box如何布局,这个区域的子元素不会影响外部元素。两个比较重要的规则:内部Box在垂直方向一个接一个放置;计算BFC高度时浮动元素也参与计算。

创建BFC的条件记六个:根元素HTML;float值不为none;position为absolute或fixed;display为inline-block、table-cell、table-caption;overflow值不为visible。使用场景对照:

布局问题BFC解法
相邻元素margin重叠让两个元素分属不同BFC,阻止margin合并
父元素高度塌陷父元素创建BFC,让浮动子元素参与高度计算
元素被浮动元素覆盖给被覆盖元素创建BFC,使其不与float box重叠
多列布局换行错位创建BFC避免宽度计算四舍五入导致自动换行

6.3 Flex速记表与居中方案

Flex容器属性记六个:flex-direction决定主轴方向,取值row、row-reverse、column、column-reverse;flex-wrap决定换行规则,取值nowrap、wrap、wrap-reverse;flex-flow是前两者的合并写法;justify-content决定水平主轴对齐方式;align-items决定竖直轴线方向对齐;align-content用于多根轴线对齐。项目属性重点记order(定义排列顺序,越小越靠前,默认0)和flex-grow(定义放大比例,有剩余空间时按比例分配)。

居中方案按场景选:

场景方案关键点
行内元素水平居中text-align:center作用在父容器上
定宽块级元素水平居中width + margin:0 auto前提是设置了宽度
未知宽度块级水平居中绝对定位 + transform:translateX(-50%)父级需要position:relative
单行文本垂直居中line-height等于容器高度只适合纯文字场景
通用水平垂直居中flex + margin:auto父级display:flex,子级margin:auto
表格样式居中display:table-cell + vertical-align:middle子级需为内联或table-cell元素

这三张表是我排查布局问题的固定顺序:先看盒模型,再判断BFC是否是根因,最后用Flex速记确认对齐参数。以前我遇到样式“玄学偏移”会这个属性调一下、那个属性改一下,浪费时间还经常改出新的问题。后来我强制自己走完这三步再动代码,发现大部分问题在第一步就暴露了——整个样式表里只改一处box-sizing,布局立刻恢复正常。从那以后每接手一个项目,第一步永远是拉开全局样式检查box-sizing,再去看flex参数。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询