前端基礎與瀏覽器機制 (Front-End Fundamentals & Browser Mechanics)
這些問題涵蓋了Web工作的基本原理,包括網絡、渲染和瀏覽器特性。
1. 瀏覽器渲染與性能 (Browser Rendering & Performance)
- URL輸入發生什么?(What happens when you type a URL?)
- 這是一個經典問題。它涉及DNS解析、TCP三次握手、HTTP請求、服務器處理、HTTP響應、瀏覽器解析(HTML, CSS, JS)、DOM/CSSOM構建、布局、繪制和合成。
- DOM樹和CSSOM樹的構建是并行的還是串行的?(Are DOM and CSSOM tree construction parallel or serial?)
- DOM 構建通常與網絡請求其他資源(如圖片)是并行的。然而,CSSOM 構建是渲染阻塞的,因為瀏覽器需要CSSOM來正確渲染頁面。JavaScript如果需要訪問或修改DOM或CSSOM,也可能阻塞DOM構建。
- 講一下URL到渲染頁面過程 (Explain the process from URL to page rendering)
- 這是“URL輸入發生什么”問題的擴展,更側重于瀏覽器端:DNS查找、TCP連接、HTTP請求/響應、解析HTML、構建DOM樹、解析CSS、構建CSSOM樹、結合生成渲染樹、布局(回流)、繪制(重繪)和合成。
- div改變尺寸和顏色(應該是想問回流和重繪) (Div changing size and color - likely asking about Reflow and Repaint)
- 回流 (Reflow):當頁面布局發生變化時(例如,元素尺寸、位置、內容變化)。這是一個昂貴的操作,因為它需要重新計算受影響元素及其后代和祖先的布局。
- 重繪 (Repaint):當元素的視覺屬性發生變化但不影響其布局時(例如,
color
、background-color
、visibility
)。這比回流的開銷小。
- 回流重繪具體是怎么實現的 (How are reflow and repaint specifically implemented?)
- 這深入到瀏覽器渲染引擎。渲染樹構建完成后,瀏覽器執行“布局”(回流)階段以確定所有元素的精確位置和大小。然后,“繪制”(重繪)階段填充像素。這些過程由瀏覽器的渲染引擎管理。
2. 網絡與協議 (Networking & Protocols)
- DNS解析具體是怎么個解析過程呢 (How does DNS resolution specifically work?)
- 涉及檢查瀏覽器緩存、操作系統緩存、路由器緩存、本地DNS服務器、根DNS服務器、TLD(頂級域名)DNS服務器和權威DNS服務器,最終獲取IP地址。它是一個分層和分布式的系統。
- 三次握手、四次揮手講一下 (Explain TCP Three-way Handshake and Four-way Wave)
- 三次握手 (Three-way Handshake):建立TCP連接(SYN, SYN-ACK, ACK)。
- 四次揮手 (Four-way Wave):終止TCP連接(FIN, ACK, FIN, ACK)。
- 301, 302, 304 (HTTP Status Codes)
- 301 Moved Permanently (永久重定向):資源已永久移動到新URL。瀏覽器應更新其書簽/緩存。
- 302 Found (臨時重定向):資源暫時移動。瀏覽器不應更新其書簽/緩存。
- 304 Not Modified (未修改):客戶端的緩存版本仍然有效。服務器告訴瀏覽器使用其緩存副本,節省帶寬。
- HTTPS加密 (HTTPS encryption)
- 在HTTP之上使用 SSL/TLS 協議。它結合使用非對稱加密(公鑰/私鑰)進行初始握手和密鑰交換,以及對稱加密進行連接建立后的數據傳輸。這確保了機密性、完整性和身份驗證。
- HTTP/2有什么新功能?多路復用具體表現 (What’s new in HTTP/2? Explain multiplexing)
- 多路復用 (Multiplexing):允許在單個TCP連接上同時發送多個請求和響應。這消除了HTTP/1.x中的“隊頭阻塞”問題,從而提高性能并減少往返次數。
- 其他特性:服務器推送、頭部壓縮(HPACK)、流優先級。
- 那你剛才說的圖片壓縮,如果要更快,你用CDN,dns解析是怎么跟CDN關聯起來的?(Regarding image compression, if you want it faster using CDN, how does DNS resolution relate to CDN?)
- 當用戶請求CDN上的資源時,DNS解析會根據用戶的地理位置和網絡狀況,將請求解析到離用戶最近的CDN節點(邊緣服務器)的IP地址。這通常通過DNS的CNAME記錄和CDN服務商的智能DNS解析實現,從而實現內容分發和加速。
3. 瀏覽器緩存 (Browser Caching)
- 瀏覽器緩存有哪些 (What types of browser caches are there?)
- 主要有 HTTP 緩存(包括強緩存和協商緩存)。其他類型包括 Service Worker 緩存、PWA 緩存(IndexedDB, LocalStorage)和內存緩存。
- 強緩存和協商緩存,怎么設置 (Strong cache and negotiated cache, how to set them up?)
- 強緩存 (Strong Cache):瀏覽器不向服務器發送請求。檢查
Expires
(HTTP/1.0) 或Cache-Control
(HTTP/1.1) 頭部。Cache-Control: max-age=<seconds>
:資源在此秒數內是新鮮的。Cache-Control: no-cache
(仍發送請求但重新驗證)、no-store
(從不緩存)。
- 協商緩存 (Negotiated Cache):瀏覽器向服務器發送請求,服務器決定緩存版本是否仍然有效。
Last-Modified
/If-Modified-Since
:服務器發送Last-Modified
頭部。在后續請求中,瀏覽器發送If-Modified-Since
帶有該日期。服務器進行比較。ETag
/If-None-Match
:服務器發送ETag
(資源內容的標識符)。在后續請求中,瀏覽器發送If-None-Match
帶有該ETag。服務器進行比較。ETag
比Last-Modified
更健壯。
- 強緩存 (Strong Cache):瀏覽器不向服務器發送請求。檢查
- 瀏覽器緩存,能詳細說說嗎,相關的屬性和標識呢?緩存過程大概是什么樣的?(Can you elaborate on browser caching, relevant attributes and identifiers? What’s the caching process like?)
- 這是一個要求詳細解釋的問題,涵蓋上述所有要點,強調使用的頭部以及瀏覽器和服務器經過的決策過程。
JavaScript 與 Web API (JavaScript & Web APIs)
這些問題側重于JavaScript的核心機制以及它如何與瀏覽器交互。
1. JavaScript 基礎 (JavaScript Fundamentals)
- JS事件循環 (JavaScript Event Loop)
- 解釋了JavaScript如何處理異步操作,盡管它是單線程的。它涉及調用棧 (Call Stack)、堆 (Heap)、Web API(定時器、DOM事件、HTTP請求)、回調隊列 (Callback Queue/Macro-task Queue) 和微任務隊列 (Micro-task Queue)(用于Promise、
queueMicrotask
)。事件循環不斷檢查調用棧是否為空,然后將任務從微任務隊列移動到調用棧,再從回調隊列移動到調用棧。
- 解釋了JavaScript如何處理異步操作,盡管它是單線程的。它涉及調用棧 (Call Stack)、堆 (Heap)、Web API(定時器、DOM事件、HTTP請求)、回調隊列 (Callback Queue/Macro-task Queue) 和微任務隊列 (Micro-task Queue)(用于Promise、
- 深拷貝,為什么要深拷貝 (Deep copy, why deep copy?)
- 深拷貝 (Deep copy):創建一個對象的完全獨立副本,包括所有嵌套的對象和數組。對復制對象的更改不會影響原始對象。
- 為什么 (Why):為了避免在修改復雜數據結構時產生意外的副作用。如果只執行淺拷貝,嵌套的對象/數組仍將引用相同的內存位置,導致意外行為。
- 垂直居中的方法 (Methods for vertical centering)
- 多種方法:
- Flexbox:
display: flex; align-items: center; justify-content: center;
- Grid:
display: grid; place-items: center;
- 絕對定位 (Absolute Positioning):
position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
- Table-cell:
display: table-cell; vertical-align: middle;
- Line-height(用于單行文本)。
- Flexbox:
- 多種方法:
- 發布訂閱者模式,能不能手寫 (Publish-Subscribe pattern, can you hand-code it?)
- 需要實現一個類似
EventEmitter
的類,包含on
(訂閱)、emit
(發布) 和off
方法。
- 需要實現一個類似
- Promise并發,Promise嵌套,Promise底層原理 (Promise concurrency, nesting, underlying principles)
- 并發 (Concurrency):使用
Promise.all()
、Promise.race()
、Promise.allSettled()
、Promise.any()
來同時管理多個 Promise。 - 嵌套 (Nesting):通過鏈式調用
.then()
來處理順序的異步操作。 - 底層原理 (Underlying Principle):Promise 代表異步操作的最終完成(或失敗)及其結果值。它們基于 A+ Promises 規范,并利用微任務隊列執行回調。
- 并發 (Concurrency):使用
- new過程發生了什么 (What happens during the
new
process?)- 創建一個新的空對象。
- 將這個新對象的
[[Prototype]]
(即__proto__
)鏈接到構造函數的prototype
對象。 - 將構造函數的作用域賦給新對象(
this
指向新對象)。 - 執行構造函數中的代碼。
- 如果構造函數沒有明確返回一個對象,則返回這個新對象。
2. 模塊化 (Modularity)
- CommonJS和ES6模塊化有什么區別 (What are the differences between CommonJS and ES6 Modules?)
- CommonJS (Node.js 默認):
- 同步加載模塊。
require()
導入,module.exports
或exports
導出。- 導出的是值的拷貝。
- ES Modules (ESM) (瀏覽器和現代Node.js):
- 異步加載模塊(靜態分析)。
import
導入,export
導出。- 導出的是值的引用(綁定)。
- 支持頂層
await
。
- CommonJS (Node.js 默認):
3. 跨域 (Cross-Origin)
- 跨域 (Cross-Origin)
- 指瀏覽器出于安全原因,限制從一個源(協議、域名、端口三者之一不同)加載的文檔或腳本與另一個源的資源進行交互。
- 解決方案:CORS (跨域資源共享)、JSONP、代理、WebSocket、Nginx反向代理等。
框架與庫 (Frameworks & Libraries)
這些問題深入到React和Vue等流行前端框架的具體實現和優化。
1. React
- react生命周期 (React Lifecycle)
- 舊版 (Class Components):
componentDidMount
、componentDidUpdate
、componentWillUnmount
等。 - 新版 (Hooks):使用
useEffect
模擬大部分生命周期行為。
- 舊版 (Class Components):
- 如何用hook實現componentWillUnmount (How to implement
componentWillUnmount
with Hooks)- 在
useEffect
的回調函數中返回一個清理函數。這個清理函數會在組件卸載時執行。
useEffect(() => {// 相當于 componentDidMount 和 componentDidUpdatereturn () => {// 相當于 componentWillUnmount}; }, []); // 空數組表示只在掛載和卸載時執行
- 在
- 在class組件能用hooks嗎?在函數式組件用class語法呢?(Can you use Hooks in class components? Can you use class syntax in functional components?)
- Hooks不能在class組件中使用。Hooks 是為函數式組件設計的。
- 函數式組件不能直接使用class語法。函數式組件就是純粹的JavaScript函數。
- class組件跟函數式組件優化的點在哪?使用函數式組件好處是什么?(Where are the optimization points for class components vs. functional components? What are the benefits of using functional components?)
- 優化點:
- Class Components:
shouldComponentUpdate
、PureComponent
。 - Functional Components:
React.memo
(用于性能優化,類似PureComponent
)、useCallback
、useMemo
。
- Class Components:
- 函數式組件好處:
- 更簡潔、可讀性更高。
- 更易于測試。
- 使用 Hooks 能夠更好地復用狀態邏輯。
- 更容易理解和推理組件行為。
- 未來可能獲得更好的性能優化(例如 Concurrent Mode)。
- 優化點:
- React會嗎,Vue2和Vue3說說你的看法和理解 (Do you know React? Talk about your views and understanding of Vue2 and Vue3)
- 這需要你結合自己的經驗,比較它們的設計理念、API風格、性能優化、生態系統等。
- Vue2: 選項式API,響應式基于
Object.defineProperty
。 - Vue3: 組合式API (Composition API) 和 選項式API 共存,響應式基于
Proxy
,性能更好,Tree-shaking 優化。 - React: JSX,函數式組件 + Hooks,強調函數式編程和不可變性。
- Vue2: 選項式API,響應式基于
- 這需要你結合自己的經驗,比較它們的設計理念、API風格、性能優化、生態系統等。
2. Vue
- Vue的雙向綁定怎么做的?(How does Vue’s two-way binding work?)
- Vue2: 主要通過
Object.defineProperty()
劫持對象的 getter 和 setter,結合發布-訂閱模式(Dep 收集依賴,Watcher 訂閱更新)。當數據變化時,setter 通知所有依賴的 Watcher,Watcher 觸發組件重新渲染。 - Vue3: 使用
Proxy
對象劫持整個對象,可以監聽屬性的增刪改查以及數組操作,性能更好,并且解決了Object.defineProperty
無法監聽新增屬性和刪除屬性的問題。
- Vue2: 主要通過
- Vue $nextTick原理 (Vue $nextTick principle)
$nextTick
的原理是利用 JavaScript 的事件循環機制。Vue 在更新 DOM 后,會將$nextTick
的回調函數推入微任務隊列(如果支持 Promise)或宏任務隊列(如setTimeout
)。這樣可以確保回調函數在 DOM 更新完成后執行,從而獲取到最新的 DOM 狀態。
- emit原理(emit原理 (emit原理(emit principle)
$emit
是 Vue 組件通信的一種方式,用于子組件向父組件發送事件。它基于 Vue 實例的事件系統。子組件通過$emit('eventName', payload)
觸發一個事件,父組件通過@eventName="handler"
監聽并處理這個事件。
- computed和watch的區別 (Differences between computed and watch)
- Computed (計算屬性):
- 基于它們的響應式依賴進行緩存。只有當依賴變化時,才會重新求值。
- 默認是同步的。
- 用于處理模板中需要復雜邏輯計算的數據,通常用于派生狀態。
- 必須有返回值。
- Watch (偵聽器):
- 用于觀察和響應 Vue 實例上的數據變化。
- 當數據變化時,執行一個副作用函數。
- 可以執行異步操作。
- 通常用于執行數據變化后的復雜操作,如網絡請求、DOM 操作等。
- Computed (計算屬性):
- Vue那個生命周期可以操作dom (Which Vue lifecycle hook can operate on DOM?)
mounted
:在實例掛載到 DOM 后調用。此時組件的模板已經渲染到 DOM 中,可以進行 DOM 操作。updated
:在組件因數據更改而重新渲染后調用。此時 DOM 已經更新,也可以進行 DOM 操作,但應避免在此鉤子中修改狀態,可能導致無限循環。
其他通用問題 (Other General Questions)
這些問題涵蓋了工具、兼容性、安全和個人職業選擇。
1. 工具與構建 (Tools & Build)
- webpack你了解嗎?(Do you know webpack?)
- Webpack 是一個靜態模塊打包器。當 Webpack 處理應用程序時,它會遞歸地構建一個依賴關系圖,其中包含應用程序所需的每個模塊,然后將所有這些模塊打包成一個或多個 bundle。
- 核心概念:Entry(入口)、Output(輸出)、Loader(加載器)、Plugin(插件)、Mode(模式)。
- 你的圖片壓縮怎么做的?(How do you do image compression?)
- 可以是在構建時(如使用 Webpack 插件
image-webpack-loader
)、上傳時(服務器端處理)、或運行時(如使用<picture>
標簽、srcset
屬性、WebP 格式)。
- 可以是在構建時(如使用 Webpack 插件
- 如果要做兼容性,你會怎么做?(How would you handle compatibility issues?)
- Polyfill:用于彌補新舊瀏覽器之間API的差異。
- Babel:將ES6+代碼轉換為ES5,以兼容舊瀏覽器。
- Autoprefixer:自動添加CSS供應商前綴。
- CSS Reset/Normalize.css:統一不同瀏覽器默認樣式。
- 漸進增強/優雅降級:設計策略。
- 瀏覽器兼容性測試:使用工具或手動測試。
2. 安全 (Security)
- 登陸校驗方法 (Login validation methods)
- Session-Cookie: 服務器創建Session,將Session ID存在Cookie中返回給客戶端,客戶端每次請求帶上Cookie,服務器根據Session ID識別用戶。
- Token-based (JWT): 客戶端登錄成功后,服務器返回一個JWT (JSON Web Token),客戶端將Token存儲(如LocalStorage),每次請求在Header中攜帶Token,服務器驗證Token有效性。
- OAuth2 / OpenID Connect: 用于第三方登錄授權。
- 說到了nodejs,問nodejs怎么實現token?(應該是想問底層原理吧)(Mentioned Node.js, how does Node.js implement tokens? (Likely asking about underlying principles))
- 在 Node.js 中實現 Token 通常指 JWT (JSON Web Token)。
- 原理:使用
jsonwebtoken
等庫。當用戶登錄時,服務器使用一個密鑰對用戶ID、角色等信息進行簽名,生成一個JWT。這個JWT包含三部分:Header(頭部)、Payload(載荷)和Signature(簽名)。客戶端收到JWT后存儲起來。每次請求時,客戶端將JWT放在HTTP請求的Authorization
頭部。服務器收到請求后,使用相同的密鑰驗證JWT的簽名,如果簽名有效且未過期,則認為用戶已認證。
- SSL加密細節 (SSL encryption details)
- SSL/TLS 握手過程:
- ClientHello: 客戶端發送支持的SSL/TLS版本、加密套件、隨機數等。
- ServerHello: 服務器選擇一個加密套件,發送證書(包含公鑰)、隨機數。
- Certificate: 客戶端驗證服務器證書的合法性(通過CA)。
- ClientKeyExchange: 客戶端生成一個預主密鑰,用服務器公鑰加密后發送給服務器。
- ChangeCipherSpec: 客戶端和服務器分別使用預主密鑰生成會話密鑰(對稱密鑰)。
- Finished: 雙方使用會話密鑰發送加密的握手消息,驗證握手是否成功。
- 之后的數據傳輸都使用對稱密鑰進行加密。
- SSL/TLS 握手過程:
3. 個人與職業 (Personal & Career)
- 為啥想做前端 (Why do you want to be a front-end developer?)
- 這是一個開放性問題,需要你表達對前端的熱情、興趣點(如用戶體驗、可視化、技術發展快等)、個人優勢與前端的契合度。
- 學習前端的過程是怎么樣的 (What was your front-end learning process like?)
- 描述你的學習路徑,例如從HTML/CSS/JS基礎開始,到框架(React/Vue),再到構建工具(Webpack),以及如何解決問題、參與項目等。
- 有學過算法和數據結構嗎?(Have you studied algorithms and data structures?)
- 前端開發中,算法和數據結構雖然不像后端那樣核心,但在優化性能、解決復雜問題(如虛擬列表、樹形結構操作)時非常重要。誠實回答并說明自己在前端場景下的應用或學習意愿。
- 我們這個工作可能三四天都會花在兼容性問題上,你能接受嗎 (Our work might involve spending three or four days on compatibility issues, can you accept that?)
- 這是一個考察你對工作內容預期和抗壓能力的問題。通常應該表示理解和接受,并強調自己有解決兼容性問題的能力和耐心。
希望這份詳細的總結和歸納對你有所幫助!祝你面試順利!
我將根據面試問題分類詳細解答,并提供擴展知識:
一、Web存儲相關
-
localStorage和cookie的區別:
- 存儲容量:cookie約4KB,localStorage約5MB
- 生命周期:cookie可設置過期時間,localStorage永久存儲(除非手動清除)
- 通信:cookie會隨HTTP請求自動發送,localStorage不會
- 訪問限制:cookie可設置domain/path限制,localStorage遵循同源策略
-
設置cookie示例:
document.cookie = "username=John; expires=Thu, 18 Dec 2025 12:00:00 UTC; path=/";
document.cookie = "useremail=john@example.com; max-age=3600; secure";
二、跨域問題
-
跨域解決方案:
- CORS(服務端設置
Access-Control-Allow-Origin
) - JSONP(利用
- CORS(服務端設置
三、JavaScript核心
-
變量存儲:
- 基本類型:Undefined、Null、Boolean、Number、String、Symbol(棧存儲)
- 引用類型:Object(堆存儲,棧存指針)
-
let/const/var區別:
// 作用域 var a = 1; // 函數作用域 let b = 2; // 塊級作用域 const c = 3; // 塊級作用域// 變量提升 console.log(d); // undefined(var會提升) var d = 4;// 重復聲明 var e = 5; var e = 6; // 允許 let f = 7; let f = 8; // 報錯
-
const的可變性:
- 不可變:基本類型(Number, String等)
- 可變:引用類型(Object, Array等)的屬性可修改
四、ES6+特性
-
Set和Map:
- Set:值唯一的集合,常用方法add/delete/has
- Map:鍵值對集合,鍵可以是任意類型,保持插入順序
-
Promise進階:
- Promise.all:全部成功則返回結果數組,一個失敗立即reject
- Promise.race:第一個settled的promise決定結果
- 新增方法:Promise.allSettled(等所有promise完成)
五、Vue框架
-
虛擬DOM:
- 本質是JS對象(輕量級DOM描述)
- 更新流程:數據變化 → 新vnode → diff算法 → 補丁更新
- 遞歸處理:確實會遞歸到最深層,但通過diff算法優化
-
Vuex核心:
// mutation必須是同步函數 mutations: {increment(state) {state.count++} }// action可以包含異步操作 actions: {async fetchData({ commit }) {const res = await api.getData();commit('SET_DATA', res.data);} }
六、手撕代碼
- 深拷貝實現:
function deepClone(obj, map = new WeakMap()) {if (obj === null || typeof obj !== 'object') return obj;if (map.has(obj)) return map.get(obj);const clone = Array.isArray(obj) ? [] : {};map.set(obj, clone);for (let key in obj) {if (obj.hasOwnProperty(key)) {clone[key] = deepClone(obj[key], map);}}return clone;
}
- 防抖與節流:
// 防抖(延遲執行)
function debounce(fn, delay) {let timer;return function(...args) {clearTimeout(timer);timer = setTimeout(() => fn.apply(this, args), delay);};
}// 節流(固定頻率執行)
function throttle(fn, interval) {let lastTime = 0;return function(...args) {const now = Date.now();if (now - lastTime >= interval) {fn.apply(this, args);lastTime = now;}};
}
- 三數之和(LeetCode 15):
function threeSum(nums) {nums.sort((a, b) => a - b);const res = [];for (let i = 0; i < nums.length - 2; i++) {if (i > 0 && nums[i] === nums[i - 1]) continue;let left = i + 1, right = nums.length - 1;while (left < right) {const sum = nums[i] + nums[left] + nums[right];if (sum === 0) {res.push([nums[i], nums[left], nums[right]]);while (left < right && nums[left] === nums[left + 1]) left++;while (left < right && nums[right] === nums[right - 1]) right--;left++;right--;} else if (sum < 0) {left++;} else {right--;}}}return res;
}
七、Webpack相關
-
Loader與Plugin:
- Loader:文件轉換器(如babel-loader轉譯JS,css-loader處理CSS)
- Plugin:擴展功能(如HtmlWebpackPlugin生成HTML文件)
-
Vue3打包:
- 主流方案:Vite(基于ESM的極速開發體驗)
- 傳統方案:webpack + vue-loader
建議結合具體項目經驗補充回答,例如提到localStorage時可以舉例說明在項目中如何用于保存用戶偏好設置,討論跨域時可以說實際項目中如何配置代理等。對于框架問題,最好能對比React的類似機制(如虛擬DOM的diff算法差異)。
1. React會嗎?Vue2和Vue3說說你的看法和理解
React
React 是一個基于 組件化 和 虛擬DOM 的前端框架,核心特點:
- 單向數據流(數據自上而下傳遞,狀態管理依賴Redux/MobX)
- JSX語法(JavaScript + XML,增強代碼可讀性)
- 函數式編程(Hooks API,如
useState
、useEffect
) - 高性能虛擬DOM(Diff算法優化渲染)
Vue2 vs Vue3
特性 | Vue2 | Vue3 |
---|---|---|
響應式原理 | Object.defineProperty (無法監聽新增屬性) | Proxy (全量監聽,性能更好) |
Composition API | 無(Options API) | 支持(邏輯復用更靈活) |
性能優化 | 虛擬DOM全量Diff | PatchFlag(靜態標記,減少Diff計算) |
TypeScript支持 | 一般 | 深度集成 |
打包體積 | 較大 | Tree-shaking優化,更小 |
生命周期 | beforeCreate 、created 等 | setup() 替代部分生命周期 |
Vue3優勢:
- 更好的性能(Proxy響應式、靜態提升)
- 更好的代碼組織(Composition API)
- 更好的TS支持
- 更小的包體積
2. SSL加密細節
SSL(Secure Sockets Layer)現已被TLS(Transport Layer Security)取代,但習慣仍稱SSL。
SSL/TLS加密流程(HTTPS)
- Client Hello:客戶端發送支持的加密算法、隨機數(Client Random)
- Server Hello:服務端返回選擇的加密算法、隨機數(Server Random)、證書
- 證書驗證:客戶端驗證證書(CA機構簽發,防止中間人攻擊)
- 密鑰交換:
- RSA:客戶端用公鑰加密Pre-Master Key,服務端私鑰解密
- ECDHE(更安全):基于橢圓曲線動態生成會話密鑰
- 會話密鑰生成:Client Random + Server Random + Pre-Master Key → 生成對稱加密密鑰
- 加密通信:后續數據使用對稱加密(AES)傳輸
加密算法:
- 非對稱加密(密鑰交換):RSA、ECDHE
- 對稱加密(數據傳輸):AES、ChaCha20
- 哈希校驗:SHA-256
3. 瀏覽器緩存
瀏覽器緩存分為 強緩存 和 協商緩存。
強緩存(無需請求服務器)
- HTTP Header:
Cache-Control: max-age=3600
(優先級高,單位秒)Expires: Wed, 21 Oct 2025 07:28:00 GMT
(HTTP/1.0,受本地時間影響)
- 緩存位置:
Memory Cache
(內存,快速但容量小)Disk Cache
(硬盤,持久但較慢)
協商緩存(需請求服務器驗證)
- Last-Modified / If-Modified-Since(基于時間)
- 服務器返回
Last-Modified
,客戶端下次帶If-Modified-Since
- 缺點:1秒內修改無法檢測
- 服務器返回
- ETag / If-None-Match(基于內容哈希,更精準)
- 服務器返回
ETag
,客戶端下次帶If-None-Match
- 服務器返回
緩存過程:
- 檢查
Cache-Control
/Expires
→ 命中強緩存直接返回 - 未命中則發送請求,服務器檢查
If-Modified-Since
/If-None-Match
- 資源未變更 → 304 Not Modified(用緩存)
- 資源變更 → 200 OK(返回新資源)
4. 手寫發布訂閱模式(Pub-Sub)及優化
基礎實現
class EventEmitter {constructor() {this.events = {};}on(event, callback) {if (!this.events[event]) this.events[event] = [];this.events[event].push(callback);}emit(event, ...args) {if (this.events[event]) {this.events[event].forEach(cb => cb(...args));}}off(event, callback) {if (this.events[event]) {this.events[event] = this.events[event].filter(cb => cb !== callback);}}
}// 使用示例
const emitter = new EventEmitter();
emitter.on("message", (data) => console.log(data));
emitter.emit("message", "Hello World!");
優化方向
- 防止內存泄漏:增加
once
方法(執行后自動取消訂閱) - 性能優化:用
Map
代替Object
(查找更快) - 錯誤處理:
try-catch
包裹回調執行 - 異步支持:
setTimeout
或Promise
處理異步事件
5. 跨域
原因
瀏覽器同源策略限制(協議+域名+端口一致)。
解決方案
- CORS(服務端設置)
Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, POST Access-Control-Allow-Headers: Content-Type
- JSONP(僅GET請求)
function handleResponse(data) {console.log(data); } const script = document.createElement("script"); script.src = "https://api.example.com/data?callback=handleResponse"; document.body.appendChild(script);
- 代理服務器(開發環境常用)
// webpack.config.js devServer: {proxy: {"/api": "http://localhost:3000",}, },
- Nginx反向代理
location /api {proxy_pass http://backend-server; }
6. TCP三次握手 & 四次揮手
三次握手(建立連接)
- SYN:客戶端發送
SYN=1, seq=x
- SYN-ACK:服務端回復
SYN=1, ACK=1, seq=y, ack=x+1
- ACK:客戶端發送
ACK=1, seq=x+1, ack=y+1
目的:確認雙方收發能力正常,防止歷史連接干擾。
四次揮手(斷開連接)
- FIN:客戶端發送
FIN=1, seq=u
- ACK:服務端回復
ACK=1, ack=u+1
(半關閉狀態) - FIN:服務端發送
FIN=1, seq=v
- ACK:客戶端回復
ACK=1, ack=v+1
(等待2MSL后關閉)
為什么四次?
因為TCP是全雙工,需分別關閉發送和接收通道。
7. nextTick原理和底層
Vue的nextTick
用于在DOM更新后執行回調,基于 微任務隊列 實現。
實現原理
- 優先使用微任務(
Promise.then
>MutationObserver
>setImmediate
>setTimeout
) - 回調隊列:將回調函數存入隊列,在下一個事件循環執行
示例代碼:
let callbacks = [];
let pending = false;function flushCallbacks() {pending = false;const copies = callbacks.slice();callbacks = [];for (let cb of copies) cb();
}function nextTick(cb) {callbacks.push(cb);if (!pending) {pending = true;Promise.resolve().then(flushCallbacks);}
}
8. Promise并發、嵌套及底層原理
Promise并發控制
function limitRequest(urls, limit) {const results = [];let count = 0;async function run() {while (urls.length && count < limit) {const url = urls.shift();count++;try {const res = await fetch(url);results.push(res);} catch (err) {results.push(err);} finally {count--;if (urls.length) run();}}}run();return results;
}
Promise嵌套(回調地獄)
fetch("/api/user").then(user => fetch(`/api/profile/${user.id}`)).then(profile => fetch(`/api/posts/${profile.id}`)).then(posts => console.log(posts));
底層原理
Promise基于 狀態機 實現:
- 狀態:
pending
、fulfilled
、rejected
- then方法:返回新Promise,支持鏈式調用
- 微任務隊列:
then
回調放入微任務隊列
9. new過程發生了什么
function myNew(constructor, ...args) {// 1. 創建空對象,繼承原型const obj = Object.create(constructor.prototype);// 2. 執行構造函數,綁定thisconst result = constructor.apply(obj, args);// 3. 如果構造函數返回對象,則使用它return result instanceof Object ? result : obj;
}// 示例
function Person(name) {this.name = name;
}
const p = myNew(Person, "John");
10. 瀏覽器緩存(詳細)
見 第3部分,補充:
- Cache-Control指令:
no-cache
:協商緩存no-store
:禁用緩存must-revalidate
:過期后必須驗證
11. 算法與數據結構
常見前端相關算法:
- 排序:快速排序、歸并排序
- 搜索:二分查找
- 數據結構:棧、隊列、鏈表、二叉樹(虛擬DOM Diff用)
- LeetCode高頻題:兩數之和、LRU緩存、反轉鏈表
12. 為什么選前端?學習過程?
為什么選前端
- 即時反饋:所見即所得,快速驗證想法
- 技術棧豐富(HTML/CSS/JS、框架、Node.js)
- 市場需求大(Web、移動端、Electron等)
學習過程
- 基礎:HTML/CSS/JavaScript(《JavaScript高級程序設計》)
- 進階:ES6、Webpack、Vue/React
- 工程化:Git、CI/CD、性能優化
- 全棧拓展:Node.js、數據庫(MySQL/MongoDB)
總結
本文涵蓋了前端面試高頻問題,建議結合項目經驗回答,例如:
- 提到Vue3時,可對比React Hooks
- 討論緩存時,可舉例項目中的緩存策略優化
- 手寫代碼時,說明優化思路(如
Map
替代Object
)
希望這份詳細解答能幫助你準備面試! 🚀
以下是針對您面試問題的全面解析,結合Vue核心原理、瀏覽器機制、網絡通信等模塊組織答案,并標注關鍵技術和易考點:
一、Vue核心原理
-
$nextTick
原理
Vue的響應式更新采用異步隊列機制,當數據變化時,DOM更新會被推入隊列,在下一個事件循環中批量執行。$nextTick
將回調函數加入隊列尾部,確保在DOM更新后執行。
實現優先級:Promise.then
>MutationObserver
>setImmediate
>setTimeout
。// 簡化實現 let pending = false; const callbacks = []; function nextTick(cb) {callbacks.push(cb);if (!pending) {pending = true;Promise.resolve().then(flushCallbacks);} }
-
$emit
原理
子組件通過this.$emit('event', data)
觸發自定義事件,父組件通過@event
監聽。底層是發布訂閱模式:Vue實例維護事件中心(_events
對象),$emit
觸發時遍歷對應事件回調執行。 -
computed vs watch
特性 computed watch 用途 同步計算新值(如過濾數據) 監聽數據變化執行異步/復雜操作 緩存 依賴不變時復用結果 無緩存,每次變化都執行 異步支持 ? 不支持 ? 支持 典型場景 購物車總價、表單校驗 搜索建議、路由參數監聽 -
操作DOM的生命周期
mounted
:組件首次渲染完成,DOM已掛載,可安全操作。updated
:數據更新導致DOM重新渲染后(慎用,易引發循環更新)。
二、瀏覽器與HTTP
-
強緩存 vs 協商緩存
類型 響應頭 狀態碼 優先級 強緩存 Cache-Control: max-age=3600
200 (from disk/memory cache) 高 協商緩存 ETag
/If-None-Match
304 低 過程:強緩存生效時不請求服務器;失效時攜帶
If-Modified-Since
或If-None-Match
向服務器驗證。 -
跨域解決方案
- CORS:服務端設置
Access-Control-Allow-Origin
- JSONP:利用
<script>
標簽無跨域限制<script src="https://api.com/data?callback=handleData"></script>
- 代理服務器:開發環境用webpack-dev-server代理,生產環境用Nginx反向代理。
- CORS:服務端設置
-
HTTP/2.0新特性
- 多路復用:一個TCP連接并行傳輸多個請求/響應,解決HTTP/1.1隊頭阻塞
- 二進制分幀、頭部壓縮、服務器推送
多路復用示例:
!https://example.com/http2-multiplexing.png
(圖示:多個流共享同一連接)
-
HTTPS加密流程
- 客戶端發送加密算法列表 + 隨機數A
- 服務器返回證書 + 隨機數B
- 客戶端驗證證書(CA機構簽發)
- 用證書公鑰加密預主密鑰發送
- 雙方用隨機數A+B+預主密鑰生成對稱加密密鑰
- 后續通信使用對稱加密(如AES)。
三、CSS與DOM
-
垂直居中方案
/* 方案1:Flex (推薦) */ .parent { display: flex; align-items: center; justify-content: center; }/* 方案2:Grid */ .parent { display: grid; place-items: center; }/* 方案3:絕對定位 + transform */ .child { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
-
回流(reflow) vs 重繪(repaint)
操作 觸發條件 性能影響 回流 尺寸/位置/結構變化 ?? 高 重繪 顏色/背景等樣式變化 ?? 中 優化建議:
- 避免頻繁操作DOM,使用
documentFragment
- 用CSS3動畫(觸發GPU加速)替代JS動畫。
- 避免頻繁操作DOM,使用
四、其他核心問題
-
Node.js實現Token
流程:const crypto = require('crypto'); // 生成Token(JWT簡化版) function createToken(payload, secret) {const header = Buffer.from(JSON.stringify({ alg: 'HS256' })).toString('base64');const body = Buffer.from(JSON.stringify(payload)).toString('base64');const sign = crypto.createHmac('sha256', secret).update(`${header}.${body}`).digest('base64');return `${header}.${body}.${sign}`; } // 驗證時重新計算簽名對比
-
CommonJS vs ES6模塊化
特性 CommonJS ES6 Modules 加載方式 運行時加載(同步) 編譯時靜態分析 輸出 module.exports
export
/import
引用類型 值的拷貝(基礎類型) 值的引用(實時綁定) -
深拷貝實現與必要性
原因:對象賦值僅復制引用,修改嵌套對象會污染原數據。
手寫深拷貝:
function deepClone(obj, map = new WeakMap()) {if (typeof obj !== 'object' || obj === null) return obj;if (map.has(obj)) return map.get(obj); // 解決循環引用const clone = Array.isArray(obj) ? [] : {};map.set(obj, clone);for (let key in obj) {if (obj.hasOwnProperty(key)) clone[key] = deepClone(obj[key], map);}return clone;
}
- 發布訂閱模式手寫
class EventEmitter {constructor() { this.events = {}; }on(event, cb) {(this.events[event] || (this.events[event] = [])).push(cb);}emit(event, ...args) {this.events[event]?.forEach(cb => cb(...args));}off(event, cb) {this.events[event] = this.events[event]?.filter(fn => fn !== cb);}
}
// 優化點:增加once()、錯誤處理、異步執行
五、面試策略建議
- React彌補方案:
- 快速學習React核心概念(組件化、Hooks、狀態管理)
- 強調Vue底層原理的掌握(如虛擬DOM Diff、響應式實現)。
- 項目亮點突出:
- 在自我介紹中量化成果,如“Vue2升Vue3提升構建速度80%”
- 主動引導技術提問(如提到性能優化引面試官追問)。
- 框架對比:
方向 Vue優勢 React優勢 響應式 Proxy深度監聽 不可變數據+手動優化 模板語法 SFC單文件組件開發高效 JSX靈活性強
面試核心在于 原理深度 + 實戰亮點,即使部分問題未答全,展示出學習能力和技術熱情也能加分。建議針對React補強基礎概念,同時深化Vue原理理解(如虛擬DOM源碼、依賴收集過程)。
以下是針對您提出的技術問題的系統性解答,結合原理與實踐經驗詳細展開:
?? 1. Vue雙向綁定原理
實現機制:
- Vue2:基于
Object.defineProperty
劫持數據屬性的getter/setter
,通過依賴收集(Dep類) 和觀察者模式(Watcher) 實現:- 數據讀取時觸發
getter
,將當前Watcher添加到Dep訂閱列表。 - 數據修改時觸發
setter
,通知Dep所有Watcher更新視圖。
- 數據讀取時觸發
- Vue3:改用
Proxy
代理整個對象,支持動態增刪屬性及深層嵌套監聽,性能更高。
流程示例:
// 簡化版數據劫持
function defineReactive(obj, key) {const dep = new Dep();let val = obj[key];Object.defineProperty(obj, key, {get() {dep.depend(); // 收集依賴return val;},set(newVal) {val = newVal;dep.notify(); // 通知更新}});
}
🖼? 2. 圖片壓縮方案
前端實現要點:
- Canvas壓縮:調整尺寸與質量
function compressImage(file, quality = 0.8) {const canvas = document.createElement('canvas');const ctx = canvas.getContext('2d');const img = new Image();img.onload = () => {canvas.width = img.width * 0.5; // 尺寸減半canvas.height = img.height * 0.5;ctx.drawImage(img, 0, 0, canvas.width, canvas.height);canvas.toBlob(blob => {// 上傳blob對象}, 'image/jpeg', quality);};img.src = URL.createObjectURL(file); }
- CDN加速:上傳壓縮后圖片至CDN,利用邊緣節點緩存減少加載時間。
🌐 3. URL到頁面渲染過程
關鍵步驟:
- DNS解析:域名 → IP地址(本地緩存 → 遞歸查詢根域、頂級域等)。
- TCP連接:三次握手建立可靠連接。
- HTTP請求:發送請求頭/體,服務器返回響應。
- 解析渲染:
- 構建DOM樹:解析HTML生成節點樹。
- 構建CSSOM:解析CSS樣式。
- 合成渲染樹:合并DOM與CSSOM,計算布局與繪制。
🔍 4. DNS解析詳細過程
分層查詢流程:
- 瀏覽器緩存 → 系統緩存(hosts文件) → 路由器緩存。
- 本地DNS服務器 → 根域名服務器(返回頂級域地址) → .com域服務器 → 目標域名服務器。
CDN關聯:
- 智能DNS解析用戶位置,返回最近的CDN節點IP,加速資源訪問。
🤝 5. 三次握手與四次揮手
- 三次握手(建立連接):
- 客戶端→服務端:SYN=1, seq=x
- 服務端→客戶端:SYN=1, ACK=1, seq=y, ack=x+1
- 客戶端→服務端:ACK=1, seq=x+1, ack=y+1。
- 四次揮手(斷開連接):
- 客戶端→服務端:FIN=1
- 服務端→客戶端:ACK=1(半關閉)
- 服務端→客戶端:FIN=1
- 客戶端→服務端:ACK=1(等待2MSL關閉)。
🧩 6. Class與函數式組件互用性
- Class組件使用Hooks:? 不可用,Hooks僅適用于函數組件。
- 函數組件模擬Class語法:? 可通過閉包+useState/useEffect實現狀態管理,但違反設計原則。
? 7. 組件優化與函數組件優勢
優化方向 | Class組件 | 函數組件 |
---|---|---|
優化手段 | shouldComponentUpdate | React.memo |
狀態邏輯復用 | HOC或Render Props | Hooks(useState/useEffect) |
打包體積 | 較大(需繼承) | 更小(無this綁定) |
性能 | 實例化開銷大 | 輕量,適合頻繁更新場景 |
函數組件核心優勢:
- 邏輯復用更靈活(自定義Hooks)。
- 避免
this
指向問題,代碼更簡潔。
📦 8. Webpack工程化實踐
常用能力:
- Loader:處理非JS資源(如
babel-loader
轉譯ES6+)。 - Plugin:擴展功能(
HtmlWebpackPlugin
生成HTML)。 - 代碼分割:
SplitChunksPlugin
拆分公共代碼。
兼容性方案:
- JS兼容:Babel +
@babel/preset-env
+core-js
按需polyfill。 - CSS兼容:PostCSS +
autoprefixer
自動加前綴。 - Polyfill服務:動態注入(如
polyfill.io
)。
? 9. 兼容性工作接受度
- 合理投入:若為必要業務需求(如政府/銀行需兼容IE),可接受短期集中處理。
- 效率建議:
- 使用自動化工具(如ESLint檢測語法兼容性)。
- 建立瀏覽器兼容矩陣,優先級分級處理。
💎 總結建議
- 原理深挖:如雙向綁定需說清Vue2/Vue3差異,DNS解析關聯CDN優化。
- 工程思維:圖片壓縮結合CDN、Webpack拆分polyfill提升效率。
- 框架理解:函數組件+Hooks是趨勢,掌握邏輯復用與性能優化點。
接受兼容性工作需明確范圍與工具支持,避免低效重復勞動。以上方案可大幅提升開發效率,縮短適配周期。
以下針對您提出的問題,結合前端核心原理與實踐經驗進行系統化解析:
🔐 一、登錄 Token 存儲與 Cookie 安全配置
-
Token 存本地 vs Cookie
- Token 存 LocalStorage 的原因
- SPA 架構適配:前后端分離項目中,前端需主動控制 Token 發送邏輯(如
Authorization: Bearer <token>
),LocalStorage API 更靈活。 - 規避 CSRF:Token 不自動隨請求發送,避免因 Cookie 自動攜帶導致的跨站請求偽造風險。
- 跨域支持:LocalStorage 數據不會自動發送,適合跨域 API 調用場景。
- SPA 架構適配:前后端分離項目中,前端需主動控制 Token 發送邏輯(如
- Cookie 的適用場景
- 傳統服務端渲染(SSR)項目,依賴自動發送機制。
- 需嚴格防御 XSS 時,配合
HttpOnly
屬性(見下文)。
- Token 存 LocalStorage 的原因
-
配置 Cookie 防 JS 操作
通過服務端設置安全屬性:Set-Cookie: token=abc123; HttpOnly; Secure; SameSite=Strict; Max-Age=3600
HttpOnly
:禁止 JavaScript 讀取 Cookie,徹底防御 XSS 竊取。Secure
:僅通過 HTTPS 傳輸,防止中間人攻擊。SameSite=Strict
:阻止跨站請求攜帶 Cookie,根治 CSRF。
🔄 二、協商緩存詳解
- 流程:
- 首請 → 服務器返回資源 +
ETag
(哈希標識)或Last-Modified
(修改時間)。 - 再請 → 瀏覽器帶
If-None-Match
(ETag值)或If-Modified-Since
(時間戳)。 - 服務器比對:
- 未變更 →
304 Not Modified
(空響應體,用本地緩存)。 - 已變更 →
200 OK
+ 新資源。
- 未變更 →
- 首請 → 服務器返回資源 +
- 對比強緩存:
特性 強緩存 協商緩存 網絡請求 無(直接讀緩存) 有(服務器驗證) 響應碼 200 (from disk/memory) 304 Not Modified 適用資源 靜態資源(JS/CSS/圖片) 頻繁更新資源(如用戶數據)
?? 三、HTTP 狀態碼 401/402/403
狀態碼 | 含義 | 典型場景 |
---|---|---|
401 | Unauthorized | 未攜帶 Token 或 Token 無效(需重新登錄)。 |
403 | Forbidden | 已認證但權限不足(如普通用戶訪問管理員接口)。 |
402 | Payment Required | 保留狀態碼,實際極少使用(原設計用于支付場景)。 |
?? 四、Cache-Control 關鍵屬性
屬性 | 作用 |
---|---|
max-age=3600 | 資源有效期(秒),優先級高于 Expires 。 |
no-cache | 禁用強緩存,每次需向服務器驗證(仍可緩存)。 |
no-store | 徹底禁用緩存(敏感數據場景)。 |
public | 允許代理服務器(CDN)緩存。 |
private | 僅允許瀏覽器緩存(禁止代理緩存)。 |
must-revalidate | 緩存過期后必須向服務器驗證。 |
🖖 五、Vue 的 MVVM 模式
- 核心流程:
- ViewModel:Vue 實例,通過
Data Binding
實現:- 數據變化 → 自動更新 DOM(
v-bind
/{{}}
)。 - DOM 事件 → 自動更新數據(
v-on
/v-model
)。
- 數據變化 → 自動更新 DOM(
- 與傳統 MVC 區別:無需手動操作 DOM(如 jQuery),由框架自動驅動視圖更新。
- ViewModel:Vue 實例,通過
🧵 六、JS 單線程與瀏覽器多線程
-
JS 單線程原因:
- 避免 DOM 操作沖突:多線程同時修改 DOM 會導致渲染結果不可控(如一個線程刪節點,另一個線程修改其樣式)。
- 歷史設計約束:作為瀏覽器腳本語言,最初定位為輕量級交互工具。
-
瀏覽器多線程協作:
線程 職責 JS 引擎線程 執行 JS 代碼(主線程)。 GUI 渲染線程 解析 HTML/CSS、布局、繪制(與 JS 引擎互斥)。 異步 HTTP 線程 處理網絡請求( fetch
/XMLHttpRequest
),完成后回調推入任務隊列。定時器線程 管理 setTimeout
/setInterval
,計時結束回調入隊。
📡 七、WebSocket 連接維護
- 心跳機制:
// 客戶端定時發送心跳包 const ws = new WebSocket('wss://api.example.com'); const heartbeatInterval = setInterval(() => {if (ws.readyState === WebSocket.OPEN) {ws.send(JSON.stringify({ type: 'heartbeat' }));} }, 30000); // 30秒一次// 服務端超時斷開:若未收到心跳,關閉連接
- 自動重連:監聽
onclose
事件,嘗試重新建立連接。 - 幀控制:
WebSocket.bufferedAmount
檢查未發送數據量,避免擁塞。
📏 八、Vue 列表高度獲取場景題
正確方案:使用 ref
獲取 DOM 高度(無需等待網絡請求)
<template><ul ref="listRef"><li v-for="item in list" :key="item.id">{{ item.name }}</li></ul>
</template><script>
export default {data() {return { list: [] };},async mounted() {// 1. 請求數據this.list = await fetchList(); // 2. 數據更新后DOM已渲染,通過ref獲取高度this.$nextTick(() => {const height = this.$refs.listRef.clientHeight;console.log('列表高度:', height);});}
};
</script>
錯誤思路分析:
- Promise.all 封裝請求:網絡請求完成 ≠ DOM 渲染完成,需等待 Vue 更新視圖。
- setTimeout 延遲獲取:不可靠,渲染時間受設備性能影響。
關鍵點:
ref
綁定:直接訪問渲染后的 DOM 元素。$nextTick
:確保 DOM 更新后執行回調,避免讀取到舊布局。
💎 總結
- 安全存儲:Token 放 LocalStorage 利于 SPA 控制,Cookie 需配置
HttpOnly
+Secure
+SameSite
三位一體防護。 - 緩存策略:靜態資源強緩存(
max-age=31536000
),動態數據協商緩存(ETag
)。 - Vue 設計:MVVM 通過數據綁定解放手動 DOM 操作,
ref
+nextTick
是訪問渲染后 DOM 的標準方案。 - 單線程本質:JS 單線程為避免 DOM 沖突,瀏覽器通過多線程協作支持異步。
面試技巧:遇到“獲取渲染后高度”類問題,優先考慮
ref
直取 DOM 而非依賴請求狀態,結合nextTick
確保時機準確。
以下是針對前端面試題的詳細解答,結合核心原理與最佳實踐,幫助您系統化掌握知識點:
1. 為什么選擇前端開發?
- 核心動機:
- 即時反饋:所見即所得(如動畫、交互效果),快速驗證想法。
- 技術廣度:涵蓋視覺設計(CSS)、邏輯(JavaScript)、工程化(Webpack)、跨端(Electron/React Native)。
- 影響力:直接塑造用戶體驗,業務價值可視化強(如數據看板、高交互應用)。
2. React 生命周期(類組件)
React 生命周期分為三個階段:
掛載階段
constructor
:初始化 state,綁定方法。static getDerivedStateFromProps(props, state)
:根據 props 更新 state(需返回對象或null
)。render
:返回 JSX。componentDidMount
:DOM 操作、網絡請求、訂閱事件。
更新階段
static getDerivedStateFromProps
(同上)。shouldComponentUpdate(nextProps, nextState)
:性能優化,返回false
阻止渲染。render
:重新渲染。getSnapshotBeforeUpdate(prevProps, prevState)
:DOM 更新前捕獲信息(如滾動位置),返回值傳給componentDidUpdate
。componentDidUpdate(prevProps, prevState, snapshot)
:更新后操作(如基于snapshot
調整 UI)。
卸載階段
componentWillUnmount
:清理定時器、取消網絡請求、移除訂閱。
為何廢棄
componentWillMount
等?
React Fiber 架構引入異步渲染,舊鉤子可能被多次調用,導致副作用(如重復請求)。替代方案:
- 數據請求移至
componentDidMount
。- 狀態派生用
getDerivedStateFromProps
。
3. JavaScript 事件循環(Event Loop)
- 單線程模型:JS 主線程執行同步任務,異步任務由瀏覽器的多線程模塊處理(如網絡請求線程、定時器線程)。
- 任務隊列:
- 宏任務(Macro Task):
setTimeout
、setInterval
、I/O、UI 渲染。 - 微任務(Micro Task):
Promise.then
、MutationObserver
、queueMicrotask
。
- 宏任務(Macro Task):
- 執行順序:
- 執行同步任務(調用棧)。
- 清空微任務隊列(優先級高)。
- 取一個宏任務執行,重復步驟 2。
// 示例
setTimeout(() => console.log("宏任務"), 0);
Promise.resolve().then(() => console.log("微任務"));
// 輸出順序:微任務 → 宏任務
4. URL 輸入到頁面渲染的流程
- DNS 解析:域名 → IP 地址(查詢本地緩存 → 遞歸查詢根域)。
- TCP 連接:三次握手建立可靠傳輸。
- HTTP 請求:瀏覽器發送請求頭 + 請求體。
- 服務器響應:返回狀態碼(如 200)、響應頭、HTML 文件。
- 解析渲染:
- 構建 DOM 樹:HTML 解析為節點樹(遇到
<script>
阻塞解析)。 - 構建 CSSOM:解析 CSS 為樣式樹。
- 合成渲染樹:合并 DOM + CSSOM,計算布局與繪制。
- 重排(Reflow)與重繪(Repaint):動態修改 DOM/CSS 觸發。
- 構建 DOM 樹:HTML 解析為節點樹(遇到
5. DOM 樹與 CSSOM 樹的構建關系
- 并行下載:HTML 解析時,預解析線程提前加載 CSS/JS 資源。
- 串行構建:
- CSSOM 構建會阻塞渲染樹合成(避免無樣式內容閃爍)。
- JS 執行會阻塞 DOM 構建(JS 可能修改 DOM/CSS)。
優化建議:CSS 內聯或優先加載,JS 用
async
/defer
避免阻塞。
6. HTTP 狀態碼 301、302、304
狀態碼 | 含義 | 典型場景 |
---|---|---|
301 | 永久重定向 | 域名遷移(SEO 權重轉移) |
302 | 臨時重定向 | 登錄跳轉(保留原 URL SEO 權重) |
304 | 資源未修改(協商緩存) | 瀏覽器緩存有效,服務器直接返回空響應 |
7. 強緩存與協商緩存
強緩存(無需請求服務器)
- 響應頭設置:
Cache-Control: max-age=3600 # 有效期(秒) Expires: Wed, 21 Oct 2025 07:28:00 GMT # 過期時間(HTTP/1.0)
- 緩存位置:
Memory Cache
(內存)、Disk Cache
(硬盤)。
協商緩存(需服務器驗證)
- 響應頭設置:
ETag: "d41d8cd98f00b204e9800998ecf8427e" # 資源哈希標識 Last-Modified: Wed, 21 Oct 2025 07:28:00 GMT # 最后修改時間
- 請求頭驗證:
If-None-Match: "d41d8cd98f00b204e9800998ecf8427e" # 匹配 ETag If-Modified-Since: Wed, 21 Oct 2025 07:28:00 GMT # 匹配修改時間
- 未變更 → 304 Not Modified(復用緩存)。
- 已變更 → 200 OK + 新資源。
8. 瀏覽器緩存類型
類型 | 特性 |
---|---|
Memory Cache | 內存緩存,快速但容量小,頁面關閉即失效(適合靜態資源) |
Disk Cache | 硬盤緩存,持久化存儲(適合大文件如 CSS/JS) |
Service Worker | 離線緩存(需 HTTPS),可攔截請求 |
Push Cache | HTTP/2 服務器推送緩存(會話級,優先級最低) |
9. 登錄校驗方法
Token 認證(主流方案)
- 登錄流程:
- 用戶提交賬號密碼 → 服務器驗證 → 返回 Token(如 JWT)。
- Token 存儲:
- 安全方案:
LocalStorage
+axios
攔截器添加Authorization: Bearer <token>
。 - 防御 XSS:避免敏感操作,關鍵接口需二次驗證(如短信)。
- 安全方案:
- Token 刷新:
- 短期 Token(1 小時) + 長期 Refresh Token(7 天),到期后自動刷新。
Session-Cookie 認證
- 流程:服務器生成 Session ID 存入 Cookie(需設置
HttpOnly
、Secure
、SameSite
)。 - 缺點:跨域限制、CSRF 風險(需配合 Token 使用)。
10. 用 Hook 實現 componentWillUnmount
在函數組件中使用 useEffect
的清理函數模擬:
import { useEffect } from 'react';function MyComponent() {useEffect(() => {// 組件掛載時執行(類似 componentDidMount)const timer = setInterval(() => console.log('Tick'), 1000);// 返回清理函數(類似 componentWillUnmount)return () => {clearInterval(timer);console.log('定時器已清理');};}, []); // 空依賴表示僅執行一次return <div>組件內容</div>;
}
關鍵點:
useEffect
的依賴數組為[]
時,僅掛載/卸載執行一次。- 清理函數在組件卸載前自動觸發,用于取消訂閱、定時器等。
總結建議
- 原理深挖:如事件循環需說清微任務優先機制,緩存設置需區分
max-age
與ETag
場景。 - 框架對比:React 生命周期遷移到 Hooks 是趨勢(面試可提
useEffect
替代方案)。 - 實戰結合:舉例優化手段(如 DNS 預解析、CDN 緩存靜態資源)。
面試時遇到開放性問題(如“為什么選前端”),關聯業務價值(如“通過懶加載提升電商首屏轉化率30%”)更易脫穎而出。