前端知识点梳理,前端面试复习

一:从输入 URL 到页面渲染 是一个经典的综合性考题,而理解 URL(统一资源定位符) 的组成是这一切的起点

1.URL 的标准组成部分

一个完整的 URL 结构如下: scheme://host:port/path?query#fragment

URI 用字符串标识某一互联网资源,而URL 表示资源的地点(互 联网上所处的位置)。可见URL是URI 的子集。

URI 和 URL 的区别?

  • URI (Uniform Resource Identifier) 是统一资源标识符,是一个大概念。

  • URL (Uniform Resource Locator) 是统一资源定位符,它不仅标识资源,还提供了找到资源的方式(比如协议)。可以理解为 URL 是 URI 的子集。

为什么 URL 中有些字符会被转义(如 %20)?

  • URL 只能使用 ASCII 字符集。特殊字符(如空格、中文)必须通过 encodeURIencodeURIComponent 进行编码。

1. 什么是"同源"?

根据我们刚刚讨论的 URL 组成,只有当两个 URL 的 协议 (Protocol)域名 (Domain)端口 (Port) 均相同时,才被称为同源

  • https://a.com/page1https://a.com/page2 ------ 同源

  • http://a.comhttps://a.com ------ 跨域(协议不同)

  • https://a.comhttps://b.com ------ 跨域(域名不同)

  • https://a.comhttps://a.com:8080 ------ 跨域(端口不同)

2. 常见的跨域解决方案

在面试中,你通常需要给出以下三种最核心的方案:

A. CORS (Cross-Origin Resource Sharing) - 最主流

这是 W3C 标准,由后端通过设置 HTTP 响应头来告诉浏览器:"我允许这个源访问我的资源"。

  • 核心响应头:Access-Control-Allow-Origin: *(或指定的域名)。

  • 简单请求 vs 预检请求:对于复杂请求(如 PUTDELETE 或自定义 Header),浏览器会先发一个 OPTIONS 方法的请求,称为预检请求。

B. JSONP (JSON with Padding) - 兼容老旧浏览器

利用了 <script> 标签不受同源策略限制的特性。

  • 限制:仅支持 GET 请求。

  • 原理代码实现:

    javascript 复制代码
    /**
     * 模拟一个简单的 JSONP 实现
     */
    function jsonp({ url, params, callbackName }) {
        return new Promise((resolve) => {
            // 1. 创建 script 标签
            const script = document.createElement('script');
            
            // 2. 将回调函数挂载到 window,供服务端调用
            window[callbackName] = function(data) {
                resolve(data);
                document.body.removeChild(script); // 善后工作
                delete window[callbackName];
            };
    
            // 3. 构建 URL,带上 callback 参数
            const query = { ...params, callback: callbackName };
            const queryString = Object.keys(query).map(key => `${key}=${query[key]}`).join('&');
            script.src = `${url}?${queryString}`;
    
            // 4. 插入页面,触发请求
            document.body.appendChild(script);
        });
    }
    
    // 使用示例
    // jsonp({ url: 'http://api.test.com/data', callbackName: 'handleRes' }).then(res => console.log(res));
    C. Proxy (代理) - 开发环境最常用

    通过"中间人"绕过浏览器限制。浏览器访问同源的代理服务器,代理服务器再去请求目标服务器(服务器之间没有同源策略)。

  • 前端构建工具配置(如 Vite/Webpack):

javascript 复制代码
// vite.config.js 示例
export default {
  server: {
    proxy: {
      '/api': {
        target: 'http://backend-api.com',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  }
}

3. 面试官深挖:Cookie 如何在跨域中携带?

这是一个高频追问点。默认情况下,跨域请求不带 Cookie。

  1. 前端 :在 Ajax/Fetch 请求中设置 withCredentials = true

  2. 后端 :设置响应头 Access-Control-Allow-Credentials: true

  3. 注意 :此时 Access-Control-Allow-Origin 不能 设为通配符 *,必须指定具体域名。

总结建议

在面试时,你可以这样总结:"跨域是浏览器的安全屏障,解决它的核心思路要么是让服务器明确许可(CORS),要么是利用标签特性(JSONP),要么是避开浏览器环境(Proxy)。"

2. DNS 解析过程

1. DNS 解析过程:将域名变为 IP 地址

当你输入 www.example.com 时,计算机并不认识这个字符串,它需要通过 DNS(域名系统)找到对应的 IP 地址。

详细步骤(递归 + 迭代):

  1. 浏览器缓存/操作系统缓存 :首先检查浏览器自身是否有该域名的解析记录,如果没有,再检查操作系统的 hosts 文件。

  2. 本地 DNS 服务器(LDNS):通常是你接入的网络服务商(ISP)。

  3. 根域名服务器(Root Nameserver) :LDNS 如果没有缓存,会去问根服务器:"我知道 .com 在哪吗?"。

  4. 顶级域名服务器(TLD Nameserver) :根服务器指向 .com 服务器,LDNS 再去问 .com 服务器:"example.com 在哪?"。

  5. 权威域名服务器(Authoritative Nameserver) :最后找到负责 example.com 的权威服务器,拿到具体的 IP 地址,返回给浏览器并缓存。


2. TCP/IP 分层管理:数据是如何打包的?

在建立连接前,我们要理解数据是怎么通过网络栈传输的。TCP/IP 通常分为四层(或 OSI 七层模型,面试常考四层):

1.应用层:

应用层决定了向用户提供应用服务时通信的活动。 TCP/IP协议族内预存了各类通用的应用服务。比如, FTP (File Transfer Protocol, 文件传输协议)和DNS (Domain Name System, 域名系统)服务就是其中两类。 HTTP 协议也处于该层。

2.传输层:

传输层对上层应用层,提供处于网络连接中的两台计算机之间的 数据传输。 在传输层有两个性质不同的协议: TCP (Transmission Control Protocol,传输控制协议)和UDP (User Data Protocol,用户数据 报协议)。

3.网络层(又名网络互连层)

网络层用来处理在网络上流动的数据包。数据包是网络传输的最小 数据单位。该层规定了通过怎样的路径(所谓的传输路线)到达对 方计算机,并把数据包传送给对方。 与对方计算机之间通过多台计算机或网络设备进行传输时,网络层 所起的作用就是在众多的选项内选择一条传输路线。

4.链路层(又名数据链路层,网络接口层)

用来处理连接网络的硬件部分。包括控制操作系统、硬件的设备驱 动、NIC (Network Interface Card,网络适配器,即网卡),及光纤等物理可见部分(还包括连接器等一切传输媒介)。硬件上的范畴 均在链路层的作用范围之内。

图解


3. TCP 三次握手:确保双方都有收发能力

拿到 IP 后,客户端需要与服务器建立 TCP 连接。为什么是三次?因为要确保双向通信链路都是通畅的。

  • 第一次握手 :客户端发送 SYN (Synchronize) 包,序列号为 x

状态:客户端进入 SYN_SENT。服务器确认了"客户端发送能力正常"。

  • 第二次握手 :服务器返回 SYN + ACK (Acknowledgment) 包,序列号 y,确认号 x+1

状态:服务器进入 SYN_RCVD。客户端确认了"服务器接收和发送能力都正常"。

  • 第三次握手 :客户端发送 ACK 包,序列号 x+1,确认号 y+1

状态:双方进入 ESTABLISHED。服务器确认了"客户端接收能力正常"。


4. 四次挥手的详细过程

想象客户端(Client)主动发起断开请求:

  • 第一次挥手 (FIN) :客户端发送一个 FIN (Finish) 报文,用来告诉服务器:"我没有数据要发给你了,我要关闭发送通道"。

状态:客户端进入 FIN_WAIT_1 状态。

  • 第二次挥手 (ACK) :服务器收到 FIN,回复一个 ACK。意思是:"收到了,但我可能还有数据没发完,你等我一下"。

状态:服务器进入 CLOSE_WAIT,客户端进入 FIN_WAIT_2。此时连接处于"半关闭"状态。

  • 第三次挥手 (FIN) :服务器处理完最后的数据,向客户端发送 FIN。意思是:"好了,我也发完了,我也要关了"。

状态:服务器进入 LAST_ACK

  • 第四次挥手 (ACK) :客户端收到服务器的 FIN,回复最后一个 ACK。意思是:"收到,祝好"。

状态:客户端进入 TIME_WAIT 状态,等待 2MSL 后彻底关闭。服务器收到 ACK 后立即 CLOSED

面试高频追问:为什么会有 TIME_WAIT

这是四次挥手最常被问到的技术细节。客户端在发送完最后一个 ACK 后,并不会立即关掉连接,而是要等待 2MSL(Maximum Segment Lifetime,报文最大生存时间)。

原因有两个:

  1. 确保最后的 ACK 能够到达服务器 :如果最后一个 ACK 丢了,服务器会超时重传第三次的 FIN。客户端只有在 TIME_WAIT 期间才能重发 ACK。

  2. 防止"已失效的请求"干扰:等待足够长的时间,让本次连接产生的所有报文都在网络中消失。这样下次建立相同 IP 和端口的连接时,就不会收到上一次连接残留的旧数据。


代码与性能层面:CLOSE_WAIT 过多怎么办?

作为前端或全栈开发者,如果监控发现服务器出现大量 CLOSE_WAIT 状态,通常是因为程序 Bug。

  • 原因 :对方发了 FIN,但你的代码没有调用 close() 方法关闭 Socket(例如后端连接池没释放,或者长连接逻辑出错)。

  • 后果:会占用大量文件描述符,导致新连接无法建立。

5.HTTP 缓存策略

HTTP 缓存就是:浏览器把请求过的资源存起来,下次用的时候直接从本地拿,不再麻烦服务器**。**

1. 缓存的整体流程

当浏览器发起请求时,它会遵循以下逻辑:

  1. 先看强缓存:如果命中了,直接用,不发请求到服务器。

  2. 再看协商缓存:如果没有强缓存或已过期,就带着"凭证"去问服务器:"我这资源还能用吗?"。

  3. 返回结果

    • 服务器说"没变":返回 304 Not Modified,浏览器继续用本地的。

    • 服务器说"变了":返回 200 OK 和新内容


2. 强缓存 (Strong Cache)

特点 :不需要发送 HTTP 请求,直接从内存 (from memory cache) 或磁盘 (from disk cache) 读取。

关键响应头:

  • Expires (HTTP/1.0)

    • 值是一个绝对时间(如 Expires: Wed, 21 Oct 2025 07:28:00 GMT)。

    • 缺点:受限于客户端本地时间,如果用户改了系统时间,缓存会失效。

  • Cache-Control (HTTP/1.1) - 推荐

    • 使用相对时间,优先级高于 Expires

    • 常用指令:

      • max-age=3600:缓存 1 小时。

      • no-cache:不使用强缓存,直接进入协商缓存阶段。

      • no-store:完全不缓存,每次都要重新下载。

3. 协商缓存 (Negotiation Cache)

特点:必须发请求到服务器,由服务器决定是否使用缓存。


4.模拟代码场景:如何设置缓存?

如果你在写一个 Node.js (Express) 后端,你可以这样控制缓存:

javascript 复制代码
const express = require('express');
const app = express();

app.get('/static/logo.png', (req, res) => {
  // 设置强缓存:1年 (单位:秒)
  res.setHeader('Cache-Control', 'public, max-age=31536000');
  
  // 或者设置协商缓存 (Express 默认会自动处理 ETag)
  // res.setHeader('Cache-Control', 'no-cache'); 
  
  res.sendFile(__dirname + '/logo.png');
});

app.listen(3000);

5. 面试官杀手锏:用户操作对缓存的影响

这是很多候选人会忽略的细节:

  • 地址栏回车 / 链接跳转:有效,强缓存和协商缓存都正常工作。

  • F5 刷新失效 。浏览器会在请求头带上 Cache-Control: max-age=0,跳过强缓存,直接发起协商缓存。

  • Ctrl + F5 (强制刷新)全部失效。跳过所有缓存,直接从服务器拉取最新的。

总结建议

在面试中谈论缓存时,你可以顺便带出 "大前端部署实践"

"通常我们会给 HTML 设置 no-cache(走协商缓存),而给静态资源(JS/CSS/图片)设置超长强缓存。为了更新这些资源,我们会给文件名加上 Content Hash。这样只要代码变了,文件名就变,浏览器就会请求新文件,而没变的文件依然能秒开。"


6.状态码

1. 状态码分类概览

2xx - 成功
  • 200 OK:请求成功,有返回内容。

  • 204 No Content :请求成功,但没有响应主体 (常用于 OPTIONS 预检请求或删除操作)。

  • 206 Partial Content :客户端发送了范围请求(Range Header),服务器成功返回了部分内容。常用于断点续传或大视频分段加载。

3xx - 重定向
  • 301 Moved Permanently:永久重定向。浏览器会自动缓存新地址,下次直接跳新地址。

  • 302 Found:临时重定向。下次访问还是会请求原地址。

  • 304 Not Modified重点! 协商缓存命中,服务器告诉浏览器:"东西没变,你直接用本地缓存吧"。

4xx - 客户端错误
  • 400 Bad Request:请求语法错误(比如 JSON 格式写错了)。

  • 401 Unauthorized:未授权,需要身份验证(比如没登录)。

  • 403 Forbidden :服务器理解请求,但拒绝执行(比如你有登录,但没有管理员权限访问该页面)。

  • 404 Not Found:资源不存在。

  • 405 Method Not Allowed :方法不支持(比如接口只准 POST,你用了 GET)。

5xx - 服务器错误
  • 500 Internal Server Error:后端代码报错了。

  • 502 Bad Gateway:充当网关或代理的服务器(如 Nginx)尝试执行请求时,从上游服务器接收到无效响应。

  • 503 Service Unavailable:服务器超载或停机维护。

  • 504 Gateway Timeout:网关超时,上游服务器没在规定时间内返回数据。

2.面试官进阶:301 和 302 对 SEO 的影响?

  • 301 (永久):搜索引擎在抓取时会把旧地址的权重(PR值)转移到新地址。如果你换了新域名,一定要做 301。

  • 302 (临时):权重不会转移。如果滥用 302,可能会被搜索引擎判定为 URL 劫持。

总结建议

当面试官问你状态码时,不仅要说出数字含义,最好能结合实际业务场景。比如谈到 206 聊聊视频大文件下载,谈到 304 聊聊刚才说的 HTTP 缓存,谈到 401/403 聊聊权限控制。

7.HTTP和 HTTPS的区别

1.核心区别汇总

2. HTTPS 的"安全"是如何实现的?

HTTPS 并不是一种新的协议,而是 HTTP + SSL/TLS。它主要解决了 HTTP 的三个安全问题:

  1. 机密性(Encryption):防止数据被中间人窃听。

  2. 完整性(Integrity):防止数据在传输过程中被篡改。

  3. 身份认证(Authentication):确认你访问的网站确实是"官宣"的那个,而不是钓鱼网站。


3. HTTPS 的握手过程(核心考点)

这是面试官最喜欢问的细节。它结合了对称加密和非对称加密的优点。

  1. 客户端请求:客户端(浏览器)向服务器发起 HTTPS 请求,连接到 443 端口,发送支持的加密算法列表。

  2. 服务器响应 :服务器选择一套加密算法,并发送自己的数字证书(包含服务器公钥)。

  3. 客户端验证

    • 浏览器检查证书是否过期、颁发机构是否可信。

    • 如果验证通过,客户端生成一个随机数(预主密钥)

  4. 非对称加密传输密钥 :客户端用服务器的公钥加密这个随机数,发给服务器。

  5. 服务器解密 :服务器用自己的私钥解密,得到这个随机数。

  6. 对称加密传输数据 :现在双方都有了这个随机数,它将作为对称加密的密钥。此后的所有数据传输都使用这个随机数进行加密。

为什么这样设计?

  • 非对称加密 (公钥/私钥)虽然安全,但速度慢

  • 对称加密 (一个密钥)速度快,但密钥传输不安全。

  • 结论:用非对称加密来安全地传输对称加密的密钥,然后用对称加密来传数据。


4. 代码层面:前端需要做什么?

作为前端开发者,你不需要编写加密算法,但你需要知道:

  • Mixed Content 警告:如果你的 HTTPS 页面中引用了 HTTP 的静态资源(如图片、脚本),浏览器会报错或拦截。

  • HSTS (HTTP Strict Transport Security):一种安全策略,强制浏览器只使用 HTTPS 与服务器通信。

javascript 复制代码
// 在 Node.js (Express) 中开启 HTTPS 的简单示例
const https = require('https');
const fs = require('fs');
const express = require('express');

const options = {
  key: fs.readFileSync('server.key'), // 私钥
  cert: fs.readFileSync('server.crt') // 证书
};

const app = express();
https.createServer(options, app).listen(443, () => {
  console.log('HTTPS Server running on port 443');
});

5. 面试官可能追问:什么是中间人攻击(MITM)?

如果黑客伪造了证书,而用户忽略了浏览器的安全警告点击了"继续访问",黑客就可以解密你的数据。这就是为什么证书的有效性验证至关重要。


二:浏览器渲染原理

1. 渲染模式的分水岭:后端返回了什么?


1.服务端渲染 (SSR - Server Side Rendering)

  • 后端返回:一个包含了完整 DOM 结构的 HTML 字符串。

  • 浏览器起点:拿到 HTML 后立即开始解析并显示内容。

  • 特点:SEO 友好,首屏加载快(白屏时间短)。

  • 现代框架:Next.js (React), Nuxt.js (Vue)。

2.客户端渲染 (CSR - Client Side Rendering)

  • 后端返回 :一个几乎为空的 HTML 壳子 (通常只有一个 <div id="app"></div>)和一堆 JS 文件

  • 浏览器起点:必须等待 JS 下载并执行完毕后,由 JS 动态创建 DOM 节点。

  • 特点:用户体验流畅(页面切换无刷新),但首屏可能较慢。

  • 现代框架:普通的 Vue-cli 或 Create-React-App 项目。


2. 浏览器渲染的详细流水线 (The Critical Rendering Path)

无论数据是怎么来的,一旦浏览器拿到了 HTML、CSS 和 JS,就会进入关键渲染路径。这是面试中最核心的流程:

第一步:构建对象模型

  1. 构建 DOM 树 :浏览器将 HTML 字节流解析为一个个令牌(Tokens),然后转换成节点,最后构建成 DOM Tree

  2. 构建 CSSOM 树:解析所有的 CSS(包括外部文件和内联样式),构建出 CSSOM Tree。

第二步:合并成渲染树 (Render Tree)

浏览器将 DOM 和 CSSOM 合并。

注意display: none 的节点不会出现在渲染树中,但 visibility: hidden 的节点会。

第三步:布局 (Layout / Reflow)

计算每个节点在屏幕上的确切位置和大小。想象成在一个白纸上画方块,确定坐标。

第四步:绘制 (Paint / Repaint)

将节点的像素信息(颜色、边框、阴影等)绘制到屏幕上。

第五步:合成 (Composite)

如果页面有复杂的层级(如 3D 转换、Canvas、video),浏览器会将它们分层处理,最后合成到一起。


3. 为什么 JS 会阻塞渲染?

原理 :默认情况下,HTML 解析器遇到 <script> 标签时会暂停,去下载并执行 JS。因为 JS 可能会操作 DOM 或修改 CSS(导致前面的工作白费)

解决方案

  • defer:脚本异步下载,等待 HTML 解析完成后执行。

  • async:脚本异步下载,下载完立即执行(可能中断解析)


4. 面试必考:重排 (Reflow) 与 重绘 (Repaint)


5. 总结与扩展

从后端返回 HTML 开始,到屏幕显示出图像,浏览器经历了一个非常复杂的流水线。

  • SSR 提前在服务器做好了"构建对象模型"的一大部分工作。

  • CSR 把这些工作全丢给了浏览器的 JS 引擎。


三:V8引擎

V8 引擎(Chrome 和 Node.js 的核心)之所以快,是因为它摒弃了传统的"解释执行",采用了 JIT (Just-In-Time) 即时编译技术。

核心执行流程:

  1. 解析(Parser) :将源代码转为 抽象语法树(AST)

    • 词法分析:把代码拆成一个个不可再分的词(Tokens)。

    • 语法分析:根据语法规则把 Tokens 组成树状结构。

  2. 解释(Ignition):解释器将 AST 转为字节码(Bytecode)并开始执行。

    • 字节码比机器码轻量,可以跨平台运行。
  3. 优化(TurboFan) :编译器会标记"热点代码"(执行次数很多的函数),将其直接编译为高效的机器码

  4. 去优化(Deoptimization):如果热点代码的变量类型发生了变化(例如原本传数字,后来传了字符串),V8 会把机器码退回到字节码。

面试加分点 :为什么 V8 提倡写"类型确定"的代码? 因为类型一旦变化,就会触发 Deoptimization,导致性能陡降。这也是为什么 TypeScript 在大型项目中能间接提升性能(通过规范类型减少 V8 的猜疑)。


四: 事件循环 (Event Loop):异步调度的灵魂

事件循环是 JS 实现非阻塞 I/O 的核心。由于 JS 是单线程的,它必须通过一个机制来协调同步代码和异步任务。

任务分类:

  • 宏任务 (Macrotask)script (整体代码), setTimeout, setInterval, I/O, UI rendering

  • 微任务 (Microtask)Promise.then, MutationObserver, process.nextTick

执行顺序 (Event Loop Tick)

  1. 执行一个宏任务(最开始是同步代码)。

  2. 执行过程中如果遇到微任务,放入微任务队列

  3. 当前宏任务执行完后,立即清空所有的微任务队列

  4. (关键点):更新渲染(Update Rendering)。

  5. 检查是否有 Web Worker 任务,开始下一个宏任务。

代码实战分析:

javascript 复制代码
console.log('1'); // 同步

setTimeout(() => {
  console.log('2'); // 宏任务
}, 0);

Promise.resolve().then(() => {
  console.log('3'); // 微任务
});

console.log('4'); // 同步

// 输出顺序:1 -> 4 -> 3 -> 2

解释:1 和 4 先入栈执行。执行完后,检查微任务队列发现 3,执行 3。最后开启下一个循环,执行宏任务 2。


五: 浏览器缓存与渲染结合:Service Worker

如果说 HTTP 缓存是"自动挡",那么 Service Worker 就是"手动挡"。它是运行在浏览器后台的独立线程 。Service Worker 的地位:它充当了浏览器与网络之间的代理服务器。它可以拦截网络请求,并根据策略决定是走网络、走缓存,还是直接返回一段自定义内容。

关键特性:

  1. 离线能力:即使没网,也能通过缓存加载页面(PWA 的核心)。

  2. 推送通知:可以在后台接收服务器消息。

  3. 不能直接操作 DOM :必须通过 postMessage 与主线程通信。

生命周期与缓存结合:

  • Install 阶段:通常用来预缓存静态资源(App Shell)。

  • Activate 阶段:清理旧缓存。

  • Fetch 阶段:拦截请求,实现缓存优先或网络优先策略。

javascript 复制代码
// service-worker.js 示例
self.addEventListener('fetch', (event) => {
  event.respondWith(
    caches.match(event.request).then((response) => {
      // 如果缓存命中,直接返回;否则走网络请求
      return response || fetch(event.request);
    })
  );
});

总结:三者的联动

  • V8 决定了 JS 代码运行的快慢

  • Event Loop 决定了任务执行的时机,以及是否会卡住 UI 渲染。

  • Service Worker 决定了资源加载的来源,是渲染流水线的"物料补给站"。

相关推荐
打小就很皮...2 小时前
React 合同审查组件:按合同标题定位
前端·react.js·markdown
CHU7290352 小时前
智慧陪伴新选择:陪诊陪护预约小程序的暖心功能解析
java·前端·小程序·php
奔跑的web.2 小时前
TypeScript namespace 详解:语法用法与使用建议
开发语言·前端·javascript·vue.js·typescript
倾国倾城的反派修仙者2 小时前
鸿蒙开发——使用弹窗授权保存媒体库资源
开发语言·前端·华为·harmonyos
泰勒疯狂展开2 小时前
Vue3研学-组件的生命周期
开发语言·前端·vue
Charlie_lll3 小时前
学习Three.js–基于GeoJSON绘制2D矢量地图
前端·three.js
小二·3 小时前
Python Web 开发进阶实战:AI 原生安全防护 —— 在 Flask + Suricata 中构建智能网络威胁狩猎平台
前端·人工智能·python
葡萄城技术团队3 小时前
SpreadJS V19.0 新特性解密:设计器容器行列合计,让报表数据汇总更灵活
前端
晚霞的不甘3 小时前
Flutter for OpenHarmony:从零到一:构建购物APP的骨架与精美UI
前端·javascript·flutter·ui·前端框架·鸿蒙