前端工程師面試攻略:Pelith、Xrex、Garena面試題目解析

更新 發佈閱讀 18 分鐘

軟體工程師職涯升級計畫啟動!立即預約職涯諮詢、履歷健檢或模擬面試👈,為您的加薪做好準備!

前端工程師的求職之路,往往伴隨著一輪又一輪的技術面試。不同公司各有側重,從 JavaScript 核心、框架應用到 Git 操作,都可能是考察的重點。本文將帶你深入了解三家知名公司——Pelith、Xrex 和 Garena 的前端面試題目,並提供詳盡的解析與答案,希望能助你在面試中過關斬將,拿到心儀的 Offer!


第一站:Pelith - 紮實的 JavaScript 基礎功

Pelith 的面試似乎特別看重求職者對 JavaScript 核心概念的理解,尤其是異步處理和基礎型別判斷。

面試題目 1:Promise

  • 考察重點: 理解 JavaScript 異步編程的核心機制,從 Callback Hell 到 Promise,再到 async/await 的演進。
  • 解析與答案:
    • 異步的必要性: JavaScript 是單線程的,為了避免耗時操作(如網路請求、文件讀寫)阻塞主線程,導致頁面卡頓,異步編程應運而生。
    • Promise: Promise 是一個代表了「未來」才會結束的事件(通常是一個異步操作)最終結果的對象。它有三種狀態:
      • pending:初始狀態,既不是成功,也不是失敗。
      • fulfilled:意味著操作成功完成。
      • rejected:意味著操作失敗。
    • 核心方法:
      • .then(onFulfilled, onRejected):用於處理 fulfilled 狀態(onFulfilled)和 rejected 狀態(onRejected)。它返回一個新的 Promise,形成鏈式調用。
      • .catch(onRejected):.then(null, onRejected) 的語法糖,專門用於處理錯誤。
      • .finally(onFinally):無論 Promise 最終是 fulfilled 還是 rejected,都會執行的回調。
    • async/await ES2017 引入的語法糖,建立在 Promise 之上,讓異步代碼看起來更像同步代碼,提高可讀性。
      • async 關鍵字用於聲明一個函數是異步函數,該函數會隱式返回一個 Promise。
      • await 關鍵字只能在 async 函數內部使用,它會暫停 async 函數的執行,等待 await 後面的 Promise 完成,然後恢復執行並返回 Promise 的結果。如果 Promise 被拒絕,await 會拋出錯誤,需要使用 try...catch 語句來捕獲。

面試題目 2:typeof

  • 考察重點: 掌握 typeof 運算符的行為,了解其返回值以及一些特殊情況。
  • 解析與答案:
    • typeof 是一個一元運算符,用於返回一個表示未經計算的操作數的類型的字符串
    • 常見返回值:
      • 'undefined':未定義的變數。
      • 'boolean':布爾值 (true / false)。
      • 'string':字符串。
      • 'number':數字 (包括 NaN 和 Infinity)。
      • 'bigint':大整數 (ES2020 新增)。
      • 'symbol':符號 (ES2015 新增)。
      • 'function':函數。
      • 'object':物件、陣列 (Array)、null。
    • 特別注意:
      • typeof null 返回 'object':這是 JavaScript 長久以來的一個 bug,為了兼容性一直保留。判斷 null 需要使用 === null。
      • typeof [] (陣列) 返回 'object':判斷陣列需要使用 Array.isArray()。
      • typeof NaN 返回 'number':NaN (Not a Number) 本身是數字類型,表示一個無效的數字。判斷 NaN 需要使用 Number.isNaN() 或 isNaN() (後者會進行類型轉換,需注意)。

第二站:Xrex - React 深度與 JavaScript 廣度並重

Xrex 的面試題目涵蓋範圍更廣,從 React 的進階 Hook、異步實踐,到 Git 版本控制和 JavaScript 的核心底層機制(事件循環、閉包),考察求職者的綜合能力。

面試題目 1: useEffect v.s useLayoutEffect

  • 考察重點: 理解 React 中處理副作用的兩個 Hook 的區別、執行時機和適用場景。
  • 解析與答案:
    • 共同點: 兩者都用於在函數組件中執行副作用操作(如數據獲取、訂閱、手動修改 DOM)。它們都接收一個函數和一個可選的依賴數組。
    • 核心區別(執行時機):
      • useEffect:在瀏覽器完成繪製 (paint) 之後異步執行。它不會阻塞瀏覽器的繪製過程。這是處理大多數副作用的首選 Hook。
      • useLayoutEffect:在所有 DOM 變更之後,瀏覽器進行繪製之前同步執行。它會阻塞瀏覽器的繪製。
    • 適用場景:
      • useEffect:適用於絕大多數副作用,如數據請求、設置訂閱、計時器等,這些操作不需要在瀏覽器繪製前完成,且不希望阻塞用戶界面。
      • useLayoutEffect:適用於需要在 DOM 更新後、瀏覽器繪製前讀取 DOM 佈局信息並同步觸發重新渲染的場景。例如,測量 DOM 元素的尺寸或位置,並根據這些信息更新狀態,以避免畫面閃爍。由於其同步阻塞特性,應謹慎使用,避免性能問題。

面試題目 2: setTimeout and promise practice

  • 考察重點: 結合實際場景理解 JavaScript 的事件循環 (Event Loop)、宏任務 (Macrotask) 和微任務 (Microtask) 的執行順序。
  • 解析與答案:
    • 這個題目通常會給出一段包含 setTimeout, Promise (.then, .catch, async/await) 的代碼,要求預測輸出順序。
    • 事件循環 (Event Loop): JavaScript 引擎用來管理和執行異步任務的機制。
    • 宏任務 (Macrotask/Task): 包括 script (整體代碼)、setTimeout, setInterval, setImmediate (Node.js), I/O 操作, UI rendering 等。宏任務會被放入宏任務隊列。
    • 微任務 (Microtask/Job): 包括 Promise.then/catch/finally, async/await (其後的代碼), queueMicrotask, MutationObserver 等。微任務會被放入微任務隊列。
    • 執行順序:
      1. 執行當前的宏任務(例如 script 標籤內的同步代碼)。
      2. 執行過程中遇到的同步代碼立即執行。
      3. 遇到異步任務(如 setTimeout 或 Promise),將其回調函數註冊到對應的隊列(宏任務隊列或微任務隊列)。
      4. 當前宏任務執行完畢後,立即檢查微任務隊列。
      5. 執行所有當前微任務隊列中的任務。如果在執行微任務過程中又產生了新的微任務,會將其加入隊列末尾,並在本輪繼續執行,直到微任務隊列清空。
      6. (可選)執行 UI 渲染操作(瀏覽器環境)。
      7. 從宏任務隊列中取出一個任務執行,重複步驟 2-6。
    • setTimeout vs Promise: setTimeout 的回調屬於宏任務,而 Promise (.then, await 後的代碼) 屬於微任務。因此,在同一次事件循環中,Promise 的回調總是比 setTimeout 的回調先執行。
    • 實踐練習 (示例代碼及輸出預測): JavaScriptconsole.log('script start'); // 1. 同步 setTimeout(function() { console.log('setTimeout'); // 5. 宏任務 }, 0); Promise.resolve().then(function() { console.log('promise1'); // 3. 微任務 }).then(function() { console.log('promise2'); // 4. 微任務 (由上一個 then 產生) }); console.log('script end'); // 2. 同步 // 預期輸出: // script start // script end // promise1 // promise2 // setTimeout

面試題目 3:git 分支的合併

  • 考察重點: 理解 Git 中合併分支 (git merge) 的概念、常用策略以及如何處理合併衝突。
  • 解析與答案:
    • 目的: 將一個分支的更改整合到另一個分支中。通常是將開發完成的功能分支合併回主分支 (如 mainmaster)。
    • 常用命令: Bash# 1. 切換到接收更改的目標分支 (e.g., main) git checkout main # 2. 執行合併命令,將來源分支 (e.g., feature-branch) 合併進來 git merge feature-branch
    • 合併策略:
      • Fast-forward (快進合併): 如果目標分支 (main) 在來源分支 (feature-branch) 創建後沒有任何新的提交,Git 會直接將 main 分支的指針移動到 feature-branch 的最新提交。不會創建新的合併提交記錄,保持線性歷史。
      • Recursive (遞歸合併) / Three-way Merge (三方合併): 如果目標分支和來源分支各自都有新的提交(歷史產生了分叉),Git 會執行三方合併。它會找到兩個分支的共同祖先節點,並將兩個分支的更改與共同祖先進行比較,生成一個新的合併提交 (Merge Commit)。這個提交有兩個父提交。這是 Git 的默認合併策略(當不能快進時)。
    • 合併衝突 (Merge Conflicts): 如果兩個分支修改了同一個文件的同一部分,Git 無法自動決定保留哪個更改,就會發生合併衝突。
      • 標記: Git 會在衝突的文件中用特殊標記(<<<<<<<, =======, >>>>>>>)標示出衝突的部分。
      • 解決: 需要手動編輯衝突文件,選擇要保留的代碼(可能來自一方,也可能是兩者結合,或者全新修改),然後移除特殊標記。
      • 完成: 解決所有衝突後,使用 git add <resolved_file> 將文件標記為已解決,最後執行 git commit 來完成合併(如果是三方合併,Git 通常會預填合併信息,確認即可;如果是 rebase 中的衝突,則使用 git rebase --continue)。

面試題目 4:Macrotask 與 MicroTask

  • 考察重點: 同面試題目 2 (setTimeout and promise practice),深入理解事件循環、宏任務和微任務的定義、種類及執行順序。
  • 解析與答案: (參考上面題目 2 的解析,這裡可以補充更多例子)
    • 宏任務例子: script (整體代碼)、setTimeout, setInterval, requestAnimationFrame (通常在渲染前執行,但行為類似宏任務), I/O, UI rendering。
    • 微任務例子: Promise.then/catch/finally, queueMicrotask() (顯式添加微任務), MutationObserver 回調, process.nextTick (Node.js 環境,比 Promise 微任務優先級更高)。
    • 關鍵點: 每次事件循環只執行一個宏任務,但會執行完所有的微任務。微任務提供了在當前宏任務結束後、下一個宏任務開始前(或 UI 渲染前)立即執行某些邏輯的能力,常用於確保某些操作在狀態更新後、渲染前完成。

面試題目 5:閉包 (Closure)

  • 考察重點: 理解閉包的定義、形成條件、原理以及常見應用場景。
  • 解析與答案:
    • 定義: 閉包是指一個函數以及其周圍的狀態(詞法環境)的組合。換句話說,閉包讓你有權限從內部函數訪問外部函數的作用域。在 JavaScript 中,閉包會在你創建一個函數時,同時創建了該函數的作用域鏈。
    • 形成條件: 當一個內部函數引用了其外部函數的變數(即使外部函數已經執行完畢),閉包就產生了。
    • 原理: JavaScript 的詞法作用域規則決定了函數在定義時就能確定其能訪問哪些變數。即使外部函數執行完畢,其執行上下文可能銷毀,但如果內部函數仍然存在引用(例如被返回或賦值給全局變數),那麼外部函數的活動對象(包含其變數)就不會被垃圾回收機制回收,內部函數依然可以通過其作用域鏈訪問這些變數。
    • 示例: JavaScriptfunction outerFunction() { let outerVariable = 'I am outside!'; function innerFunction() { console.log(outerVariable); // 訪問外部函數的變數 } return innerFunction; // 返回內部函數 } const myClosure = outerFunction(); // outerFunction 執行完畢,但 outerVariable 所在的環境被 innerFunction 引用 myClosure(); // 輸出: "I am outside!" -> 閉包的效果
    • 應用場景:
      • 數據封裝與私有變數: 模擬私有成員,保護內部狀態不被外部直接訪問。
      • 回調函數與異步: 在回調函數中訪問定義它們時的上下文信息(例如,循環中為每個 setTimeout 保存特定的索引值)。
      • 函數工廠: 創建具有特定配置或狀態的函數。
      • 柯里化 (Currying) / 部分應用 (Partial Application)。
      • 模塊化: 在 ES6 模塊出現之前,常用立即執行函數表達式 (IIFE) 配合閉包來創建模塊作用域。

第三站:Garena - 專注 React 性能優化

Garena 的面試題目似乎更側重於 React 的實際應用和性能優化技巧。

面試題目 1:useMemo

  • 考察重點: 理解 useMemo Hook 的作用、使用方法、依賴數組的重要性,以及它與 useCallback 的區別。
  • 解析與答案:
    • 作用: useMemo 用於記憶化 (Memoization) 一個計算結果。它接收一個「創建」函數和一個依賴數組。useMemo 僅在某個依賴項改變時才重新計算記憶化的值。這種優化有助於避免在每次渲染時都進行高開銷的計算。
    • 語法: JavaScriptconst memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
      • 第一個參數是一個函數,該函數的返回值會被記憶化。
      • 第二個參數是一個依賴數組。只有當數組中的某個值發生變化時,第一個參數的函數才會重新執行。如果傳入空數組 [],函數只會在組件初始渲染時執行一次。
    • 使用場景:
      • 當組件中有計算成本很高的操作(例如,對大型數組進行複雜的過濾、排序或計算)時,可以使用 useMemo 來緩存結果,避免每次渲染都重新計算。
      • 當需要將某個計算結果作為 prop 傳遞給子組件,並且希望僅在該結果實際變化時才觸發子組件的重新渲染(配合 React.memo 或 shouldComponentUpdate 使用)時。
    • useCallback 的區別:
      • useMemo:記憶化函數的返回值(一個值)。
      • useCallback:記憶化函數本身(一個函數實例)。useCallback(fn, deps) 等價於 useMemo(() => fn, deps)。useCallback 主要用於將回調函數傳遞給經過優化的子組件(如使用 React.memo 包裹的組件)時,防止因為父組件渲染導致函數實例變化,從而引起不必要的子組件渲染。

總結與啟示

從 Pelith、Xrex 到 Garena 的面試經驗可以看出:

  1. 基礎是根本: 無論框架如何演進,對 JavaScript 核心(異步、事件循環、閉包、typeof 等)的深刻理解始終是重中之重。
  2. 框架深度不可少: 對於 React 開發者而言,不僅要會用 Hook,更要理解其原理、區別和適用場景(useEffect vs useLayoutEffect, useMemo vs useCallback)。
  3. 實踐與原理結合: setTimeout 與 Promise 的結合考察了事件循環的實際應用;Git 合併則考察了版本控制的實操能力。
  4. 性能優化意識: useMemo 的考察體現了對應用性能的關注,這是進階工程師的必備素養。

準備前端面試,不僅要刷題,更要深入理解每個知識點背後的原理和應用場景。希望這篇整理能為你的求職之路點亮一盞明燈!祝你面試順利!

留言
avatar-img
留言分享你的想法!
avatar-img
跨越國界的程式人生
2會員
40內容數
自學程式,現為網頁開發工程師,同時擔任線上課程講師,專注於幫助自學程式的開發者找到理想工作。熱愛技術與分享,致力於將複雜的概念轉化為實用知識,讓更多人踏入軟體開發的世界。
2025/03/29
這篇文章整理了前端開發中常見的效能優化技巧、React與JavaScript的知識點,以及Redux Toolkit和React Fiber的應用、Reflow與Repaint、Event Loop、Higher Order Component、React Hooks等主題。
Thumbnail
2025/03/29
這篇文章整理了前端開發中常見的效能優化技巧、React與JavaScript的知識點,以及Redux Toolkit和React Fiber的應用、Reflow與Repaint、Event Loop、Higher Order Component、React Hooks等主題。
Thumbnail
2025/03/20
這篇文章涵蓋了HTTP 方法、JWT 認證授權機制、CORS 設定、HTTP 狀態碼,以及LeetCode熱門題目(Longest Substring Without Repeating Characters、Valid Parentheses)的解法,適合學習Web開發以及後端技術的讀者。
Thumbnail
2025/03/20
這篇文章涵蓋了HTTP 方法、JWT 認證授權機制、CORS 設定、HTTP 狀態碼,以及LeetCode熱門題目(Longest Substring Without Repeating Characters、Valid Parentheses)的解法,適合學習Web開發以及後端技術的讀者。
Thumbnail
2025/03/19
這篇文章記錄近期學習的技術重點,包含WebStorage & Cookie安全性問題、排序演算法Merge Sort、圖的遍歷DFS,以及React Component開發經驗。文中提供相關學習資源連結,適合對網頁開發、演算法及面試準備感興趣的朋友參考。
Thumbnail
2025/03/19
這篇文章記錄近期學習的技術重點,包含WebStorage & Cookie安全性問題、排序演算法Merge Sort、圖的遍歷DFS,以及React Component開發經驗。文中提供相關學習資源連結,適合對網頁開發、演算法及面試準備感興趣的朋友參考。
Thumbnail
看更多
你可能也想看
Thumbnail
本文介紹了CSS Battle #172 交叉骷髏題目的解答技巧,包括圖層拆解的熟練程度和對小圓拆開處理等技巧。作者分享了100%的解法,鼓勵讀者分享自己的作法與交流。
Thumbnail
本文介紹了CSS Battle #172 交叉骷髏題目的解答技巧,包括圖層拆解的熟練程度和對小圓拆開處理等技巧。作者分享了100%的解法,鼓勵讀者分享自己的作法與交流。
Thumbnail
本文介紹了CSS Battle 17的挑戰題目,並提供瞭解題的技巧和方法。內容包括基本排版、圖形解構能力和技術總結。歡迎大家分享自己的解法與作者交流。
Thumbnail
本文介紹了CSS Battle 17的挑戰題目,並提供瞭解題的技巧和方法。內容包括基本排版、圖形解構能力和技術總結。歡迎大家分享自己的解法與作者交流。
Thumbnail
本篇文章分享了前端工程師在 CSS Battle #166 的解題方式,藉由使用 flex 來進行排版,並提供了相關的技術總結。歡迎一起來學習或練習基礎切版的朋友們和作者互動。
Thumbnail
本篇文章分享了前端工程師在 CSS Battle #166 的解題方式,藉由使用 flex 來進行排版,並提供了相關的技術總結。歡迎一起來學習或練習基礎切版的朋友們和作者互動。
Thumbnail
本篇文章分享了 CSS Battle 的題目 #160 的解法,並講解了對於前端工程師基礎切版的重要性和技術總結。
Thumbnail
本篇文章分享了 CSS Battle 的題目 #160 的解法,並講解了對於前端工程師基礎切版的重要性和技術總結。
Thumbnail
前端工程師需要時不時拿出來打磨基本功。本文分享了從#18問題來提供的CSS Battle的題目作法,並介紹了grid的使用方式,以及nth-of-type的應用。這題算是蠻能鑑別你對基本CSS常用排版的熟悉程度。歡迎大家分享自己的作法與我交流 !
Thumbnail
前端工程師需要時不時拿出來打磨基本功。本文分享了從#18問題來提供的CSS Battle的題目作法,並介紹了grid的使用方式,以及nth-of-type的應用。這題算是蠻能鑑別你對基本CSS常用排版的熟悉程度。歡迎大家分享自己的作法與我交流 !
Thumbnail
本文介紹CSS Battle題目#73的解法,涵蓋了分層拆解圖形、使用grid排版、調整樣式等基礎技巧。
Thumbnail
本文介紹CSS Battle題目#73的解法,涵蓋了分層拆解圖形、使用grid排版、調整樣式等基礎技巧。
Thumbnail
是的,身為前端工程師的基本功!還是需要時不時拿出來打磨一番! 很多大公司的切版與前端是分開的,但不能因為碰不到就不去理解,假如要系統性的調整樣式,那麼你就一定要懂基礎,就好像你要調整微前端的架構,總不能連包板工具的設定都不會吧! 回到正題,這系列文章每個禮拜三都會更新一題CSS Battle的題
Thumbnail
是的,身為前端工程師的基本功!還是需要時不時拿出來打磨一番! 很多大公司的切版與前端是分開的,但不能因為碰不到就不去理解,假如要系統性的調整樣式,那麼你就一定要懂基礎,就好像你要調整微前端的架構,總不能連包板工具的設定都不會吧! 回到正題,這系列文章每個禮拜三都會更新一題CSS Battle的題
Thumbnail
在 2021 年的剛轉職成為前端工程師的時候,我在面試時滿常會被詢問到 JavaScript 中閉包的議題,當時候自己回答的滿差的,於是在 2022 年時,我寫了一系列的有關於函式程式設計鐵人賽的文章, 裡頭就有簡單提到有關於閉包的議題。
Thumbnail
在 2021 年的剛轉職成為前端工程師的時候,我在面試時滿常會被詢問到 JavaScript 中閉包的議題,當時候自己回答的滿差的,於是在 2022 年時,我寫了一系列的有關於函式程式設計鐵人賽的文章, 裡頭就有簡單提到有關於閉包的議題。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News