همه مقالات

مصاحبه فرانت‌اند

راهنمای کامل آمادگی مصاحبه فرانت‌اند: از جونیور تا سینیور

راهنمای کامل آمادگی مصاحبه فرانت‌اند: مراحل مصاحبه، انتظارات جونیور تا سینیور، پرتکرارترین سوالات جاوااسکریپت، ری‌اکت و Next.js و یک برنامه مطالعه ۴ هفته‌ای.

نوشته Mahdi Hosseini13 دقیقه مطالعه
فهرست مطالب

در این راهنما می‌بینید مصاحبه فرانت‌اند در عمل چه مراحلی دارد، از هر سطح (جونیور، میدل، سینیور) دقیقاً چه انتظاری می‌رود و کدام مفاهیم HTML، CSS، جاوااسکریپت، TypeScript، ری‌اکت، Next.js، پرفورمنس و system design بیشتر از همه پرسیده می‌شوند. در انتها هم یک برنامه مطالعه واقع‌بینانه ۴ هفته‌ای و چند توصیه کاربردی برای روز مصاحبه آمده تا به‌جای حدس زدن، برای سوال‌هایی که واقعاً پرسیده می‌شوند آماده شوید.

مراحل معمول مصاحبه فرانت‌اند

هر شرکتی فرایند خودش را دارد، اما بیشتر مصاحبه‌های فرانت‌اند، چه در شرکت‌های ایرانی و چه در موقعیت‌های ریموت خارجی، از همین چند مرحله ساخته می‌شوند. اینکه بدانید در کدام مرحله هستید، مشخص می‌کند روی چه چیزی تمرکز کنید.

۱. مصاحبه اولیه با HR یا ریکروتر

یک تماس ۲۰ تا ۳۰ دقیقه‌ای برای سنجیدن تناسب کلی: سابقه کاری، تکنولوژی‌هایی که با آن‌ها کار کرده‌اید، حقوق درخواستی، زمان شروع به کار و برای موقعیت‌های خارجی، سطح زبان انگلیسی. یک معرفی یک‌دقیقه‌ای و دقیق از خودتان آماده کنید و عدد حقوق مدنظرتان را از قبل بدانید.

۲. اسکرینینگ فنی یا آزمون

معمولاً یک تماس کوتاه با یک برنامه‌نویس یا یک آزمون آنلاین. سوال‌ها سریع و مفهومی‌اند: «فرق == و === چیست؟»، «useEffect با آرایه وابستگی خالی چه کار می‌کند؟»، «specificity در CSS چطور محاسبه می‌شود؟». خیلی از شرکت‌ها برای این مرحله از آزمون‌های چندگزینه‌ای استفاده می‌کنند. اینجا گستردگی دانش مهم‌تر از عمق است و تمرین با کوییزهای زمان‌دار بیشترین اثر را دارد.

۳. Live coding

در حالی که صفحه‌تان را share کرده‌اید، یک مسئله حل می‌کنید. در فرانت‌اند معمولاً یکی از این‌هاست:

  • یک کامپوننت کوچک UI مثل autocomplete، مودال، تب یا لیست infinite scroll با جاوااسکریپت خالص یا ری‌اکت.
  • یک تابع کاربردی: debounce، throttle، deep clone، پیاده‌سازی Promise.all یا flat کردن آرایه.
  • یک مسئله الگوریتمی ساده تا متوسط (آرایه، رشته، hash map). سوال‌های سخت LeetCode در مصاحبه فرانت‌اند کم پیش می‌آید.

مصاحبه‌کننده تقریباً به همین ترتیب به این‌ها اهمیت می‌دهد: نحوه توضیح دادن، توجه به edge caseها و درست کار کردن کد.

۴. تسک خانه (Take-home)

یک اپلیکیشن کوچک که در چند ساعت تا دو سه روز می‌سازید: گرفتن داده از API، نمایش لیست با فیلتر و صفحه‌بندی، مدیریت حالت‌های loading و error. بررسی‌کننده‌ها به ساختار پروژه، تقسیم‌بندی کامپوننت‌ها، مدیریت state، تایپ‌ها، تست‌ها و README نگاه می‌کنند. یک پروژه کوچک، تمیز و کامل خیلی بهتر از یک پروژه بلندپروازانه و نیمه‌کاره است.

۵. Frontend System Design (میدل به بالا و سینیور)

باید چیزی مثل news feed، ویجت چت، گالری تصاویر یا یک design system را طراحی کنید. بحث درباره معماری کامپوننت‌ها، data fetching و کش، مدیریت state، استراتژی رندر، پرفورمنس، دسترس‌پذیری و مدیریت خطاست. از سینیورها انتظار می‌رود خودشان این گفتگو را هدایت کنند.

۶. مصاحبه رفتاری (Behavioral)

سوال درباره تعارض در تیم، مسئولیت‌پذیری، اشتباه‌ها و همکاری با دیزاینر و بک‌اند. ۵ تا ۶ داستان واقعی از تجربه کاری‌تان با فرمت STAR (موقعیت، وظیفه، اقدام، نتیجه) آماده کنید و هر جا ممکن است، نتیجه را با عدد بگویید.

از جونیور، میدل و سینیور چه انتظاری می‌رود؟

یک سوال ثابت بسته به سطح، متفاوت ارزیابی می‌شود. «event loop را توضیح بده» برای جونیور یک سوال قبول/رد است، اما از سینیور انتظار می‌رود آن را به مشکلات واقعی، مثلاً long taskهایی که ورودی کاربر را بلاک می‌کنند، ربط بدهد.

حوزهجونیورمیدلسینیور
جاوااسکریپتمبانی محکم: scope، closure، آرایه‌ها، async/awaitevent loop، prototype، this، مدیریت خطادرک عمیق runtime، memory leak، trade-offهای پرفورمنس
ری‌اکتکامپوننت، props، state، hookهای پایهرفتار رندر، custom hook، memoization، data fetchingمعماری، مرز server/client، مدیریت state در مقیاس تیم
CSSbox model، flexbox، ریسپانسیوgrid، specificity، باگ‌های layout، معماری CSSdesign system، theming، پرفورمنس رندر
تستمی‌داند چرا تست مهم استunit test و component test می‌نویسداستراتژی تست تیم را تعریف می‌کند
System designانتظار نمی‌رودیک فیچر را end to end طراحی می‌کندطراحی کل اپ را هدایت می‌کند و trade-offها را توضیح می‌دهد
مسئولیتتسک‌های مشخص را انجام می‌دهدمالک فیچرهاستمالک نتیجه است، منتورینگ می‌کند، روی جهت فنی اثر می‌گذارد

درباره سطح خودتان صادق باشید. اپلای برای سینیور و جواب دادن در حد میدل، از اپلای برای میدل و فراتر رفتن از انتظارات، خیلی بدتر است.

مباحث اصلی و پرتکرارترین مفاهیم

HTML و CSS

خیلی از کاندیداها این بخش را دست‌کم می‌گیرند و امتیازهای ساده را از دست می‌دهند.

  • HTML معنایی (Semantic): کی از <button> و کی از <a> استفاده کنیم، تگ‌های <nav>، <main>، <article> و <section>، و اینکه چرا <div> کلیک‌پذیر مشکل دارد (فوکوس کیبورد ندارد و screen reader نقش آن را نمی‌فهمد).
  • Box model: content، padding، border و margin، و اینکه box-sizing: border-box چه چیزی را تغییر می‌دهد. margin collapsing بین المان‌های block عمودی یک سوال تکمیلی کلاسیک است.
  • Flexbox در برابر Grid: Flexbox برای چیدمان یک‌بعدی (یک سطر یا یک ستون) و Grid برای چیدمان دوبعدی. فرق justify-content و align-items، معنی flex: 1 و الگوی grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)) را بلد باشید.
  • Specificity: استایل inline بیشتر از ID، ID بیشتر از class/attribute/pseudo-class، و این‌ها بیشتر از selector المان. !important قوانین عادی را override می‌کند و :where() هیچ specificityای ندارد.
  • Position و stacking context: relative، absolute، fixed، sticky و اینکه چرا گاهی z-index «کار نمی‌کند» (چون transform یا opacity کمتر از ۱ یک stacking context جدید می‌سازد).
  • دسترس‌پذیری (a11y): متن alt، label برای inputها، مدیریت فوکوس در مودال، کنتراست رنگ، و استفاده از ARIA فقط وقتی HTML بومی کافی نیست.

برای تمرین: سوالات مصاحبه HTML و CSS سطح جونیور.

جاوااسکریپت

قلب تقریباً همه مصاحبه‌های فرانت‌اند همین‌جاست. اگر فقط برای یک مبحث وقت دارید، همین را مسلط شوید.

Closure. closure تابعی است که به متغیرهای scope محل تعریفش دسترسی دارد، حتی بعد از اینکه اجرای آن scope تمام شده باشد. معروف‌ترین سوال مصاحبه:

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0);
}
// خروجی: 3, 3, 3

for (let j = 0; j < 3; j++) {
  setTimeout(() => console.log(j), 0);
}
// خروجی: 0, 1, 2

var در سطح تابع scope دارد، پس هر سه callback یک i مشترک می‌بینند که موقع اجرا مقدارش 3 است. let برای هر تکرار حلقه یک binding جدید می‌سازد و هر callback مقدار مخصوص خودش را نگه می‌دارد.

Event loop. اول کد همگام (synchronous) اجرا می‌شود، بعد همه microtaskها (callbackهای Promise و queueMicrotask)، بعد یک macrotask (setTimeout، I/O، رویدادها)، دوباره microtaskها و همین‌طور ادامه.

console.log("1");
setTimeout(() => console.log("2"), 0);
Promise.resolve().then(() => console.log("3"));
queueMicrotask(() => console.log("4"));
console.log("5");
// خروجی: 1, 5, 3, 4, 2

اینکه بتوانید توضیح بدهید چرا خروجی این است، خیلی ارزشمندتر از حفظ کردنش است.

بقیه مباحث پرتکرار جاوااسکریپت:

  • this: بر اساس نحوه صدا زدن تابع تعیین می‌شود، نه محل تعریفش. arrow function خودش this ندارد و آن را از scope بیرونی می‌گیرد. call، apply و bind را بشناسید.
  • Promise و async/await: وضعیت‌ها (pending، fulfilled، rejected)، chaining، مدیریت خطا با try/catch و فرق Promise.all، Promise.allSettled، Promise.race و Promise.any.
  • Prototype: هر آبجکت یک [[Prototype]] داخلی دارد و جستجوی property در زنجیره prototype بالا می‌رود. class عمدتاً یک syntax روی همین مکانیزم است.
  • Hoisting: تعریف‌های var بالا برده می‌شوند و مقدار undefined می‌گیرند؛ let و const هم hoist می‌شوند ولی تا خط تعریف در temporal dead zone می‌مانند؛ function declarationها کامل hoist می‌شوند.
  • مقایسه و تساوی: === بدون تبدیل نوع مقایسه می‌کند و == تبدیل نوع انجام می‌دهد. null == undefined برابر true است، NaN === NaN برابر false است (از Number.isNaN استفاده کنید) و آبجکت‌ها با reference مقایسه می‌شوند.

یک گرم‌کردن رایج در live coding، نوشتن debounce است:

function debounce(fn, delay) {
  let timerId;
  return function (...args) {
    clearTimeout(timerId);
    timerId = setTimeout(() => fn.apply(this, args), delay);
  };
}

تمرین بر اساس سطح: سوالات جاوااسکریپت سطح جونیور و سوالات جاوااسکریپت سطح میدل.

TypeScript

امروز تقریباً در همه آگهی‌های فرانت‌اند اسم TypeScript هست. مصاحبه‌کننده معمولاً می‌خواهد ببیند از آن برای مدل کردن داده استفاده می‌کنید، نه فقط برای ساکت کردن کامپایلر.

  • Generics: نوشتن تابع و کامپوننت قابل استفاده مجدد با تایپ درست، و محدود کردن با extends.
  • Narrowing: typeof، instanceof، in، discriminated union و type guard سفارشی (value is User).
  • Utility typeها: Partial، Required، Pick، Omit، Record، ReturnType، Awaited.
  • type در برابر interface و unknown در برابر any: unknown مجبورتان می‌کند قبل از استفاده narrow کنید و به همین دلیل برای داده‌های بیرونی انتخاب امن‌تری است.
type ApiResult<T> =
  | { status: "success"; data: T }
  | { status: "error"; message: string };

function render<T>(result: ApiResult<T>) {
  if (result.status === "success") {
    return result.data; // narrow شده به T
  }
  return result.message; // narrow شده به string
}

برای تمرین سری بزنید به بانک سوالات TypeScript.

ری‌اکت

سوال‌های ری‌اکت روی فهم نحوه رندر شدن تمرکز دارند، نه حفظ اسم APIها.

  • رندر: کامپوننت وقتی دوباره رندر می‌شود که state خودش تغییر کند، والدش رندر شود یا contextی که مصرف می‌کند تغییر کند. re-render با به‌روزرسانی DOM یکی نیست؛ ری‌اکت اول خروجی را diff می‌کند.
  • قوانین hookها: hookها را فقط در سطح بالای کامپوننت یا custom hook صدا بزنید، چون ری‌اکت برای تطبیق state با هر hook به ترتیب صدا زدن‌ها تکیه می‌کند.
  • دام‌های useEffect: وابستگی‌های جاافتاده که باعث stale closure می‌شوند، حلقه بی‌نهایت از set کردن stateی که خودش وابستگی است، نداشتن cleanup برای subscription و timer، و استفاده از effect برای چیزی که باید موقع رندر محاسبه شود.
  • Key: key به ری‌اکت کمک می‌کند آیتم‌های لیست را بین رندرها تطبیق دهد. استفاده از index آرایه به‌عنوان key وقتی آیتم‌ها جابه‌جا، اضافه یا حذف شوند خراب می‌شود و ممکن است state یک سطر به سطر دیگر منتقل شود.
  • Memoization: React.memo، useMemo و useCallback فقط وقتی مفیدند که جلوی کار سنگین را بگیرند یا props را برای فرزندان memo شده از نظر reference ثابت نگه دارند. پیچیدن همه چیز در آن‌ها فقط هزینه اضافه دارد. اشاره کنید که React Compiler در پروژه‌هایی که فعالش کرده‌اند این کار را خودکار انجام می‌دهد.
  • مدیریت state: اول state محلی، اگر کامپوننت‌های هم‌سطح نیاز داشتند lift کردن state، context برای مقادیر سراسری کم‌تغییر (تم، احراز هویت)، و در صورت نیاز یک کتابخانه مثل Redux Toolkit یا Zustand، یا ابزار server state مثل TanStack Query. دلیل انتخابتان را توضیح دهید، نه فقط اسمش را.

یک باگ کلاسیک stale closure:

function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const id = setInterval(() => {
      setCount((c) => c + 1); // functional update مشکل count قدیمی را حل می‌کند
    }, 1000);
    return () => clearInterval(id);
  }, []);

  return <p>{count}</p>;
}

اگر به‌جایش setCount(count + 1) با آرایه وابستگی خالی بنویسید، شمارنده روی 1 می‌ماند، چون callback اینتروال همیشه مقدار اولیه count را می‌بیند.

تمرین: سوالات مصاحبه ری‌اکت سطح جونیور، سوالات ری‌اکت سطح میدل و سوالات مدیریت state.

Next.js

برای موقعیت‌های Next.js منتظر سوال درباره استراتژی‌های رندر و مدل App Router باشید.

  • SSR، SSG، ISR و CSR: HTML کی ساخته می‌شود (در هر درخواست، موقع build، موقع build با revalidate در پس‌زمینه، یا در مرورگر) و trade-off بین تازگی داده، سرعت و هزینه سرور.
  • App Router: مسیریابی مبتنی بر فایل با فایل‌های layout، page، loading و error، layoutهای تودرتو و route groupها.
  • Server Component در برابر Client Component: کامپوننت‌ها به‌صورت پیش‌فرض Server Component هستند؛ "use client" را فقط وقتی اضافه کنید که state، effect، event handler یا API مرورگر لازم دارید. Server Componentها جاوااسکریپت ارسالی به مرورگر را کم می‌کنند و می‌توانند مستقیم داده بگیرند.
  • کش: بدانید رفتار کش بین نسخه‌ها تغییر کرده است. در نسخه‌های اخیر درخواست‌های fetch به‌صورت پیش‌فرض کش نمی‌شوند و باید صریحاً کش را فعال کنید. revalidate زمانی و on-demand را توضیح دهید و بگویید با کدام نسخه کار کرده‌اید.

تمرین: سوالات Next.js سطح میدل.

پرفورمنس و Core Web Vitals

از میدل و سینیور انتظار می‌رود درباره پرفورمنس با معیارهای واقعی حرف بزنند:

  • LCP (Largest Contentful Paint): مقدار خوب ۲.۵ ثانیه یا کمتر است. با بهینه‌سازی تصاویر، preload کردن تصویر اصلی، رندر سمت سرور و پاسخ سریع سرور بهتر می‌شود.
  • INP (Interaction to Next Paint): مقدار خوب ۲۰۰ میلی‌ثانیه یا کمتر است و از ۲۰۲۴ جای FID را گرفته. با شکستن long taskها، کم کردن جاوااسکریپت و پرهیز از کار سنگین در event handlerها بهتر می‌شود.
  • CLS (Cumulative Layout Shift): مقدار خوب ۰.۱ یا کمتر است. با رزرو فضا برای تصاویر، تبلیغات و embedها و مدیریت درست فونت‌ها اصلاح می‌شود.

code splitting، lazy loading، virtualization لیست‌ها و پیدا کردن long taskها در پنل Performance کروم را هم بلد باشید.

Frontend System Design

یک ساختار ثابت داشته باشید تا سر جلسه قفل نکنید:

  1. شفاف‌سازی نیازمندی‌ها: نیازمندی‌های عملکردی (کاربر چه کارهایی می‌کند) و غیرعملکردی (مقیاس، دستگاه‌ها، آفلاین، دسترس‌پذیری، SEO).
  2. معماری سطح بالا: کامپوننت‌های اصلی و نحوه ارتباطشان.
  3. مدل داده و API: چه داده‌ای لازم است، REST یا GraphQL، صفحه‌بندی (cursor یا offset)، به‌روزرسانی real-time (polling، SSE، WebSocket).
  4. State و کش: چه چیزی سمت سرور است، چه چیزی سمت کلاینت و چطور همگام می‌مانند.
  5. پرفورمنس، دسترس‌پذیری و مدیریت خطا: حالت‌های loading، retry، optimistic update، ناوبری با کیبورد.
  6. Trade-offها: بگویید با وقت بیشتر یا در مقیاس بزرگ‌تر چه چیزی را تغییر می‌دادید.

تمرین: سوالات frontend system design سطح سینیور.

اشتباهات رایج کاندیداها

  • حفظ کردن جواب بدون فهمیدن. مصاحبه‌کننده دقیقاً برای همین سوال تکمیلی می‌پرسد و رایج‌ترینش «چرا؟» است.
  • کد زدن در سکوت. قبل از تایپ، رویکردتان را بلند توضیح دهید. راه‌حل درستی که در سکوت نوشته شود، امتیاز کمتری از راه‌حل نیمه‌درست با استدلال شفاف می‌گیرد.
  • نادیده گرفتن edge caseها. آرایه خالی، مقدار null، خطای شبکه، دابل‌کلیک، متن خیلی طولانی.
  • بی‌توجهی به HTML، CSS و دسترس‌پذیری. امتیازهای ساده‌ای که خیلی‌ها از دست می‌دهند.
  • Over-engineering در تسک خانه. اضافه کردن Redux، micro-frontend و design system اختصاصی به یک اپ دوصفحه‌ای نشانه قضاوت فنی ضعیف است.
  • جواب‌های کلی در مصاحبه رفتاری. «با تیم همکاری کردیم و حلش کردیم» چیزی نمی‌گوید. بگویید خودتان چه کردید و چه چیزی تغییر کرد.
  • سوال نپرسیدن در پایان. حس بی‌علاقگی منتقل می‌کند. درباره تیم، فرایند code review و معیار موفقیت در این نقش بپرسید.

برنامه مطالعه ۴ هفته‌ای

این برنامه با فرض روزی ۱.۵ تا ۲ ساعت در روزهای کاری و کمی بیشتر در آخر هفته نوشته شده. عمق هر بخش را با سطح هدفتان تنظیم کنید.

هفته اول: مبانی جاوااسکریپت

  • scope، closure، hoisting، this، prototype و مقایسه.
  • event loop، Promise و async/await.
  • پیاده‌سازی دستی: debounce، throttle، Promise.all، deep clone و Array.prototype.map.
  • هر روز یک کوییز زمان‌دار جاوااسکریپت بزنید و هر جواب غلط را آن‌قدر مرور کنید تا بتوانید توضیحش دهید.

هفته دوم: HTML، CSS و TypeScript

  • HTML معنایی و مبانی دسترس‌پذیری؛ یک صفحه را فقط با کیبورد تست کنید.
  • دو سه layout را از صفر با Flexbox و Grid بسازید.
  • specificity، stacking context و طراحی ریسپانسیو.
  • generics، narrowing و utility typeها در TypeScript؛ یک پروژه کوچک JS را به TS تبدیل کنید.

هفته سوم: ری‌اکت و Next.js

  • رفتار رندر، قوانین hookها، cleanup و وابستگی‌های useEffect.
  • ساخت کامپوننت‌های رایج مصاحبه: autocomplete با fetch دیبانس‌شده، مودال با focus trap، لیست صفحه‌بندی‌شده با حالت loading و error.
  • انتخاب ابزار مدیریت state و اینکه کی سراغ کتابخانه‌های server state برویم.
  • استراتژی‌های رندر Next.js، Server و Client Component، کش و revalidate.

هفته چهارم: پرفورمنس، system design و مصاحبه آزمایشی

  • Core Web Vitals؛ یکی از پروژه‌های خودتان را با Lighthouse بررسی کنید و دو مشکل را رفع کنید.
  • دو سه مسئله system design را با ساختار بالا بلند تمرین کنید.
  • ۵ تا ۶ داستان STAR آماده کنید.
  • حداقل دو مصاحبه آزمایشی (mock interview) با یک دوست یا همکار داشته باشید، شامل live coding با محدودیت زمان.
  • بر اساس نتیجه کوییزها، ضعیف‌ترین مباحث را دوباره مرور کنید.

توصیه‌هایی برای روز مصاحبه

  • ۱۵ دقیقه زودتر تجهیزات را تست کنید: دوربین، میکروفون، اینترنت، share صفحه و ادیتور یا IDE آنلاینی که قرار است استفاده شود. اگر اینترنتتان ناپایدار است، یک راه جایگزین (مثلاً هات‌اسپات موبایل) آماده داشته باشید.
  • مسئله را با کلمات خودتان تکرار کنید و قبل از کد زدن سوال‌های شفاف‌کننده بپرسید.
  • ساده شروع کنید، بعد بهتر کنید. یک راه‌حل brute-force که کار می‌کند و بعد بهینه می‌شود، از یک راه‌حل هوشمندانه نیمه‌کاره بهتر است.
  • بگویید «نمی‌دانم، اما این‌طور پیدایش می‌کنم» وقتی واقعاً نمی‌دانید. حدس زدن با اعتمادبه‌نفس و اشتباه بودن، ضرر بیشتری دارد.
  • کدتان را تست کنید؛ یک ورودی نمونه و یک edge case را قدم به قدم دنبال کنید.
  • زمان را مدیریت کنید. اگر چند دقیقه گیر کردید، بگویید و راهنمایی بخواهید؛ این بخش عادی فرایند است.
  • بعد از مصاحبه سوال‌ها را یادداشت کنید. این یادداشت‌ها بهترین منبع برای مصاحبه بعدی‌اند.

جمع‌بندی

مصاحبه فرانت‌اند بیشتر به تسلط روی مبانی امتیاز می‌دهد تا آشنایی با جدیدترین کتابخانه. روی جاوااسکریپت، نحوه رندر در ری‌اکت و توضیح شفاف تمرکز کنید، بدانید از سطح هدفتان چه انتظاری می‌رود و در شرایط واقعی تمرین کنید. سریع‌ترین راه پیدا کردن نقاط ضعف، سنجیدن منظم خودتان است. تمرین را با کوییزهای سطح‌بندی‌شده در سوالات مصاحبه فرانت‌اند DevTier شروع کنید و پیشرفتتان را مبحث به مبحث دنبال کنید.

این موضوع‌ها را تمرین کن

مقالات دیگر