Dưới đây là bộ đáp án chi tiết và chuyên sâu cho các câu hỏi phỏng vấn Frontend năm 2026, được tổng hợp dựa trên các tiêu chuẩn kỹ thuật mới nhất của React 19 và Next.js 16.
I. JavaScript & TypeScript Core
1. Event Loop & Task Prioritization: Microtask queue (Promises, async/await, MutationObserver) có mức ưu tiên cao hơn Macrotask queue (setTimeout, I/O, events). Microtasks được thực thi ngay sau mã đồng bộ và phải được giải phóng hoàn toàn trước khi trình duyệt thực hiện bước repaint (vẽ lại) tiếp theo. Hiện tượng "Starvation" (đói tài nguyên) xảy ra khi một chuỗi Microtask đệ quy liên tục thêm tác vụ mới vào hàng đợi, khiến Macrotasks và quá trình render bị chặn vô hạn, dẫn đến ứng dụng bị treo hoàn toàn.
2. Memory Management (Mark-and-Sweep & WeakMap): Cơ chế "Mark-and-Sweep" bắt đầu từ các đối tượng gốc (roots), đánh dấu tất cả đối tượng có thể truy cập được là "alive" và thu hồi bộ nhớ của các đối tượng không được đánh dấu. WeakMap và WeakSet giữ các tham chiếu yếu (weak references) đến đối tượng, nghĩa là chúng không ngăn cản Garbage Collector thu hồi bộ nhớ nếu đối tượng đó không còn tham chiếu mạnh nào khác. Đây là công cụ đắc lực để lưu trữ metadata cho DOM nodes hoặc cache mà không lo rò rỉ bộ nhớ (memory leaks).
3. Object Copying Mechanics:
shallow copy: Chỉ sao chép các thuộc tính cấp 1, các đối tượng lồng nhau vẫn dùng chung tham chiếu.
deep copy: Sao chép hoàn toàn cấu trúc đối tượng.
So sánh:
structuredClone()là Web API bản địa nhanh nhất, hỗ trợMap,Set, và tham chiếu vòng, nhưng không sao chép được hàm hay DOM nodes.JSON.parse(JSON.stringify())rất chậm và mất dữ liệu đặc biệt (Date, RegExp).lodash.cloneDeepxử lý được mọi trường hợp nhưng làm tăng kích thước bundle thêm khoảng 17KB.
4. Reference Logic & Copy Algorithms: Khi gán b = a, cả hai biến cùng trỏ về một vùng nhớ; thay đổi thuộc tính của b sẽ trực tiếp thay đổi a. Để sao chép nested object, các thư viện như Lodash sử dụng thuật toán đệ quy kết hợp với một bản đồ (Map) để theo dõi các đối tượng đã xử lý, giúp tránh lặp vô hạn khi gặp tham chiếu vòng và bảo toàn các kiểu dữ liệu phức tạp.
5. Promise.all vs Await tuần tự: Sử dụng Promise.all khi các tác vụ không phụ thuộc lẫn nhau để thực thi song song, giúp giảm tổng thời gian chờ xuống bằng thời gian của task lâu nhất. Promise.allSettled mang lại sự ổn định vì nó đợi tất cả promises kết thúc (bất kể thành công hay thất bại) và trả về mảng kết quả chi tiết, tránh việc một task fail làm sập toàn bộ chuỗi như Promise.all.
6. Conditional Performance (Switch vs If-Else): switch thường nhanh hơn if-else khi có nhiều điều kiện vì trình biên dịch (như V8) có thể tạo ra một "jump table" (bảng nhảy) cho phép truy cập trực tiếp vào khối lệnh cần thực thi (O(1)) thay vì kiểm tra tuần tự từng nhánh (O(n)).
7. TypeScript Evolution (Unions vs Enum): Năm 2026, "String Literal Unions" ('A' | 'B') kết hợp as const được ưu tiên vì chúng biến mất hoàn toàn sau khi biên dịch (zero bundle size), trong khi Enum tạo ra mã JavaScript dư thừa. Ngoài ra, numeric enums thiếu an toàn kiểu vì cho phép gán bất kỳ giá trị số nào.
8. Advanced Typing (infer & satisfies): infer cho phép trích xuất kiểu dữ liệu từ bên trong một cấu trúc phức tạp trong conditional types (ví dụ: lấy kiểu trả về của một hàm). Toán tử satisfies giúp kiểm tra xem một đối tượng có khớp với interface không mà vẫn giữ nguyên kiểu dữ liệu literal của nó, giúp IntelliSense hoạt động chính xác hơn so với việc ép kiểu bằng as.
II. React 19 Core & Hooks
9. useMemo ghi nhớ hàm: Có, useMemo hoàn toàn có thể ghi nhớ định nghĩa hàm nếu hàm đó là giá trị trả về của khối logic tính toán bên trong. Tuy nhiên, useCallback là cú pháp viết tắt chuyên dụng cho mục đích này.
10. useCallback use cases: Ngoài tối ưu re-render, useCallback quan trọng để đảm bảo tính ổn định tham chiếu (referential stability) khi truyền hàm làm dependency cho các hook khác (useEffect, useMemo) hoặc ngăn chặn re-render cho các component con được bọc trong React.memo.
11. Internal Hook Storage: React lưu trữ các giá trị hook dưới dạng một danh sách liên kết (Linked List) gắn vào thuộc tính memoizedState của mỗi node Fiber. Thứ tự gọi Hook là "linh thiêng" vì React dựa vào thứ tự thực thi để ánh xạ đúng trạng thái cũ với Hook tương ứng; nếu gọi Hook trong điều kiện, danh sách này sẽ bị lệch chỉ mục.
12. useMemo vs useEffect (Cùng logic, khác kết quả):
useMemo: Chạy đồng bộ trong quá trình Render. Nếu có logic impure (side effect) bên trong, nó có thể làm chậm hoặc treo UI render.useEffect: Chạy bất đồng bộ sau khi giao diện đã vẽ xong (paint).Ví dụ: Nếu logic là cập nhật một biến global,
useMemosẽ làm biến đó thay đổi ngay khi render, cònuseEffectsẽ đợi sau khi user thấy giao diện mới thay đổi, dẫn đến sự sai lệch về thời điểm hiển thị dữ liệu.
13. DOM Sync (useEffect vs useLayoutEffect): useLayoutEffect chạy đồng bộ ngay sau khi DOM thay đổi nhưng trước khi trình duyệt vẽ (paint). Nó được dùng để đo đạc kích thước phần tử và cập nhật UI ngay lập tức để tránh hiện tượng nhấp nháy (flickering), trong khi useEffect (chạy sau paint) sẽ khiến user thấy UI cũ trong vài miligiây.
14. Function Component Lifecycle: Gồm 3 giai đoạn: Mount (thêm vào DOM), Update (render lại), và Unmount (gỡ bỏ). useEffect chạy sau render; clean-up function chạy ngay trước khi component unmount hoặc trước khi effect đó chạy lại ở lần render tiếp theo để dọn dẹp tài nguyên cũ.
15. Rules of Hooks: Không gọi Hook trong vòng lặp hay điều kiện vì React quản lý trạng thái dựa trên thứ tự gọi trong danh sách liên kết của Fiber. Nếu thứ tự thay đổi, React không thể xác định state nào thuộc về hook nào.
16. useRef Mechanics (React 19): useRef trả về một object ổn định {current:...} tồn tại xuyên suốt vòng đời component mà không kích hoạt re-render khi giá trị thay đổi. React 19 cho phép truyền ref như một prop thông thường xuống component con, loại bỏ nhu cầu sử dụng forwardRef.
17. Context API Optimization: Chia nhỏ Context (Context Splitting) để cô lập các state thay đổi thường xuyên, hoặc bọc component con trong useMemo/React.memo để tránh re-render khi giá trị Context của cha thay đổi nhưng component con không sử dụng.
18. New React 19 Hooks:
useActionState: Tự động quản lý trạng thái form (pending, data, error).useOptimistic: Hiển thị kết quả dự đoán ngay lập tức và tự động rollback nếu server lỗi.use(): Unwrap Promises hoặc Context trực tiếp trong hàm render (có thể gọi trongif/else).
19. React Compiler Rules: Trình biên dịch tự động hóa memoization ở mức build-time. Lập trình viên phải tuân thủ tính thuần khiết (idempotency) và tính bất biến (immutability) của props/state; nếu vi phạm, Compiler sẽ "bỏ qua" tối ưu hóa cho component đó.
III. Next.js 16+ & Rendering Strategies
20. Hydration Mechanism: Server gửi HTML tĩnh kèm dữ liệu khởi tạo trong thẻ <script id="__NEXT_DATA__">. Tại trình duyệt, React đọc dữ liệu này, tái tạo Virtual DOM và thực hiện bước "gắn" (attach) các trình lắng nghe sự kiện vào các node DOM thật đã có sẵn mà không cần tạo lại chúng.
21. Rendering Comparison (SSG, SSR, ISR, PPR): PPR (Partial Prerendering) là sự kết hợp hoàn hảo: Server gửi một "vỏ tĩnh" (static shell) ngay lập tức, sau đó stream các phần động (dynamic components) song song qua Suspense. Điều này giúp triệt tiêu hiện tượng "Network Waterfall" của SSR truyền thống.
22. RSC to Client Serialization: Chỉ các dữ liệu có thể tuần tự hóa (serializable) mới được truyền qua ranh giới Server-Client. Hàm, class instances hoặc DOM nodes không thể serialize và sẽ gây lỗi.
23. Next.js 16 Caching: Sử dụng directive use cache để ghi nhớ kết quả component/hàm. API revalidateTag() dùng để làm mới cache trong background (stale-while-revalidate), còn updateTag() (chỉ dùng trong Server Actions) sẽ xóa cache ngay lập tức để thực hiện cơ chế "read-your-writes".
IV. Styling, Performance & Situations
24. Tailwind v4 Oxide Engine: Tailwind v4 sử dụng engine viết bằng Rust (Oxide) với cơ chế "Source Detection" tự động quét các file nguồn để chỉ tạo ra CSS cho những class thực sự được sử dụng, giúp tốc độ build nhanh hơn 35-50%.
25. Critical Rendering Path (CRP) Deep Dive: Khi gặp thẻ <script> (không có async/defer), trình duyệt dừng parse HTML để tải và thực thi mã. Thuộc tính transform và opacity hiệu quả hơn vì chúng được xử lý bởi Compositor thread, bỏ qua giai đoạn Layout và Paint đắt đỏ.
26. Default Behavior & Passive Listeners: Ngoài preventDefault(), sử dụng passive: true trong event listeners giúp trình duyệt biết handler sẽ không chặn cuộn trang, cải thiện độ mượt mà của UI.
27. Storage Comparison:
Local Storage: 5-10MB, vĩnh viễn, không gửi lên server.
Session Storage: 5MB, xóa khi đóng tab.
Cookies: 4KB, gửi kèm mọi request, hỗ trợ bảo mật qua
HttpOnlyvàSameSite.
28. XSS/CSRF Protection: LocalStorage dễ bị XSS vì JavaScript truy cập được. Cookies dùng HttpOnly để chống XSS, Secure để bắt buộc HTTPS, và SameSite=Strict/Lax để chặn tấn công CSRF.
29. Refresh Token Rotation (Next.js 16 Proxy): Sử dụng file proxy.ts (thay thế middleware truyền thống) để đánh chặn request. Nếu Access Token hết hạn, proxy sẽ gọi API refresh token, cập nhật HttpOnly cookies mới và cho phép request tiếp tục với thông tin mới.
30. Centralized Policy Engine (RBAC): Sử dụng một engine tập trung (như Oso) định nghĩa các quy tắc phân quyền trong file riêng biệt. Logic này được áp dụng đồng nhất tại Server Components (để render UI) và Server Actions (để bảo mật thực thi), ngăn chặn user chỉnh sửa mã client để gian lận quyền hạn.
31. 10.000 Input Form Design: Lưu trữ từng trường (field-level saving) lên server ngay khi người dùng onBlur. Sử dụng Redis để lưu bản nháp (draft) dựa trên Fingerprint trình duyệt hoặc Session Cookie, cho phép người dùng quay lại nhập tiếp mà không cần đăng nhập hay dùng client storage.
32. 3 Tab Lag Solution (React 19): Sử dụng useTransition để đánh dấu việc chuyển tab là cập nhật không ưu tiên, giữ UI luôn phản hồi. Áp dụng component <Activity> (React 19.2) để ẩn tab cũ mà không mất state/DOM, giúp hiển thị lại tức thì khi quay lại.
33. Pagination Race Condition: Sử dụng AbortController. Ngay khi người dùng chuyển sang trang mới, gọi controller.abort() để hủy request của trang cũ đang chạy, đảm bảo dữ liệu hiển thị cuối cùng luôn khớp với trang mới nhất.









