درود دوستان. توی قسمت دوم از مجموعه پستهای سوالات مصاحبه فرانتاند میخوایم ۱۰ تا سوال زیر رو بررسی کنیم:
۱۱. منظور از Mobile-first Strategy چیه؟
۱۲. Garbage Collection توی جاوااسکریپت چیه؟
۱۳. متدهای HEAD و OPTION چه تفاوتهایی با هم دارن؟
۱۴. چند تا از Best Practice های تستنویسی رو میشناسین؟
۱۵. دستور git cherry-pick چکار میکنه؟
۱۶. هدف از User Agent توی مرورگرها چیه؟
۱۷. Node و Element توی DOM چه تفاوتهایی با هم دارن؟
۱۸. توی جاوااسکریپت Syntax Error و Type Error چه تفاوتهایی با هم دارن؟
۱۹. DNS چیه؟
۲۰. چرا از Shallow Rendering توی تستنویسی استفاده کنیم؟
قبل از شروع پیشنهاد میکنم پست مقدمهٔ این مجموعه سوالات رو بخونین:
قبل از ادامه میخوام یادی کنیم از عزیز. امیدوارم روحش شاد باشه و در آرامش ✨💚
۱۱. منظور از Mobile-first Strategy چیه؟
Mobile-first Strategy یک روش و یک استراتژی طراحی صفحات وب (UI و UX) هست که توی اون همونطور که از عنوان یعنی Mobile-first مشخصه، دستگاههای موبایلی به عنوان اولویت اصلی برای طراحی صفحات قرار میگیرن و بعد پلتفرمهای دیگه مثل دسکتاپ.
توی روشهای قدیم، معمولاً صفحات ابتدا برای پلتفرمهای دستکاپ طراحی میشد و بعد در صورت نیاز برای پلتفرمهای موبایلی. اما با گسترش اینترنت و توجه بیشتر مردم به دستگاههای موبایلی، چیزی که اهمیت بیشتری پیدا کرده رابط کاربری توی این دستگاهها هست و به همین خاطر خیلی از کسب و کارها دستگاههای موبایلی رو به عنوان اولویت اصلی قرار میدن. به این استراتژی طراحی میگیم Mobile-first Strategy.
۱۲. Garbage Collection توی جاوااسکریپت چیه؟
Garbage Collection به پروسهٔ آزادسازی خودکار حافظه گفته میشه. توی این پروسه، جاوااسکریپت به طور خودکار مقادیری که دیگه توی برنامه مورد استفاده قرار نمیگیرن رو از حافظه پاک میکنه تا فضای حافظه آزاد بشه.
مثلاً متغیرهایی که توی Scope های داخلی یا توابع تعریف میکنیم، بعد از اینکه کار اون Scope یا تابع تموم بشه، اون متغیرها هم از حافظه پاک میشن. اما برای مثال متغیرهای گلوبال که همیشه در دسترس هستن، توسط Garbage Collector حذف نمیشن و تا آخر توی حافظه حضور دارن.
var iAmGlobal = "Hi"; function run() { const iAmLocal = "Hi"; // ... } run();
توی این کد، وقتی کار تابع run به پایان میرسه، متغیری که داخل این تابع هست هم از بین میره و از حافظه پاک میشه. اما متغیر خط ۱ تا پایان کار برنامه قابل دسترس هست و Garbage Collector کاری با اون نداره.
۱۳. متدهای HEAD و OPTION چه تفاوتهایی با هم دارن؟
توی مبحث RESTful API در کنار متدهای پرکاربردی مثل GET و POST، دو متد با کاربرد خاص وجود داره به اسمهای HEAD و OPTION.
متد HEAD: وقتی توی یک درخواست HTTP از متد HEAD استفاده میکنیم، به معنی هست که از Response فقط به اطلاعات Header احتیاج داریم. بنابراین توی Response این درخواست، body وجود نخواهد داشت.
متد OPTION: اگه میخوایم اطلاعاتی کلی درباره قوانین و نحوهٔ تعامل با API مد نظر (مثل متدهای HTTP قابل استفاده و یا مجوز CORS) داشته باشیم، از این متد استفاده میکنیم. شاید دقت کرده باشین که مرورگر هنگام بررسی CORS، ابتدا یک درخواست با متد OPTION به آدرس مد نظر میزنه تا CORS رو بررسی کنه.
۱۴. چند تا از Best Practice های تستنویسی رو میشناسین؟
موارد زیر چند Best Practice برای تست کردن هر برنامهای هست:
۱. خوانایی تستها: تستهای ما باید اونقدر واضح باشن که وقتی یک توسعهدهندهٔ دیگه اونها رو میبینه بتونه به آسونی متوجه اونها بشه.
۲. عنوان تستها: همونطور که میدونیم تستها معمولاً توی محیط ترمینال اجرا میشن و وقتی یک تست Fail میشه باید دقیقاً بدونیم چه تستی و چرا Fail شده. برای همین هنگام نامگذاری تستها باید مشخص کنیم که: چه چیزی قراره تست بشه؟ تحت چه شرایطی؟ خروجی مورد انتظار چی هست؟
// 1. The unit under test describe('Products Service', () => { describe('Add new product', () => { // 2. scenario and 3. expectation it('When no price is specified, then the product status is pending approval', () => { const newProduct = new ProductService().add(...); expect(newProduct.status).to.equal('pendingApproval'); }); }); });
۳. الگوی AAA: این الگو میگه بهتره تستهامون رو به ۳ قسمت مجزا تقسیم کنیم:
۱. Arrange: کدهایی که مخصوص راهاندازی و آمادهسازی تست هست
۲. Act: کدهایی که مخصوص اجرای تست هست
۳. Assert: کدهایی که مخصوص بررسی و مقایسهٔ خروجی تست با چیزی که انتظار داریم هست
describe("Customer classifier", () => { test("When customer spent more than $500, should be classified as premium", () => { //Arrange const customerToClassify = { spent: 505, joined: new Date(), id: 1 }; const DBStub = sinon.stub(dataAccess, "getCustomer").reply({ id: 1, classification: "regular" }); //Act const receivedClassification = customerClassifier.classifyCustomer(customerToClassify); //Assert expect(receivedClassification).toMatch("premium"); }); });
۴. تست کردن فقط متدهای Public: وقتی API ها و یا متدهای Public رو تست میکنیم، مطمئن میشیم که متدهای درونی و Private هم تست میشن. بنابراین نیازی به تستنویسی مجزا برای اونها نیست.
۵. استفاده از ابزارهای تولید دیتای Fake: بجای استفاده از کلماتی مثل Foo و Bar و لورم ایپسوم، بهتره از کتابخونههایی استفاده کنیم که مخصوص تولید کردن دیتای Fake هستن تا بتونیم اطلاعاتی متنوعتر و واقعیتر داشته باشیم.
برای مشاهدهٔ لیست کامل میتونین رو ببینین.
۱۵. دستور git cherry-pick چکار میکنه؟
فرض کنیم توی یک ریپازیتوری مشغول کار روی یک برنچ هستیم. از طرفی برنچهای دیگهای هم وجود داره که توسط خودمون یا افراد دیگه داره روی اونها کار میشه. حالا میخوایم تغییراتی که توی یکی از برنچها وجود داره رو اضافه کنیم به برنچ خودمون. شاید به ذهنمون برسه که از دستور git merge استفاده کنیم. اما همونطور که میدونیم استفاده از این دستور کل برنچ مد نظر به همراه کامیتهای اون رو با برنچ ما ادغام میکنه. گاهی اوقات ما فقط به یک کامیت خاص احتیاج داریم که به برنچ خودمون اضافه کنیم. برای اینکار دستور git cherry-pick به کارمون میاد.
نحوهٔ استفاده از دستور git cherry-pick به این صورت هست:
git cherry-pick <commit hash>
برای استفاده از این دستور، باید Hash کامیت مد نظرمون رو بدونیم. با اجرای دستور بالا تغییراتی که توی کامیت مد نظر وجود داره به برنچ ما اضافه میشه. دقت کنیم که این دستور یک کامیت جدید با یک Hash جدید برامون میسازه.
۱۶. هدف از User Agent توی مرورگرها چیه؟
User Agent یک رشته هست که مرورگر اون رو توی هدر درخواستهای HTTP به سرور ارسال میکنه و حاوی اطلاعاتی مثل اسم و ورژن مرورگر، سیستم عامل، نوع دستگاه و ویژگیهایی مثل رزولوشن صفحه نمایش هست. با این کار، سرور میتونه پاسخ مناسبتری به این درخواست بده. مثلاً اگه کاربری با استفاده از موبایل میخواد از وبسایت ما دیدن کنه، توی سرور با بررسی کردن User Agent میتونیم ورژن موبایلی برنامهمون رو به اون کاربر ارائه بدیم.
User Agent به این صورت توی درخواست دیده میشه:
GET /example.html HTTP/1.1 Host: www.example.com <<User-Agent>>: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.1 Safari/537.36
نکتهای که باید در نظر داشته باشیم اینه که این رشته میتونه توسط ابزارهایی مثل اکستنشنهای مرورگر دستکاری بشه. بنابراین محل مناسبی برای پاس دادن اطلاعات امنیتی و حساس نیست.
۱۷. Node و Element توی DOM چه تفاوتهایی با هم دارن؟
همونطور که میدونیم یک صفحهٔ HTML از اجزای مختلفی مثل تگها، متنها، کامنتها و ... تشکیل میشه. برای دسترسی به این اجزا و کار کردن با اونها، مرورگر برای ما آبجکت DOM که یک رابط بین HTML و جاوااسکریپت هست رو میسازه. با DOM میتونیم به همهٔ این اجزا دسترسی داشته باشیم و تغییراتی توی صفحه بدیم. به این اجزایی که توی DOM وجود دارن به طور کلی گفته میشه Node. مثلاً متن توی یک تگ p، کامنتها و خودِ المنتها همگی نوعی Node هستن. و همچنین اعضایی مثل div و img یک نوع خاص از Node هستن که بهشون گفته میشه Element.
۱۸. توی جاوااسکریپت Syntax Error و Type Error چه تفاوتهایی با هم دارن؟
Syntax Error: اگه ساختار ظاهری و قواعد نوشتاری جاوااسکریپت رو رعایت نکنیم، مفسر جاوااسکریپت بهمون Syntax Error برمیگردونه. کد زیر شامل یک Syntax Error هست:
function add(x, y) { return x + y; add(2, 5);
اینجا توی خط ۳ براکت پایانی تابع add حذف شده. بنابراین مفسر قبل از اینکه کدهای ما رو به طور واقعی اجرا کنه بهمون چنین خطایی رو برمیگردونه:
<<SyntaxError>>: missing } after function body
Type Error: این خطا رو زمانی میگیریم که قصد اجرای یک عملیات غیر منتظره روی یک مقدار رو داریم. برای مثال فراخونی یک متد از null یا مقدار مجدد نسبت دادن به یک متغیر const. موارد زیر همگی نمونهٔ Type Error توی جاوااسکریپت هستن:
// 1. TypeError: a is not a function const a = 1; a(); // 2. TypeError: null has no properties null.toUpperCase(); // 3. TypeError: invalid assignment to const 'x' const x = 1; x = 2;
نوع دیگهای از خطا توی جاوااسکریپت وجود داره به اسم Reference Error که اون رو زمانی میگیریم که میخوایم به یک مقدار غیر قابل دسترسی یا تعریفنشده دسترسی پیدا کنیم. مثلاً:
// ReferenceError: y is not defined console.log(y); { const x = 10; } // ReferenceError: x is not defined console.log(x);
۱۹. DNS چیه؟
DNS مخفف Domain Name System هست و وظیفهٔ اون ترجمه و تبدیل کردن اسم دامنهها (مثلاً google.com) به آدرس IP قابل خوندن برای کامپیوترهاست (مثلاً 4.2.2.4). وقتی برای مثال توی مرورگر آدرس google.com رو باز میکنیم، ابتدا این آدرس باید ترجمه و تبدیل بشه به IP آدرس مربوطه تا بتونیم اون آدرس رو لود کنیم و ببینیم. این تبدیل، وظیفه DNS هست. در واقع DNS مثل اپ Contact توی گوشیها عمل میکنه که توی اون هر اسمی به یک شماره تلفن نسبت داده شده.
۲۰. چرا از Shallow Rendering توی تستنویسی استفاده کنیم؟
Shallow Rendering یک تکنیک تستنویسی هست که بیشتر توی فریمورکهای Component-Based مثل ویو و ریاکت دیده میشه. وقتی میخوایم یک کامپوننت رو با تکنیک Shallow Rendering تست کنیم، هنگام تست فقط خود کامپوننت رندر میشه و کامپوننتهای داخلی اون کامپوننت رندر نمیشن تا توجه و تمرکز روی خود کامپوننت والد باشه. با این کار، تست کردن راحتتر، سریعتر و دقیقتر خواهد بود. اما باید بدونیم که استفاده از Shallow Rendering همیشه خوب نیست.

از معایب Shallow Rendering اینه که:
- ممکنه رفتارهای اون کامپوننت رو توی محیطهای واقعی نادیده بگیریم
- اگه کامپوننت به کامپوننتهای داخلی وابستگی داشته باشه ممکنه حتی باعث سختتر شدن تست بشه
- باعث نادیده گرفتهشدن خیلی از تعاملهای بین کامپوننت والد و فرزندها میشه که باعث میشه تست کمتر قابل اعتماد باشه
پس بهتره از این تکنیک هم مثل هر چیز دیگهای با آگاهی استفاده کنیم.
خب دوستان قسمت دوم هم به آخرش رسید. امیدوارم از سوالات و نکتههایی که بررسی کردیم استفاده کرده باشین. اگه شما هم سوالات جالبی از مصاحبهها میشناسین میتونین توی قسمت کامنتها به اشتراک بذارین تا توی قسمتهای بعدی اونها رو بررسی کنیم. روزتون خوش 👋
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
https://stackoverflow.com/questions/9339429/what-does-cherry-picking-a-commit-with-git-mean
https://www.freecodecamp.org/news/type-error-vs-reference-error-javascript/
https://stackoverflow.com/questions/46881630/what-is-shallow-rendering-in-jest-unit-tests-in-react
