كيف تجتاز مقابلة JavaScript: المستوى المتقدم

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

كيف تجتاز مقابلة JavaScript: أهم أسئلة المستوى المتقدم

\n\n

مقابلة العمل لوظيفة مطور JavaScript كبير (Senior) أو مهندس Node.js ليست مجرد اختبار لقواعد اللغة. يريد المحاورون رؤية فهم عميق للغة: كيف يعمل Event Loop، ما هو السياق this في الحقيقة، وكيف تتجنب "الجحيم" من التداخل عند العمل مع العمليات غير المتزامنة. في هذه المقالة، سنحلل الأسئلة الأكثر شيوعًا وخبثًا التي تُطرح على المستوى المتقدم. استعد ليس فقط لقراءة الإجابات، بل لفهم الآليات.

\n\n

1. Event Loop، مكدس الاستدعاءات (Call Stack) والمهام الصغيرة (Microtasks vs Macrotasks)

\n\n

هذه هي على الأرجح المجموعة الأكثر شيوعًا في مقابلات Node.js. السؤال هو: "ماذا سيطبع هذا الكود وبأي ترتيب؟".

\n\n
console.log('1');\n\nsetTimeout(() => console.log('2'), 0);\n\nPromise.resolve().then(() => console.log('3'));\n\nprocess.nextTick(() => console.log('4'));\n\nconsole.log('5');
\n\n

الإجابة الصحيحة: 1, 5, 4, 3, 2.

\n\n

التحليل:

\n
    \n
  • الكود المتزامن (Synchronous code) (1, 5) يُنفذ أولاً.
  • \n
  • process.nextTick() هي مهمة صغيرة (microtask) ذات أولوية قصوى. تُنفذ فورًا بعد العملية الحالية، ولكن قبل أي مهام صغيرة أخرى (Promise) ومهام كبيرة (macrotasks) مثل setTimeout.
  • \n
  • Promise.then() هي أيضًا مهمة صغيرة، لكن أولويتها أقل من nextTick.
  • \n
  • setTimeout(cb, 0) هي مهمة كبيرة (macrotask). تُنفذ فقط بعد أن يتم تفريغ مكدس الاستدعاءات وجميع المهام الصغيرة (جميع nextTick و Promise) بالكامل.
  • \n
\n\n

كيف تجيب بشكل صحيح: اشرح أن Node.js له مراحل (Phases) في Event Loop. المهام الصغيرة (process.nextTick و Promise) تُعالج بين المراحل. المهام الكبيرة (setTimeout, setInterval, I/O) تُعالج داخل المراحل. nextTick هو قائمة انتظار غير قياسية ولكنها مهمة جدًا، ويمكنها حظر Event Loop إذا استُخدمت بشكل متكرر (Recursively).

\n\n

2. السياق this و"فقدانه"

\n\n

السؤال: "كيف يعمل this في JavaScript؟ أعط مثالاً حيث يُفقد this، وكيف تصلح ذلك".

\n\n

المستوى المتقدم يعني أنك تعرف القواعد الأربع:

\n
    \n
  1. الربط الجديد (New binding) — عند استدعاء دالة باستخدام new، يشير this إلى الكائن الجديد الذي تم إنشاؤه.
  2. \n
  3. الربط الصريح (Explicit binding) — call, apply, bind.
  4. \n
  5. الربط الضمني (Implicit binding) — عندما تُستدعى الدالة كطريقة لكائن (obj.method()).
  6. \n
  7. الافتراضي (Default) — الكائن العام (global في Node.js، window في المتصفح) أو undefined في الوضع الصارم (Strict mode).
  8. \n
\n\n

مثال على فقدان السياق:

\n
const user = {\n  name: 'Alice',\n  greet() {\n    console.log(`Hello, ${this.name}`);\n  }\n};\n\nconst greetFn = user.greet;\ngreetFn(); // Hello, undefined
\n\n

لماذا؟ قمنا بتعيين الطريقة إلى متغير. الآن greetFn() تُستدعى بدون سياق الكائن (user). this يرتبط بالكائن العام (أو undefined في الوضع الصارم).

\n\n

كيف تصلح:

\n
    \n
  • استخدم bind: const greetFn = user.greet.bind(user);
  • \n
  • استخدم دالة السهم (Arrow function) (ليس لها this خاص بها، بل تأخذه من السياق المعجمي الخارجي).
  • \n
  • استدعِ عبر call/apply: greetFn.call(user).
  • \n
\n\n

سؤال إضافي: "وماذا سيحدث إذا مررنا user.greet إلى setTimeout؟" — نفس تأثير فقدان السياق. يُصلح باستخدام bind أو دالة السهم في الكولباك (Callback).

\n\n

3. الإغلاقات (Closures)

المدونات

توصيات الكتب