JavaScript

ویژگی انتخابگر CSS چیست و چگونه کار می کند؟

مرورگر بر اساس ویژگی قوانین CSS تعیین می کند که چه استایل هایی را روی یک عنصر نمایش دهد. ما فرض می کنیم که مرورگر قبلاً قوانینی را که با یک عنصر خاص مطابقت دارند، تعیین کرده است. در میان قوانین منطبق، ویژگی، چهار مقدار جدا شده با کاما، a, b, c, d برای هر قانون بر اساس موارد زیر محاسبه می شوند:

  1. a این است که آیا استایل های درون خطی استفاده می شوند یا خیر. اگر اعلان ویژگی یک استایل درون خطی روی عنصر باشد، a برابر با 1 است، در غیر این صورت 0.
  2. b تعداد انتخابگرهای ID است.
  3. c تعداد کلاس ها، ویژگی ها و انتخابگرهای شبه کلاس است.
  4. d تعداد تگ ها و انتخابگرهای شبه عناصر است.

ویژگی حاصل یک امتیاز نیست، بلکه یک ماتریس از مقادیر است که می تواند ستون به ستون مقایسه شود. هنگام مقایسه انتخابگرها برای تعیین کدام یک بالاترین ویژگی را دارد، از چپ به راست نگاه کنید و بالاترین مقدار را در هر ستون مقایسه کنید. بنابراین یک مقدار در ستون b مقادیر در ستون های c و d را نادیده می گیرد، مهم نیست که چه باشند. به همین ترتیب، ویژگی 0,1,0,0 بیشتر از 0,0,10,10 خواهد بود.

در موارد ویژگی برابر: آخرین قانون، قانونی است که شمارش می شود. اگر شما همان قانون را دو بار در شیوه نامه خود (بدون در نظر گرفتن داخلی یا خارجی) نوشته اید، سپس قانون پایین تر در شیوه نامه شما به عنصری که باید استایل دهی شود، نزدیک تر است، خاص تر تلقی می شود و بنابراین اعمال خواهد شد.

من قوانین CSS را با ویژگی کم می نویسم تا در صورت لزوم به راحتی قابل نادیده گرفتن باشند. هنگام نوشتن کد کتابخانه کامپوننت UI CSS، مهم است که آنها ویژگی های کمی داشته باشند تا کاربران کتابخانه بتوانند آنها را بدون استفاده از قوانین CSS بسیار پیچیده فقط به خاطر افزایش ویژگی یا توسل به !important نادیده بگیرند.

تفاوت بین بازنشانی reset و عادی سازی normalize CSS چیست؟ کدام را انتخاب می کنید و چرا؟

  • بازنشانی - بازنشانی به معنای حذف تمام استایل های پیش فرض مرورگر روی عناصر است. به عنوان مثال، حاشیه ها margins، فاصله ها paddings، اندازه فونت ها font-sizes همه عناصر بازنشانی می شوند تا یکسان باشند. شما باید استایل دهی را برای عناصر تایپوگرافی رایج دوباره اعلام کنید.
  • عادی سازی - عادی سازی استایل های پیش فرض مفید را به جای unstlying همه چیز حفظ می کند. همچنین باگ ها را برای وابستگی های رایج مرورگر اصلاح می کند.

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

توضیح دهید floats و نحوه کار آنها.

Float یک ویژگی موقعیت یابی CSS است. عناصر شناور شده بخشی از جریان صفحه باقی می مانند و بر موقعیت سایر عناصر تأثیر می گذارند (به عنوان مثال، متن در اطراف عناصر شناور جریان می یابد)، برخلاف عناصر position: absolute که از جریان صفحه حذف می شوند.

ویژگی CSS clear می تواند برای قرار گرفتن در زیر عناصر شناور شده left/right/both استفاده شود.

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

هک .clearfix از یک شبه انتخابگر CSS هوشمند ::after برای پاک کردن شناورها استفاده می کند. به جای تنظیم overflow روی والد، یک کلاس اضافی clearfix را به آن اعمال می کنید. سپس این CSS را اعمال کنید:

.clearfix::after { content: ' '; visibility: hidden; display: block; height: 0; clear: both; }

به عنوان جایگزین، ویژگی overflow: auto یا overflow: hidden را به عنصر والد بدهید که یک زمینه فرمت بندی بلوک جدید در داخل فرزندان ایجاد می کند و برای شامل شدن فرزندان خود گسترش می یابد.

z-index را توضیح دهید و چگونه زمینه پشته سازی (stacking context) شکل می گیرد.

ویژگی z-index در CSS ترتیب پشته سازی عمودی عناصر همپوشان را کنترل می کند. z-index فقط روی عناصری که مقدار position آنها static نیست، تأثیر می گذارد.

بدون هیچ مقدار z-index، عناصر به ترتیبی که در DOM ظاهر می شوند، روی هم قرار می گیرند (پایین ترین در همان سطح سلسله مراتب در بالا ظاهر می شود). عناصر با موقعیت دهی غیر استاتیک (و فرزندانشان) همیشه در بالای عناصر با موقعیت دهی استاتیک پیش فرض ظاهر می شوند، صرف نظر از سلسله مراتب HTML.

یک زمینه پشته سازی عنصری است که مجموعه ای از لایه ها را شامل می شود. در یک زمینه پشته سازی محلی، مقادیر z-index فرزندان آن نسبت به آن عنصر تنظیم می شود تا ریشه سند. لایه های خارج از آن زمینه — یعنی عناصر همزاد یک زمینه پشته سازی محلی — نمی توانند بین لایه های داخل آن قرار گیرند. اگر عنصر B روی عنصر A قرار گیرد، یک عنصر فرزند عنصر A، عنصر C، هرگز نمی تواند بالاتر از عنصر B باشد حتی اگر عنصر C دارای z-index بالاتری نسبت به عنصر B باشد.

هر زمینه پشته سازی مستقل است - پس از پشته شدن محتویات عنصر، کل عنصر در ترتیب پشته سازی زمینه پشته سازی والد در نظر گرفته می شود. تعدادی از ویژگی های CSS یک زمینه پشته سازی جدید را ایجاد می کنند، مانند opacity کمتر از 1، filter که none نیست، و transform که none نیست.

_نکته: دقیقاً چه چیزی یک عنصر را برای ایجاد یک زمینه پشته سازی واجد شرایط می کند در این مجموعه طولانی از قوانین ذکر شده است.

Block Formatting Context (BFC) را توضیح دهید و چگونه کار می کند.

یک Block Formatting Context (BFC) بخشی از رندرینگ بصری CSS یک صفحه وب است که در آن جعبه های بلوکی چیده می شوند. شناورها، عناصر با موقعیت مطلق، inline-blocks، table-cells، table-caption ها، و عناصر با overflow غیر از visible (مگر زمانی که آن مقدار به viewport منتقل شده باشد) زمینه های فرمت بندی بلوک جدیدی را ایجاد می کنند.

دانستن نحوه ایجاد یک زمینه فرمت بندی بلوک مهم است، زیرا بدون انجام این کار، جعبه حاوی، فرزندان شناور را شامل نخواهد شد. این مشابه collapsing margins است، اما موذیانه تر است زیرا کل جعبه ها به روش های عجیبی فرو می ریزند.

یک BFC یک جعبه HTML است که حداقل یکی از شرایط زیر را برآورده می کند:

  • مقدار float برابر با none نیست.
  • مقدار position نه static است و نه relative.
  • مقدار display برابر با table-cell، table-caption، inline-block، flex، یا inline-flex، grid، یا inline-grid است.
  • مقدار overflow برابر با visible نیست.

در یک BFC، لبه بیرونی سمت چپ هر جعبه با لبه چپ بلوک حاوی (برای فرمت راست به چپ، لبه های راست با هم تماس دارند) تماس می گیرد.

حاشیه های عمودی بین جعبه های همسایه در سطح بلوک در یک BFC فرو می ریزند. برای اطلاعات بیشتر در مورد collapsing margins بخوانید.

تکنیک های مختلف پاکسازی چیست و کدام برای چه زمینه ای مناسب است؟

  • روش div خالی - <div style='clear:both;'></div>.
  • روش Clearfix - به کلاس .clearfix در بالا مراجعه کنید.
  • روش overflow: auto یا overflow: hidden - والد یک زمینه فرمت بندی بلوک جدید ایجاد می کند و برای شامل شدن فرزندان شناور خود گسترش می یابد.

در پروژه های بزرگ، من یک کلاس کمکی .clearfix می نوشتم و از آنها در جاهایی که نیاز داشتم استفاده می کردم. overflow: hidden ممکن است در صورتی که فرزندان بلندتر از والد باشند، آنها را قطع کند و خیلی ایده آل نیست.

CSS sprites را توضیح دهید و چگونه آنها را در یک صفحه یا سایت پیاده سازی می کنید.

CSS sprites چندین تصویر را در یک تصویر بزرگتر ترکیب می کنند. این یک تکنیک معمولاً استفاده شده برای آیکون ها است (Gmail از آن استفاده می کند). نحوه پیاده سازی آن:

  1. از یک sprite generator استفاده کنید که چندین تصویر را در یک تصویر بسته بندی می کند و CSS مناسب را برای آن تولید می کند.
  2. هر تصویر یک کلاس CSS مربوطه با ویژگی های background-image، background-position و background-size تعریف شده خواهد داشت.
  3. برای استفاده از آن تصویر، کلاس مربوطه را به عنصر خود اضافه کنید.

مزایا:

  • کاهش تعداد درخواست های HTTP برای چندین تصویر (فقط یک درخواست واحد برای هر spritesheet مورد نیاز است). اما با HTTP2، بارگذاری چندین تصویر دیگر مشکل چندانی نیست.
  • بارگیری پیشرفته دارایی هایی که تا زمانی که لازم نباشند بارگیری نمی شوند، مانند تصاویری که فقط در pseudo-states های :hover ظاهر می شوند. چشمک زدن دیده نمی شود.

چگونه به رفع مشکلات استایل دهی خاص مرورگر نزدیک می شوید؟

  • پس از شناسایی مشکل و مرورگر مشکل ساز، از یک شیوه نامه جداگانه استفاده کنید که فقط زمانی که آن مرورگر خاص استفاده می شود، بارگذاری می شود. البته این تکنیک نیاز به رندرینگ سمت سرور دارد.
  • از کتابخانه هایی مانند Bootstrap استفاده کنید که قبلاً این مشکلات استایل دهی را برای شما حل کرده اند.
  • از autoprefixer برای اضافه کردن خودکار پیشوندهای وندور به کد خود استفاده کنید.
  • از Reset CSS یا Normalize.css استفاده کنید.
  • اگر از Postcss (یا یک کتابخانه transpiling مشابه) استفاده می کنید، ممکن است پلاگین هایی وجود داشته باشند که به شما امکان می دهند از سینتکس CSS مدرن (و حتی پیشنهادات W3C) استفاده کنید که آن بخش ها از کد شما را به کد ایمن مربوطه تبدیل می کند که در اهدافی که استفاده کرده اید کار خواهد کرد.

چگونه صفحات خود را برای مرورگرهای با قابلیت محدود ارائه می دهید؟ از چه تکنیک ها/فرآیندهایی استفاده می کنید؟

  • کاهش تدریجی - عمل ساخت یک برنامه برای مرورگرهای مدرن در حالی که اطمینان حاصل می شود که در مرورگرهای قدیمی تر نیز عملکردی باقی می ماند.
  • بهبود تدریجی - عمل ساخت یک برنامه برای یک سطح پایه از تجربه کاربری، اما اضافه کردن بهبودهای عملکردی زمانی که یک مرورگر از آن پشتیبانی می کند.
  • از caniuse.com برای بررسی پشتیبانی از ویژگی ها استفاده کنید.
  • Autoprefixer برای درج خودکار پیشوند وندور.
  • تشخیص ویژگی با استفاده از Modernizr.
  • استفاده از پرس و جوهای ویژگی CSS @support

راه های مختلف برای پنهان کردن بصری محتوا (و در دسترس قرار دادن آن فقط برای صفحه خوان ها) چیست؟

این تکنیک ها مربوط به دسترسی پذیری (a11y) هستند.

  • width: 0; height: 0. عنصر را به هیچ وجه در صفحه جا ندهید، در نتیجه آن را نمایش نمی دهد.
  • position: absolute; left: -99999px. آن را خارج از صفحه قرار دهید.
  • text-indent: -9999px. این فقط روی متن درون عناصر block کار می کند. این یک ترفند پرکاربرد و معروف است، اما با برخی معایب مانند ایجاد مشکلات عملکردی همراه است، بنابراین ممکن است بخواهید به جای آن از text-indent: 100% استفاده کنید.
  • Meta tags. به عنوان مثال با استفاده از Schema.org، RDF و JSON-LD.
  • WAI-ARIA. یک مشخصات فنی W3C که نحوه افزایش دسترسی پذیری صفحات وب را مشخص می کند.

حتی اگر WAI-ARIA راه حل ایده آل باشد، من روش موقعیت دهی absolute را انتخاب می کنم، زیرا کمترین عیب را دارد، برای اکثر عناصر کار می کند و یک تکنیک آسان است.

آیا تا به حال از سیستم گرید استفاده کرده اید، و اگر بله، کدام را ترجیح می دهید؟

قبل از اینکه فلکس محبوب شود (حدود سال 2014)، سیستم گرید مبتنی بر float قابل اعتمادترین بود زیرا هنوز بیشترین پشتیبانی مرورگر را در بین سیستم های جایگزین موجود (فلکس، گرید) داشت. بوت استرپ تا بوت استرپ 4 که به رویکرد مبتنی بر فلکس تغییر کرد، از رویکرد float استفاده می کرد. در حال حاضر (2020)، فلکس رویکرد توصیه شده برای ساخت سیستم های گرید است و پشتیبانی مرورگر مناسبی دارد.

برای ماجراجویان، آنها می توانند به CSS Grid Layout نگاه کنند، که از ویژگی جدید و درخشان grid استفاده می کند؛ حتی برای ساخت طرح بندی های گرید بهتر از فلکس است و در آینده راه اصلی برای انجام این کار خواهد بود.

آیا از media queries یا طرح بندی های/CSS مخصوص موبایل استفاده یا پیاده سازی کرده اید؟

بله. یک مثال می تواند تبدیل یک ناوبری پشته ای قرصی به یک ناوبری تب ثابت در پایین فراتر از یک نقطه شکست خاص باشد.

آیا با استایل دهی SVG آشنایی دارید؟

بله، چندین روش برای رنگ آمیزی اشکال (از جمله تعیین ویژگی‌ها روی شی) با استفاده از CSS درون‌خطی، یک بخش CSS جاسازی شده، یا یک فایل CSS خارجی وجود دارد. بیشتر SVG‌هایی که در وب پیدا می‌کنید از CSS درون‌خطی استفاده می‌کنند، اما هر نوع مزایا و معایب خاص خود را دارد.

رنگ آمیزی پایه را می توان با تنظیم دو ویژگی در گره انجام داد: fill و stroke. fill رنگ داخل شی را تنظیم می کند و stroke رنگ خط کشیده شده در اطراف شی را تنظیم می کند. می توانید از همان طرح های نامگذاری رنگ CSS که در HTML استفاده می کنید، استفاده کنید، چه نام های رنگی (یعنی red)، مقادیر RGB (یعنی rgb(255,0,0))، مقادیر Hex، مقادیر RGBA و غیره.

<rect x="10" y="10" width="100" height="100" stroke="blue" fill="purple" fill-opacity="0.5" stroke-opacity="0.8" />

fill='purple' بالا نمونه ای از یک ویژگی نمایشی است. جالب است که بر خلاف استایل های درون خطی مانند style='fill: purple' که به طور تصادفی یک ویژگی نیز هست، ویژگی های نمایشی می توانند توسط استایل های CSS تعریف شده در یک شیوه نامه نادیده گرفته شوند. بنابراین، اگر چیزی مانند svg { fill: blue; } را انجام دهید، fill بنفش که ما تعریف کرده ایم را نادیده می گیرد.

آیا می توانید مثالی از ویژگی @media به غیر از screen بدهید؟

بله، چهار نوع از ویژگی های @media (از جمله screen) وجود دارد:

  • all - برای همه دستگاه های نوع رسانه
  • print - برای پرینترها
  • speech - برای صفحه خوان ها که صفحه را با صدای بلند می خوانند
  • screen - برای صفحه نمایش رایانه، تبلت، تلفن هوشمند و غیره

در اینجا مثالی از کاربرد نوع رسانه print آورده شده است:

@media print { body { color: black; } }

برخی از نکاتی که در نوشتن CSS کارآمد باید در نظر داشت، چیست؟

اولاً، درک کنید که مرورگرها انتخابگرها را از راست ترین (انتخابگر کلیدی) به چپ مطابقت می دهند. مرورگرها عناصر را در DOM مطابق با انتخابگر کلیدی فیلتر می کنند و برای تعیین تطابق ها به سمت بالا در عناصر والد خود حرکت می کنند. هر چه طول زنجیره انتخابگر کوتاه تر باشد، مرورگر می تواند سریعتر تعیین کند که آیا آن عنصر با انتخابگر مطابقت دارد یا خیر. از این رو از انتخابگرهای کلیدی که انتخابگرهای تگ و جهانی هستند خودداری کنید. آنها تعداد زیادی از عناصر را مطابقت می دهند و مرورگرها باید کار بیشتری برای تعیین مطابقت والدین انجام دهند.

متدولوژی BEM (Block Element Modifier) توصیه می کند که همه چیز یک کلاس واحد داشته باشد، و در جایی که به سلسله مراتب نیاز دارید، آن نیز در نام کلاس گنجانده می شود، این به طور طبیعی انتخابگر را کارآمد و آسان برای نادیده گرفتن می کند.

از اینکه کدام ویژگی های CSS باعث reflow، repaint و compositing می شوند آگاه باشید. از نوشتن استایل هایی که طرح را تغییر می دهند (باعث reflow می شوند) در صورت امکان خودداری کنید.

مزایا/معایب استفاده از پیش‌پردازنده‌های CSS چیست؟

مزایا:

  • CSS قابل نگهداری‌تر می‌شود.
  • نوشتن انتخابگرهای تو در تو آسان است.
  • متغیرها برای تم‌بندی ثابت. می‌توان فایل‌های تم را در پروژه‌های مختلف به اشتراک گذاشت.
  • Mixins برای تولید CSS تکراری.
  • ویژگی‌های Sass مانند حلقه‌ها، لیست‌ها و نقشه‌ها می‌توانند پیکربندی را آسان‌تر و کم‌حرف‌تر کنند.
  • تقسیم کد شما به چندین فایل. فایل‌های CSS را نیز می‌توان تقسیم کرد، اما انجام این کار نیاز به یک درخواست HTTP برای دانلود هر فایل CSS دارد.

معایب:

  • نیاز به ابزارهایی برای پیش‌پردازش. زمان کامپایل مجدد می‌تواند کند باشد.
  • ننوشتن CSS فعلی و بالقوه قابل استفاده. به عنوان مثال، با استفاده از چیزی مانند postcss-loader با webpack، می‌توانید CSS بالقوه سازگار با آینده را بنویسید، که به شما امکان می‌دهد از چیزهایی مانند متغیرهای CSS به جای متغیرهای Sass استفاده کنید. بنابراین، شما در حال یادگیری مهارت‌های جدیدی هستید که می‌تواند در صورت استاندارد شدن (یا زمانی که استاندارد شوند) مفید باشد.

آنچه را که در مورد پیش‌پردازنده‌های CSS که استفاده کرده‌اید دوست دارید و دوست ندارید، توضیح دهید.

دوست داشتن:

  • بیشتر مزایای ذکر شده در بالا.
  • کمتر در جاوااسکریپت نوشته شده است که با Node به خوبی کار می کند.

دوست نداشتن:

  • من از Sass از طریق node-sass استفاده می کنم، که یک اتصال برای LibSass است که در C++ نوشته شده است. هنگام جابجایی بین نسخه های Node، باید مکرراً آن را کامپایل مجدد کنم.
  • در Less، نام متغیرها با @ پیشوند می شوند، که می تواند با کلمات کلیدی بومی CSS مانند @media، @import و قانون @font-face اشتباه گرفته شود.

چگونه یک کامپ طراحی وب را که از فونت های غیر استاندارد استفاده می کند، پیاده سازی می کنید؟

از @font-face استفاده کنید و font-family را برای font-weight های مختلف تعریف کنید.

توضیح دهید که یک مرورگر چگونه تشخیص می دهد که کدام عناصر با یک انتخابگر CSS مطابقت دارند.

این بخش مربوط به قسمت نوشتن CSS کارآمد در بالا است. مرورگرها انتخابگرها را از راست ترین (انتخابگر کلیدی) به چپ مطابقت می دهند. مرورگرها عناصر را در DOM بر اساس انتخابگر کلیدی فیلتر می کنند و برای تعیین مطابقت ها به سمت بالا در عناصر والد خود حرکت می کنند. هرچه طول زنجیره انتخابگر کوتاه تر باشد، مرورگر می تواند سریعتر تعیین کند که آیا آن عنصر با انتخابگر مطابقت دارد یا خیر.

به عنوان مثال با این انتخابگر p span، مرورگرها ابتدا تمام عناصر <span> را پیدا می کنند و تا ریشه به سمت بالا در والد آن حرکت می کنند تا عنصر <p> را پیدا کنند. برای یک <span> خاص، به محض یافتن یک <p>، می داند که <span> مطابقت دارد و می تواند تطبیق خود را متوقف کند.

شبه عناصر را توصیف کنید و در مورد کاربرد آنها بحث کنید.

شبه عنصر CSS یک کلمه کلیدی است که به یک انتخابگر اضافه می شود و به شما امکان می دهد بخش خاصی از عناصر انتخاب شده را استایل دهید. می توان از آنها برای تزئین (:first-line، :first-letter) یا افزودن عناصر به نشانه گذاری (ترکیب با content: ...) بدون نیاز به اصلاح نشانه گذاری (:before، :after) استفاده کرد.

  • :first-line و :first-letter می توانند برای تزئین متن استفاده شوند.
  • در هک .clearfix که در بالا نشان داده شد برای افزودن یک عنصر با فضای صفر و clear: both استفاده می شود.
  • فلش های مثلثی در راهنماها از :before و :after استفاده می کنند. جداسازی نگرانی ها را تشویق می کند زیرا مثلث بخشی از استایل دهی محسوب می شود و نه واقعاً DOM.

درک خود را از مدل جعبه (box model) توضیح دهید و اینکه چگونه به مرورگر در CSS می گویید که طرح بندی شما را در مدل های جعبه ای مختلف رندر کند.

مدل جعبه CSS جعبه های مستطیلی را توصیف می کند که برای عناصر در درخت سند ایجاد می شوند و طبق مدل قالب بندی بصری چیده می شوند. هر جعبه دارای یک ناحیه محتوا (مانند متن، تصویر و غیره) و نواحی اختیاری padding، border و margin اطراف آن است.

مدل جعبه CSS مسئول محاسبه موارد زیر است:

  • چقدر فضا یک عنصر بلوکی اشغال می کند.
  • آیا حاشیه ها و/یا margin ها همپوشانی دارند یا فرو می ریزند.
  • ابعاد یک جعبه.

مدل جعبه قوانین زیر را دارد:

  • ابعاد یک عنصر بلوکی با width، height، padding، borders و margins محاسبه می شود.
  • اگر height مشخص نشده باشد، یک عنصر بلوکی به اندازه محتوای خود، به علاوه padding (مگر اینکه شناورهایی وجود داشته باشند، که برای آنها به پایین مراجعه کنید) ارتفاع خواهد داشت.
  • اگر width مشخص نشده باشد، یک عنصر بلوکی غیر شناور برای متناسب شدن با عرض والد خود منهای padding گسترش می یابد.
  • height یک عنصر با height محتوا محاسبه می شود.
  • width یک عنصر با width محتوا محاسبه می شود.
  • به طور پیش فرض، paddings و borders بخشی از width و height یک عنصر نیستند.

box-sizing: border-box; } * { چه کاری انجام می دهد؟ مزایای آن چیست؟

  • به طور پیش فرض، عناصر دارای box-sizing: content-box هستند، و فقط اندازه محتوا در نظر گرفته می شود.
  • box-sizing: border-box نحوه محاسبه width و height عناصر را تغییر می دهد، border و padding نیز در محاسبه گنجانده می شوند.
  • height یک عنصر اکنون با height محتوا + padding عمودی + عرض border عمودی محاسبه می شود.
  • width یک عنصر اکنون با width محتوا + padding افقی + عرض border افقی محاسبه می شود.
  • در نظر گرفتن padding ها و border ها به عنوان بخشی از مدل جعبه ما، بهتر با نحوه تصور طراحان از محتوا در گریدها همخوانی دارد.

ویژگی display در CSS چیست و می توانید چند مثال از کاربرد آن ارائه دهید؟

  • none, block, inline, inline-block, flex, grid, table, table-row, table-cell, list-item.

| display | توضیحات | | :-- | :-- | | none | عنصری را نمایش نمی دهد (عنصر دیگر بر طرح سند تأثیر نمی گذارد). همه عناصر فرزند نیز دیگر نمایش داده نمی شوند. سند طوری رندر می شود که گویی عنصر در درخت سند وجود ندارد | | block | عنصر تمام خط را در جهت بلوک مصرف می کند (که معمولاً افقی است) | | inline | عناصر می توانند در کنار یکدیگر قرار گیرند | | inline-block | شبیه inline است، اما به برخی از ویژگی های block مانند تنظیم width و height اجازه می دهد | | table | مانند عنصر <table> رفتار می کند | | table-row | مانند عنصر <tr> رفتار می کند | | table-cell | مانند عنصر <td> رفتار می کند | | list-item | مانند یک عنصر <li> رفتار می کند که به آن اجازه می دهد list-style-type و list-style-position را تعریف کند |

تفاوت بین `inline` و `inline-block` چیست؟

من برای اطمینان، مقایسه ای با block را نیز اضافه می کنم.

| | block | inline-block | inline | | --- | --- | --- | --- | | اندازه | عرض کانتینر والد خود را پر می کند. | بستگی به محتوا دارد. | بستگی به محتوا دارد. | | موقعیت دهی | در یک خط جدید شروع می شود و هیچ عنصر HTML را در کنار خود تحمل نمی کند (مگر زمانی که float را اضافه کنید) | همراه با سایر محتوا جریان می یابد و به عناصر دیگر در کنار خود اجازه می دهد. | همراه با سایر محتوا جریان می یابد و به عناصر دیگر در کنار خود اجازه می دهد. | | می تواند width و height را مشخص کند | بله | بله | خیر. در صورت تنظیم نادیده گرفته می شود. | | می تواند با vertical-align تراز شود | خیر | بله | بله | | حاشیه ها و padding ها | همه جهات رعایت می شوند. | همه جهات رعایت می شوند. | فقط جهات افقی رعایت می شوند. جهات عمودی، در صورت مشخص شدن، بر طرح بندی تأثیر نمی گذارند. فضای عمودی که اشغال می کند به line-height بستگی دارد، حتی اگر border و padding به صورت بصری در اطراف محتوا ظاهر شوند. | | Float | - | - | مانند یک عنصر block می شود که می توانید حاشیه ها و padding های عمودی را تنظیم کنید. |

تفاوت بین یک عنصر با موقعیت دهی `relative`, `fixed`, `absolute` و `static` چیست؟

یک عنصر موقعیت‌دهی شده، عنصری است که ویژگی position محاسبه‌شده آن یکی از مقادیر relative، absolute، fixed یا sticky باشد.

  • static - موقعیت پیش‌فرض؛ عنصر به طور معمول در صفحه جریان می‌یابد. ویژگی‌های top, right, bottom, left و z-index اعمال نمی‌شوند.
  • relative - موقعیت عنصر نسبت به خودش تنظیم می‌شود، بدون تغییر طرح‌بندی (و در نتیجه فضایی برای عنصر در جایی که اگر موقعیت‌دهی نشده بود، می‌ماند).
  • absolute - عنصر از جریان صفحه حذف می‌شود و در یک موقعیت مشخص نسبت به نزدیک‌ترین جد موقعیت‌دهی شده خود (در صورت وجود)، یا در غیر این صورت نسبت به بلوک حاوی اولیه، قرار می‌گیرد. جعبه‌های با موقعیت مطلق می‌توانند حاشیه‌ها داشته باشند و با هیچ حاشیه دیگری فرو نمی‌ریزند. این عناصر بر موقعیت سایر عناصر تأثیر نمی‌گذارند.
  • fixed - عنصر از جریان صفحه حذف می‌شود و در یک موقعیت مشخص نسبت به viewport قرار می‌گیرد و هنگام اسکرول حرکت نمی‌کند.
  • sticky - موقعیت‌دهی sticky ترکیبی از موقعیت‌دهی relative و fixed است. عنصر به صورت relative رفتار می‌شود تا زمانی که از یک آستانه مشخص عبور کند، که در آن نقطه به صورت fixed رفتار می‌شود.

از کدام فریم‌ورک‌های CSS موجود به صورت محلی یا در تولید استفاده کرده‌اید؟ چگونه آنها را تغییر/بهبود می‌دهید؟

  • بوت استرپ - چرخه انتشار کند. بوت استرپ 4 تقریباً 2 سال در آلفا بوده است. یک کامپوننت دکمه اسپینر اضافه کنید، زیرا به طور گسترده‌ای استفاده می‌شود.
  • سیمنتیک UI - ساختار کد منبع، سفارشی‌سازی تم را به شدت دشوار می‌کند. سیستم تم‌بندی غیرمتعارف آن برای سفارشی‌سازی دردسر ساز است. مسیر پیکربندی در کتابخانه فروشنده سخت‌کد شده است. برای نادیده گرفتن متغیرها برخلاف بوت استرپ، به خوبی طراحی نشده است.
  • بولما - نیاز به کلاس‌ها و نشانه‌گذاری‌های غیرمعنایی و اضافی زیادی دارد. با نسخه‌های قبلی سازگار نیست. ارتقاء نسخه‌ها برنامه را به روش‌های ظریف خراب می‌کند.

آیا با مشخصات جدید CSS Flexbox یا Grid کار کرده‌اید؟

بله. فلکس باکس عمدتاً برای طرح‌بندی‌های 1-بعدی در نظر گرفته شده است در حالی که گرید برای طرح‌بندی‌های 2-بعدی است.

فلکس باکس بسیاری از مشکلات رایج در CSS را حل می‌کند، مانند مرکز قرار دادن عمودی عناصر در یک کانتینر، فوتر چسبنده و غیره. بوت استرپ و بولما بر اساس فلکس باکس هستند و احتمالاً این روزها روش توصیه شده برای ایجاد طرح‌بندی‌ها است. قبلاً فلکس باکس را امتحان کرده بودم اما در استفاده از flex-grow با مشکلاتی در سازگاری مرورگر (سافاری) مواجه شدم و مجبور شدم کد خود را با استفاده از inline-blocks و ریاضیات برای محاسبه عرض‌ها به صورت درصدی بازنویسی کنم، تجربه خوبی نبود.

گرید تا کنون بصری‌ترین رویکرد برای ایجاد طرح‌بندی‌های مبتنی بر گرید است (باید هم باشد!) اما در حال حاضر پشتیبانی مرورگر گسترده‌ای ندارد.

تفاوت بین کدنویسی یک وب‌سایت به صورت ریسپانسیو و استفاده از استراتژی موبایل-اول چیست؟

توجه داشته باشید که این دو رویکرد منحصر به فرد نیستند.

ریسپانسیو کردن یک وب‌سایت به این معنی است که برخی از عناصر با تطبیق اندازه یا سایر عملکردها با اندازه صفحه دستگاه، معمولاً عرض viewport، از طریق پرس و جوهای رسانه‌ای CSS، پاسخ خواهند داد، به عنوان مثال، کوچک‌تر کردن اندازه فونت در دستگاه‌های کوچک‌تر.

@media (min-width: 601px) { .my-class { font-size: 24px; } } @media (max-width: 600px) { .my-class { font-size: 12px; } }

استراتژی موبایل-اول نیز ریسپانسیو است، با این حال موافق است که ما باید به صورت پیش‌فرض تمام استایل‌ها را برای دستگاه‌های موبایل تعریف کنیم، و فقط قوانین ریسپانسیو خاص را بعداً به دستگاه‌های دیگر اضافه کنیم. با توجه به مثال قبلی:

.my-class { font-size: 12px; } @media (min-width: 600px) { .my-class { font-size: 24px; } }

استراتژی موبایل-اول 2 مزیت اصلی دارد:

  • در دستگاه‌های موبایل عملکرد بهتری دارد، زیرا تمام قوانین اعمال شده برای آنها نیازی به اعتبار سنجی در برابر هیچ پرس و جوی رسانه‌ای ندارند.
  • کد تمیزتری را در رابطه با قوانین CSS ریسپانسیو اجبار می‌کند.

طراحی واکنش‌گرا چه تفاوتی با طراحی تطبیقی دارد؟

هم طراحی واکنش‌گرا و هم تطبیقی تلاش می‌کنند تا تجربه کاربری را در دستگاه‌های مختلف بهینه کنند، با تنظیم برای اندازه‌های مختلف نمایشی، وضوح، زمینه‌های استفاده، مکانیزم‌های کنترل و غیره.

طراحی واکنش‌گرا بر اساس اصل انعطاف‌پذیری کار می‌کند - یک وب‌سایت سیال واحد که می‌تواند در هر دستگاهی خوب به نظر برسد. وب‌سایت‌های واکنش‌گرا از media queries، گرید‌های انعطاف‌پذیر و تصاویر واکنش‌گرا برای ایجاد تجربه‌ای کاربری استفاده می‌کنند که بر اساس عوامل متعدد تغییر می‌کند و انعطاف‌پذیر است. مانند یک توپ واحد که برای جا شدن در حلقه‌های مختلف بزرگ یا کوچک می‌شود.

طراحی تطبیقی بیشتر شبیه تعریف مدرن بهبود تدریجی است. به جای یک طراحی انعطاف‌پذیر، طراحی تطبیقی دستگاه و سایر ویژگی‌ها را تشخیص می‌دهد و سپس ویژگی و طرح‌بندی مناسب را بر اساس مجموعه‌ای از اندازه‌های نمایشی از پیش تعریف شده و سایر ویژگی‌ها ارائه می‌دهد. سایت نوع دستگاه مورد استفاده را تشخیص می‌دهد و طرح‌بندی از پیش تعیین شده را برای آن دستگاه ارائه می‌دهد. به جای یک توپ واحد که از چند حلقه با اندازه‌های مختلف عبور می‌کند، شما چندین توپ مختلف خواهید داشت که بسته به اندازه حلقه از آنها استفاده کنید.

هر دو روش مشکلاتی دارند که باید مورد بررسی قرار گیرند:

  • طراحی واکنش‌گرا می‌تواند بسیار چالش‌برانگیز باشد، زیرا شما اساساً از یک طرح‌بندی واحد و در عین حال واکنش‌گرا برای متناسب شدن با همه موقعیت‌ها استفاده می‌کنید. نحوه تنظیم نقاط شکست media query یکی از این چالش‌ها است. آیا از مقادیر استاندارد شده نقطه شکست استفاده می‌کنید؟ یا از نقاط شکستی استفاده می‌کنید که برای طرح‌بندی خاص شما منطقی هستند؟ اگر آن طرح‌بندی تغییر کند چه می‌شود؟
  • طراحی تطبیقی معمولاً نیاز به تشخیص عامل کاربر یا تشخیص DPI و غیره دارد که همه اینها می‌توانند غیرقابل اعتماد باشند.

آیا تا به حال با گرافیک رتینا کار کرده‌اید؟ اگر بله، چه زمانی و از چه تکنیک‌هایی استفاده کردید؟

رتینا صرفاً یک اصطلاح بازاریابی برای اشاره به نمایشگرهای با وضوح بالا با نسبت پیکسل بزرگتر از 1 است. نکته کلیدی این است که استفاده از نسبت پیکسل به این معنی است که این نمایشگرها در حال شبیه‌سازی یک صفحه نمایش با وضوح پایین‌تر هستند تا عناصر را با همان اندازه نشان دهند. امروزه ما تمام دستگاه‌های موبایل را به صورت پیش‌فرض نمایشگرهای رتینا در نظر می‌گیریم.

مرورگرها به صورت پیش‌فرض عناصر DOM را با توجه به وضوح دستگاه رندر می‌کنند، به جز تصاویر.

برای داشتن گرافیک‌های واضح و زیبا که بهترین استفاده را از نمایشگرهای رتینا ببرند، باید در صورت امکان از تصاویر با وضوح بالا استفاده کنیم. با این حال، استفاده همیشه از تصاویر با بالاترین وضوح بر عملکرد تأثیر می‌گذارد زیرا باید بایت‌های بیشتری از طریق سیم ارسال شود.

برای غلبه بر این مشکل، می‌توانیم از تصاویر ریسپانسیو، همانطور که در HTML5 مشخص شده است، استفاده کنیم. این کار مستلزم در دسترس قرار دادن فایل‌های با وضوح مختلف از یک تصویر برای مرورگر و اجازه دادن به آن برای تصمیم‌گیری در مورد بهترین تصویر، با استفاده از ویژگی HTML srcset و به صورت اختیاری sizes است، به عنوان مثال:

<div responsive-background-image> <img src="/images/test-1600.jpg" sizes=" (min-width: 768px) 50vw, (min-width: 1024px) 66vw, 100vw" srcset=" /images/test-400.jpg 400w, /images/test-800.jpg 800w, /images/test-1200.jpg 1200w " /> </div>

مهم است که توجه داشته باشید مرورگرهایی که از srcset HTML5 پشتیبانی نمی‌کنند (یعنی IE11) آن را نادیده گرفته و به جای آن از src استفاده خواهند کرد. اگر واقعاً نیاز به پشتیبانی از IE11 داریم و می‌خواهیم این ویژگی را به دلایل عملکردی ارائه دهیم، می‌توانیم از یک polyfill جاوااسکریپت استفاده کنیم، به عنوان مثال.

برای آیکون‌ها، من همچنین ترجیح می‌دهم از SVG و فونت‌های آیکون در صورت امکان استفاده کنم، زیرا آنها بدون توجه به وضوح، بسیار واضح رندر می‌شوند.

یک حلقه for ایجاد کنید که تا 100 تکرار می شود و در مضرب های 3 'fizz'، در مضرب های 5 'buzz' و در مضرب های 3 و 5 'fizzbuzz' را خروجی می دهد.

این نسخه از FizzBuzz را توسط [Paul Irish] بررسی کنید.

for (let i = 1; i <= 100; i++) { let f = i % 3 == 0, b = i % 5 == 0; console.log(f ? (b ? 'FizzBuzz' : 'Fizz') : b ? 'Buzz' : i); }

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

چرا، به طور کلی، ایده خوبی است که دامنه جهانی یک وب‌سایت را همانطور که هست رها کرده و هرگز آن را دستکاری نکنیم؟

هر اسکریپت به دامنه جهانی دسترسی دارد، و اگر همه از فضای نام جهانی برای تعریف متغیرهای خود استفاده کنند، احتمالاً تداخل رخ خواهد داد. از الگوی ماژول (IIFE) برای کپسوله‌سازی متغیرهای خود در یک فضای نام محلی استفاده کنید.

چرا از چیزی مانند رویداد `load` استفاده می کنید؟ آیا این رویداد معایبی دارد؟ آیا جایگزینی می شناسید، و چرا از آنها استفاده می کنید؟

رویداد load در پایان فرآیند بارگذاری سند فعال می شود. در این مرحله، تمام اشیاء در سند در DOM قرار دارند و تمام تصاویر، اسکریپت ها، لینک ها و زیرفریم ها بارگذاری خود را به پایان رسانده اند.

رویداد DOM DOMContentLoaded پس از ساخت DOM برای صفحه فعال می شود، اما منتظر نمی ماند تا منابع دیگر بارگذاری شوند. این در موارد خاصی که نیازی به بارگذاری کامل صفحه قبل از مقداردهی اولیه ندارید، ترجیح داده می شود.

توضیح دهید برنامه تک صفحه‌ای (SPA) چیست و چگونه آن را برای سئو بهینه کنیم.

مطالب زیر از [راهنمای عالی Grab Front End] گرفته شده است، که اتفاقاً توسط خودم نوشته شده است!

امروزه توسعه‌دهندگان وب به محصولاتی که می‌سازند، به جای وب‌سایت، برنامه وب (Web App) می‌گویند. در حالی که تفاوت دقیقی بین این دو اصطلاح وجود ندارد، برنامه‌های وب معمولاً بسیار تعاملی و پویا هستند و به کاربر اجازه می‌دهند اقدامات خاصی را انجام دهد و پاسخی به آن عمل دریافت کند. به طور سنتی، مرورگر HTML را از سرور دریافت کرده و آن را رندر می‌کند. وقتی کاربر به URL دیگری می‌رود، یک بارگذاری مجدد کامل صفحه (full-page refresh) لازم است و سرور HTML جدیدی را به صفحه جدید ارسال می‌کند. این فرآیند رندرینگ سمت سرور (server-side rendering) نامیده می‌شود.

با این حال، در SPAs مدرن، به جای آن از رندرینگ سمت کلاینت (client-side rendering) استفاده می‌شود. مرورگر صفحه اولیه را از سرور به همراه اسکریپت‌ها (فریم‌ورک‌ها، کتابخانه‌ها، کد برنامه) و شیوه نامه‌های مورد نیاز برای کل برنامه بارگذاری می‌کند. هنگامی که کاربر به صفحات دیگر می‌رود، بارگذاری مجدد صفحه اتفاق نمی‌افتد. URL صفحه از طریق [HTML5 History API] به‌روزرسانی می‌شود. داده‌های جدید مورد نیاز برای صفحه جدید، معمولاً با فرمت JSON، توسط مرورگر از طریق درخواست‌های [AJAX] به سرور بازیابی می‌شوند. سپس SPA به صورت پویا صفحه را با داده‌ها از طریق جاوااسکریپت، که قبلاً در بارگذاری اولیه صفحه دانلود کرده بود، به‌روزرسانی می‌کند. این مدل مشابه نحوه کار برنامه‌های موبایل بومی (native mobile apps) است.

مزایا:

  • برنامه پاسخگوتر به نظر می‌رسد و کاربران به دلیل بارگذاری مجدد کامل صفحه، فلش بین صفحات را نمی‌بینند.
  • درخواست‌های HTTP کمتری به سرور ارسال می‌شود، زیرا دارایی‌های یکسان نیازی به بارگذاری مجدد برای هر بارگذاری صفحه ندارند.
  • جداسازی واضح نگرانی‌ها بین کلاینت و سرور؛ می‌توانید به راحتی کلاینت‌های جدیدی برای پلتفرم‌های مختلف (مانند موبایل، چت‌بات، ساعت‌های هوشمند) بسازید بدون نیاز به تغییر کد سرور. همچنین می‌توانید پشته فناوری را در کلاینت و سرور به طور مستقل تغییر دهید، تا زمانی که قرارداد API شکسته نشود.

معایب:

  • بارگذاری اولیه صفحه سنگین‌تر به دلیل بارگذاری فریم‌ورک، کد برنامه و دارایی‌های مورد نیاز برای چندین صفحه.
  • یک گام اضافی در سرور شما باید انجام شود و آن پیکربندی آن برای هدایت تمام درخواست‌ها به یک نقطه ورودی واحد و اجازه دادن به مسیریابی سمت کلاینت برای ادامه کار از آنجا است.
  • SPAs برای رندر کردن محتوا به جاوااسکریپت متکی هستند، اما همه موتورهای جستجو جاوااسکریپت را در طول خزش (crawling) اجرا نمی‌کنند، و ممکن است محتوای خالی در صفحه شما ببینند. این به طور ناخواسته به بهینه‌سازی موتور جستجو (SEO) برنامه شما آسیب می‌زند. با این حال، بیشتر اوقات، زمانی که برنامه‌ها را می‌سازید، سئو مهم‌ترین عامل نیست، زیرا تمام محتوا نیازی به ایندکس شدن توسط موتورهای جستجو ندارد. برای غلبه بر این مشکل، می‌توانید برنامه خود را سمت سرور رندر کنید یا از خدماتی مانند [Prerender] استفاده کنید تا 'جاوااسکریپت شما را در مرورگر رندر کند، HTML استاتیک را ذخیره کند و آن را به خزنده‌ها برگرداند'.

میزان تجربه شما با Promises و/یا polyfills آنها چقدر است؟

دانش کاری در این زمینه را دارم. یک Promise شیئی است که ممکن است در آینده یک مقدار واحد تولید کند: یا یک مقدار حل شده یا دلیلی برای عدم حل شدن آن (به عنوان مثال، یک خطای شبکه رخ داده است). یک Promise ممکن است در یکی از 3 حالت ممکن باشد: fulfilled، rejected یا pending. کاربران Promise می توانند callbacks را برای مدیریت مقدار fulfilled یا دلیل رد شدن اضافه کنند.

برخی از polyfills های رایج $.deferred، Q و Bluebird هستند اما همه آنها با مشخصات مطابقت ندارند. ES2015 از Promises به طور بومی پشتیبانی می کند و معمولاً امروزه نیازی به polyfills نیست.

مزایا و معایب استفاده از Promises به جای callbacks چیست؟

مزایا

  • جلوگیری از Callback hell که می‌تواند غیرقابل خواندن باشد.
  • نوشتن کد ناهمزمان ترتیبی که با .then() خوانا باشد را آسان می‌کند.
  • نوشتن کد ناهمزمان موازی با Promise.all() را آسان می‌کند.
  • با Promises، این سناریوها که فقط در کدنویسی با callbacks وجود دارند، اتفاق نمی‌افتفتند:
    • فراخوانی callback خیلی زود
    • فراخوانی callback خیلی دیر (یا هرگز)
    • فراخوانی callback خیلی کم یا خیلی زیاد
    • عدم انتقال هرگونه محیط/پارامتر لازم
    • بلعیدن هرگونه خطا/استثنایی که ممکن است رخ دهد

معایب

  • کد کمی پیچیده‌تر (قابل بحث).
  • در مرورگرهای قدیمی‌تر که ES2015 پشتیبانی نمی‌شود، برای استفاده از آن باید یک polyfill بارگذاری کنید.

برخی از مزایا/معایب نوشتن کد جاوااسکریپت در زبانی که به جاوااسکریپت کامپایل می‌شود، چیست؟

برخی از نمونه‌هایی از زبان‌هایی که به جاوااسکریپت کامپایل می‌شوند عبارتند از CoffeeScript، Elm، ClojureScript، PureScript و TypeScript.

مزایا:

  • برخی از مشکلات دیرینه در جاوااسکریپت را حل می‌کند و ضد الگوهای جاوااسکریپت را دلسرد می‌کند.
  • به شما امکان می‌دهد کدهای کوتاه‌تری بنویسید، با ارائه برخی syntactic sugar روی جاوااسکریپت، که به نظر من ES5 فاقد آن است، اما ES2015 عالی است.
  • تایپ‌های استاتیک (در مورد TypeScript) برای پروژه‌های بزرگ که نیاز به نگهداری طولانی مدت دارند، فوق‌العاده هستند.

معایب:

  • نیاز به یک فرآیند build/compile دارد زیرا مرورگرها فقط جاوااسکریپت را اجرا می‌کنند و کد شما قبل از ارائه به مرورگرها باید به جاوااسکریپت کامپایل شود.
  • اشکال‌زدایی می‌تواند دردسر ساز باشد اگر source map شما به درستی به سورس کامپایل نشده شما نگاشت نشود.
  • اکثر توسعه‌دهندگان با این زبان‌ها آشنا نیستند و باید آنها را یاد بگیرند. اگر از آن برای پروژه‌های خود استفاده کنید، هزینه آموزشی برای تیم شما دربرخواهد داشت.
  • جامعه کوچک‌تر (بستگی به زبان دارد)، به این معنی که یافتن منابع، آموزش‌ها، کتابخانه‌ها و ابزارها دشوارتر خواهد بود.
  • پشتیبانی IDE/editor ممکن است کافی نباشد.
  • این زبان‌ها همیشه عقب‌تر از آخرین استاندارد جاوااسکریپت خواهند بود.
  • توسعه‌دهندگان باید از آنچه که کد آنها به آن کامپایل می‌شود آگاه باشند – زیرا آن چیزی است که واقعاً اجرا خواهد شد، و این چیزی است که در نهایت اهمیت دارد.

عملاً، ES2015 جاوااسکریپت را به طرز چشمگیری بهبود بخشیده و نوشتن آن را بسیار دلپذیرتر کرده است. من واقعاً نیازی به CoffeeScript این روزها نمی‌بینم.

چه ابزارها و تکنیک‌هایی برای اشکال‌زدایی کد جاوااسکریپت استفاده می‌کنید؟

  • React و Redux
    • [React Devtools]
    • [Redux Devtools]
  • Vue
    • [Vue Devtools]
  • جاوااسکریپت
    • [Chrome Devtools]
    • عبارت debugger
    • اشکال‌زدایی قدیمی console.log

از چه ساختارهای زبانی برای پیمایش روی ویژگی‌های شیء و آیتم‌های آرایه استفاده می‌کنید؟

برای اشیاء:

  • حلقه‌های for-in - for (var property in obj) { console.log(property); }. با این حال، این حلقه روی ویژگی‌های ارث‌بری شده نیز تکرار می‌شود، و باید قبل از استفاده از آن، یک بررسی obj.hasOwnProperty(property) اضافه کنید.
  • Object.keys() - Object.keys(obj).forEach(function (property) { ... }). Object.keys() یک متد استاتیک است که تمام ویژگی‌های قابل شمارش شیئی را که به آن می‌دهید، لیست می‌کند.
  • Object.getOwnPropertyNames() - Object.getOwnPropertyNames(obj).forEach(function (property) { ... }). Object.getOwnPropertyNames() یک متد استاتیک است که تمام ویژگی‌های قابل شمارش و غیرقابل شمارش شیئی را که به آن می‌دهید، لیست می‌کند.

برای آرایه‌ها:

  • حلقه‌های for - for (var i = 0; i < arr.length; i++). مشکل رایج در اینجا این است که var در محدوده تابع قرار دارد و نه در محدوده بلوک، و اکثر اوقات شما یک متغیر تکرارکننده با محدوده بلوک می‌خواهید. ES2015 let را معرفی می‌کند که دارای محدوده بلوک است و توصیه می‌شود به جای آن از آن استفاده کنید. بنابراین اینگونه می‌شود: for (let i = 0; i < arr.length; i++).
  • forEach - arr.forEach(function (el, index) { ... }). این ساختار گاهی اوقات راحت‌تر است زیرا اگر تنها چیزی که نیاز دارید عناصر آرایه باشد، نیازی به استفاده از index ندارید. متدهای every و some نیز وجود دارند که به شما امکان می‌دهند تکرار را زودتر خاتمه دهید.
  • حلقه‌های for-of - for (let elem of arr) { ... }. ES6 یک حلقه جدید، حلقه for-of را معرفی می‌کند که به شما امکان می‌دهد روی اشیایی که با پروتکل iterable مطابقت دارند مانند String، Array، Map، Set و غیره حلقه بزنید. این حلقه مزایای حلقه for و متد forEach() را ترکیب می‌کند. مزیت حلقه for این است که می‌توانید از آن خارج شوید، و مزیت forEach() این است که مختصرتر از حلقه for است زیرا به متغیر شمارنده نیازی ندارید. با حلقه for-of، هم توانایی خروج از حلقه و هم یک نحو مختصرتر را دریافت می‌کنید.

بیشتر اوقات، من متد .forEach را ترجیح می‌دهم، اما واقعاً بستگی به کاری دارد که می‌خواهید انجام دهید. قبل از ES6، وقتی نیاز داشتیم با استفاده از break حلقه را زودتر خاتمه دهیم، از حلقه‌های for استفاده می‌کردیم. اما اکنون با ES6، می‌توانیم این کار را با حلقه‌های for-of انجام دهیم. وقتی به انعطاف‌پذیری بیشتری نیاز دارم، مانند افزایش تکرارکننده بیش از یک بار در هر حلقه، از حلقه‌های for استفاده می‌کنم.

همچنین، هنگام استفاده از حلقه for-of، اگر نیاز به دسترسی به هر دو اندیس و مقدار هر عنصر آرایه دارید، می‌توانید این کار را با متد entries() آرایه ES6 و destructuring انجام دهید:

const arr = ['a', 'b', 'c']; for (let [index, elem] of arr.entries()) { console.log(index, ': ', elem); }

تفاوت بین اشیاء قابل تغییر (mutable) و تغییرناپذیر (immutable) را توضیح دهید.

تغییرناپذیری یک اصل اصلی در برنامه نویسی تابعی است و چیزهای زیادی برای ارائه به برنامه های شیءگرا نیز دارد. یک شیء قابل تغییر، شیئی است که وضعیت آن پس از ایجاد قابل اصلاح است. یک شیء تغییرناپذیر، شیئی است که وضعیت آن پس از ایجاد قابل اصلاح نیست.

مثالی از یک شیء تغییرناپذیر در جاوااسکریپت چیست؟

در جاوااسکریپت، برخی از انواع داخلی (اعداد، رشته‌ها) تغییرناپذیر هستند، اما اشیاء سفارشی به طور کلی قابل تغییر هستند.

برخی از اشیاء داخلی تغییرناپذیر جاوااسکریپت عبارتند از Math، Date.

در اینجا چند روش برای افزودن/شبیه‌سازی تغییرناپذیری روی اشیاء ساده جاوااسکریپت آورده شده است.

ویژگی‌های ثابت شیء

با ترکیب writable: false و configurable: false، می‌توانید اساساً یک ثابت (قابل تغییر، بازتعریف یا حذف نیست) به عنوان یک ویژگی شیء ایجاد کنید، مانند:

let myObject = {}; Object.defineProperty(myObject, 'number', { value: 42, writable: false, configurable: false, }); console.log(myObject.number); // 42 myObject.number = 43; console.log(myObject.number); // 42

جلوگیری از گسترش

اگر می‌خواهید از اضافه شدن ویژگی‌های جدید به یک شیء جلوگیری کنید، اما بقیه ویژگی‌های شیء را دست نخورده باقی بگذارید، Object.preventExtensions(...) را فراخوانی کنید:

var myObject = { a: 2, }; Object.preventExtensions(myObject); myObject.b = 3; myObject.b; // undefined

در حالت غیر-strict، ایجاد b بی‌صدا شکست می‌خورد. در حالت strict، یک TypeError پرتاب می‌کند.

مهر و موم کردن (Seal)

Object.seal() یک شیء 'مهر و موم شده' ایجاد می‌کند، به این معنی که یک شیء موجود را گرفته و اساساً Object.preventExtensions() را روی آن فراخوانی می‌کند، اما همچنین تمام ویژگی‌های موجود آن را به عنوان configurable: false علامت‌گذاری می‌کند.

بنابراین، نه تنها نمی‌توانید ویژگی‌های بیشتری اضافه کنید، بلکه نمی‌توانید هیچ ویژگی موجود را دوباره پیکربندی یا حذف کنید (اگرچه هنوز می‌توانید مقادیر آنها را تغییر دهید).

منجمد کردن (Freeze)

Object.freeze() یک شیء منجمد ایجاد می‌کند، به این معنی که یک شیء موجود را گرفته و اساساً Object.seal() را روی آن فراخوانی می‌کند، اما همچنین تمام ویژگی‌های 'دسترسی‌دهنده داده' را به عنوان writable:false علامت‌گذاری می‌کند، به طوری که مقادیر آنها قابل تغییر نباشند.

این رویکرد بالاترین سطح تغییرناپذیری است که می‌توانید برای خود یک شیء به دست آورید، زیرا از هرگونه تغییر در شیء یا هر یک از ویژگی‌های مستقیم آن جلوگیری می‌کند (اگرچه، همانطور که در بالا ذکر شد، محتویات هر شیء ارجاع شده دیگر تحت تأثیر قرار نمی‌گیرد).

var immutable = Object.freeze({});

منجمد کردن یک شیء اجازه نمی‌دهد ویژگی‌های جدید به آن اضافه شود و از حذف یا تغییر ویژگی‌های موجود جلوگیری می‌کند. Object.freeze() قابلیت شمارش، قابلیت پیکربندی، قابلیت نوشتن و پروتوتایپ شیء را حفظ می‌کند. شیء منتقل شده را برمی‌گرداند و یک کپی منجمد ایجاد نمی‌کند.

مزایا و معایب تغییرناپذیری چیست؟

مزایا

  • تشخیص تغییر آسان‌تر - برابری شیء را می‌توان به روشی کارآمد و آسان از طریق برابری ارجاعی تعیین کرد. این برای مقایسه تفاوت‌های شیء در React و Redux مفید است.
  • برنامه‌هایی با اشیاء تغییرناپذیر کمتر پیچیده‌تر هستند، زیرا نیازی به نگرانی در مورد چگونگی تکامل یک شیء در طول زمان ندارید.
  • کپی‌های دفاعی دیگر ضروری نیستند وقتی اشیاء تغییرناپذیر از توابع بازگردانده می‌شوند یا به آنها ارسال می‌شوند، زیرا هیچ امکانی برای تغییر یک شیء تغییرناپذیر توسط آن وجود ندارد.
  • اشتراک‌گذاری آسان از طریق ارجاع - یک کپی از یک شیء به همان اندازه خوب است، بنابراین می‌توانید اشیاء را کش کنید یا از همان شیء چندین بار استفاده مجدد کنید.
  • Thread-safe - اشیاء تغییرناپذیر را می‌توان با خیال راحت بین threads در یک محیط multi-threaded استفاده کرد زیرا هیچ خطری برای تغییر آنها در threads‌های همزمان در حال اجرا وجود ندارد.
  • با استفاده از کتابخانه‌هایی مانند ImmutableJS، اشیاء با استفاده از اشتراک‌گذاری ساختاری اصلاح می‌شوند و حافظه کمتری برای داشتن چندین شیء با ساختارهای مشابه مورد نیاز است.

معایب

  • پیاده‌سازی‌های ساده از ساختارهای داده تغییرناپذیر و عملیات آن می‌تواند منجر به عملکرد بسیار ضعیفی شود زیرا هر بار اشیاء جدیدی ایجاد می‌شوند. توصیه می‌شود برای ساختارهای داده تغییرناپذیر کارآمد و عملیاتی که از اشتراک‌گذاری ساختاری بهره می‌برند، از کتابخانه‌ها استفاده کنید.
  • تخصیص (و آزاد کردن) بسیاری از اشیاء کوچک به جای اصلاح اشیاء موجود می‌تواند تأثیر عملکردی داشته باشد. پیچیدگی تخصیص‌دهنده یا جمع‌آوری‌کننده زباله معمولاً به تعداد اشیاء در heap بستگی دارد.
  • ساختارهای داده چرخه‌ای مانند نمودارها دشوار است. اگر دو شیء دارید که پس از مقداردهی اولیه قابل تغییر نیستند، چگونه می‌توانید آنها را به یکدیگر ارجاع دهید؟

چگونه می‌توانید در کد خود به تغییرناپذیری دست یابید؟

جایگزین استفاده از اعلان‌های const همراه با تکنیک‌های ذکر شده در بالا برای ایجاد است. برای 'تغییر' اشیاء، از عملگر spread، Object.assign، Array.concat() و غیره برای ایجاد اشیاء جدید به جای تغییر شیء اصلی استفاده کنید.

مثال‌ها:

// مثال آرایه const arr = [1, 2, 3]; const newArr = [...arr, 4]; // [1, 2, 3, 4] // مثال شیء const human = Object.freeze({ race: 'human' }); const john = { ...human, name: 'John' }; // {race: 'human', name: 'John'} const alienJohn = { ...john, race: 'alien' }; // {race: 'alien', name: 'John'}

تفاوت بین توابع همزمان (synchronous) و ناهمزمان (asynchronous) را توضیح دهید.

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

توابع ناهمزمان معمولاً یک callback را به عنوان پارامتر می‌پذیرند و اجرا بلافاصله پس از فراخوانی تابع ناهمزمان به خط بعدی ادامه می‌یابد. callback تنها زمانی فراخوانی می‌شود که عملیات ناهمزمان کامل شده و call stack خالی باشد. عملیات سنگین مانند بارگذاری داده از یک وب‌سرور یا جستجو در یک پایگاه داده باید به صورت ناهمزمان انجام شود تا thread اصلی بتواند به اجرای عملیات دیگر ادامه دهد به جای مسدود شدن تا زمانی که آن عملیات طولانی کامل شود (در مورد مرورگرها، UI متوقف خواهد شد).

Event loop چیست؟ تفاوت بین call stack و task queue چیست؟

event loop یک حلقه تک رشته‌ای است که call stack را نظارت می‌کند و بررسی می‌کند که آیا کاری برای انجام در task queue وجود دارد یا خیر. اگر call stack خالی باشد و توابع callback در task queue وجود داشته باشند، یک تابع از queue خارج شده و به call stack منتقل می‌شود تا اجرا شود.

اگر هنوز سخنرانی Philip Robert درباره Event Loop را ندیده‌اید، حتماً ببینید. این یکی از پربازدیدترین ویدیوها در مورد جاوااسکریپت است.

تفاوت‌ها در استفاده از `foo` بین `function foo() {}` و `var foo = function() {}` را توضیح دهید.

اولی یک اعلان تابع است در حالی که دومی یک عبارت تابع است. تفاوت اصلی این است که اعلان‌های تابع، بدنه آنها hoist می‌شود اما بدنه‌های عبارات تابع hoist نمی‌شوند (آنها رفتار hoisting مشابه متغیرها را دارند). برای توضیح بیشتر در مورد hoisting، به سوال بالا در مورد hoisting مراجعه کنید. اگر سعی کنید یک عبارت تابع را قبل از تعریف آن فراخوانی کنید، خطای Uncaught TypeError: XXX is not a function را دریافت خواهید کرد.

اعلان تابع

foo(); // 'FOOOOO' function foo() { console.log('FOOOOO'); }

عبارت تابع

foo(); // Uncaught TypeError: foo is not a function var foo = function () { console.log('FOOOOO'); };

تفاوت‌های بین متغیرهای ایجاد شده با استفاده از `let`، `var` یا `const` چیست؟

متغیرهای اعلان شده با کلمه کلیدی var در محدوده تابعی که در آن ایجاد شده‌اند، یا اگر خارج از هر تابعی ایجاد شده باشند، در محدوده شیء سراسری قرار می‌گیرند. let و const دارای محدوده بلوکی هستند، به این معنی که فقط در نزدیک‌ترین مجموعه از براکت‌های مجعد (تابع، بلوک if-else یا حلقه for) قابل دسترسی هستند.

function foo() { // همه متغیرها در داخل توابع قابل دسترسی هستند. var bar = 'bar'; let baz = 'baz'; const qux = 'qux'; console.log(bar); // bar console.log(baz); // baz console.log(qux); // qux } console.log(bar); // ReferenceError: bar is not defined console.log(baz); // ReferenceError: baz is not defined console.log(qux); // ReferenceError: qux is not defined
if (true) { var bar = 'bar'; let baz = 'baz'; const qux = 'qux'; } // متغیرهای اعلان شده با var در هر نقطه از محدوده تابع قابل دسترسی هستند. console.log(bar); // bar // متغیرهای تعریف شده با let و const در خارج از بلوکی که در آن تعریف شده‌اند قابل دسترسی نیستند. console.log(baz); // ReferenceError: baz is not defined console.log(qux); // ReferenceError: qux is not defined

var اجازه می‌دهد متغیرها hoist شوند، به این معنی که می‌توان به آنها در کد قبل از اعلانشان ارجاع داد. let و const این اجازه را نمی‌دهند و به جای آن خطا پرتاب می‌کنند.

console.log(foo); // undefined var foo = 'foo'; console.log(baz); // ReferenceError: cannot access lexical declaration 'baz' before initialization let baz = 'baz'; console.log(bar); // ReferenceError: cannot access lexical declaration 'bar' before initialization const bar = 'bar';

اعلان مجدد یک متغیر با var خطایی پرتاب نمی‌کند، اما let و const این کار را می‌کنند.

var foo = 'foo'; var foo = 'bar'; console.log(foo); // 'bar' let baz = 'baz'; let baz = 'qux'; // Uncaught SyntaxError: Identifier 'baz' has already been declared

let و const در این تفاوت دارند که let اجازه تخصیص مجدد مقدار متغیر را می‌دهد در حالی که const این اجازه را نمی‌دهد.

// این درست است. let foo = 'foo'; foo = 'bar'; // این باعث ایجاد استثنا می‌شود. const baz = 'baz'; baz = 'qux';

تفاوت بین کلاس ES6 و سازنده‌های تابع ES5 چیست؟

ابتدا به مثالی از هر کدام نگاه کنیم:

// سازنده تابع ES5 function Person(name) { this.name = name; } // کلاس ES6 class Person { constructor(name) { this.name = name; } }

برای سازنده‌های ساده، آنها بسیار شبیه به نظر می‌رسند.

تفاوت اصلی در سازنده هنگام استفاده از وراثت مشخص می‌شود. اگر بخواهیم یک کلاس Student ایجاد کنیم که از Person به ارث ببرد و یک فیلد studentId اضافه کنیم، علاوه بر موارد بالا، باید این کارها را انجام دهیم.

// سازنده تابع ES5 function Student(name, studentId) { // فراخوانی سازنده ابرکلاس برای مقداردهی اولیه اعضای مشتق شده از ابرکلاس. Person.call(this, name); // مقداردهی اولیه اعضای خود زیرکلاس. this.studentId = studentId; } Student.prototype = Object.create(Person.prototype); Student.prototype.constructor = Student; // کلاس ES6 class Student extends Person { constructor(name, studentId) { super(name); this.studentId = studentId; } }

استفاده از وراثت در ES5 بسیار پرحرف‌تر است و نسخه ES6 آسان‌تر قابل درک و به خاطر سپردن است.

آیا می‌توانید یک مورد استفاده برای سینتکس جدید تابع پیکانی (arrow => function) ارائه دهید؟ این سینتکس جدید چه تفاوتی با توابع دیگر دارد؟

یکی از مزایای آشکار توابع پیکانی، ساده‌سازی سینتکس مورد نیاز برای ایجاد توابع، بدون نیاز به کلمه کلیدی function است. this در داخل توابع پیکانی نیز به محدوده احاطه‌کننده مرتبط می‌شود که متفاوت از توابع عادی است که در آنها this توسط شیء فراخوانی کننده تعیین می‌شود. this با محدوده واژگانی مفید است هنگام فراخوانی callback‌ها، به خصوص در کامپوننت‌های React.

چه مزیتی در استفاده از سینتکس فلش (arrow syntax) برای یک متد در یک سازنده وجود دارد؟

مزیت اصلی استفاده از یک تابع فلش به عنوان متد در داخل یک سازنده این است که مقدار this در زمان ایجاد تابع تنظیم می‌شود و پس از آن نمی‌تواند تغییر کند. بنابراین، هنگامی که سازنده برای ایجاد یک شیء جدید استفاده می‌شود، this همیشه به آن شیء اشاره خواهد کرد. به عنوان مثال، فرض کنید یک سازنده Person داریم که یک نام کوچک را به عنوان آرگومان می‌گیرد و دو متد برای console.log کردن آن نام دارد، یکی به عنوان یک تابع معمولی و دیگری به عنوان یک تابع فلش:

const Person = function (firstName) { this.firstName = firstName; this.sayName1 = function () { console.log(this.firstName); }; this.sayName2 = () => { console.log(this.firstName); }; }; const john = new Person('John'); const dave = new Person('Dave'); john.sayName1(); // John john.sayName2(); // John // مقدار 'this' تابع معمولی می‌تواند تغییر کند، اما تابع فلش نمی‌تواند john.sayName1.call(dave); // Dave (زیرا 'this' اکنون شیء dave است) john.sayName2.call(dave); // John john.sayName1.apply(dave); // Dave (زیرا 'this' اکنون شیء dave است) john.sayName2.apply(dave); // John john.sayName1.bind(dave)(); // Dave (زیرا 'this' اکنون شیء dave است) john.sayName2.bind(dave)(); // John var sayNameFromWindow1 = john.sayName1; sayNameFromWindow1(); // undefined (زیرا 'this' اکنون شیء window است) var sayNameFromWindow2 = john.sayName2; sayNameFromWindow2(); // John

نکته اصلی در اینجا این است که this می‌تواند برای یک تابع معمولی تغییر کند، اما زمینه (context) برای یک تابع فلش همیشه یکسان باقی می‌ماند. بنابراین حتی اگر تابع فلش خود را به قسمت‌های مختلف برنامه خود ارسال می‌کنید، نیازی نیست نگران تغییر زمینه باشید.

این می‌تواند به ویژه در کامپوننت‌های کلاس React مفید باشد. اگر یک متد کلاس را برای چیزی مانند یک کنترل‌کننده کلیک با استفاده از یک تابع معمولی تعریف کنید، و سپس آن کنترل‌کننده کلیک را به عنوان یک prop به یک کامپوننت فرزند منتقل کنید، باید this را نیز در سازنده کامپوننت والد bind کنید. اگر به جای آن از یک تابع فلش استفاده کنید، نیازی به bind کردن this نیست، زیرا متد به طور خودکار مقدار this خود را از زمینه لغوی احاطه‌کننده خود دریافت خواهد کرد.

تعریف تابع مرتبه بالاتر (higher-order function) چیست؟

یک تابع مرتبه بالاتر، هر تابعی است که یک یا چند تابع را به عنوان آرگومان می‌گیرد، که از آنها برای کار روی برخی داده‌ها استفاده می‌کند، و/یا یک تابع را به عنوان نتیجه باز می‌گرداند. توابع مرتبه بالاتر برای انتزاع برخی عملیاتی طراحی شده‌اند که به طور مکرر انجام می‌شوند. مثال کلاسیک این موضوع map است که یک آرایه و یک تابع را به عنوان آرگومان می‌گیرد. سپس map از این تابع برای تبدیل هر آیتم در آرایه استفاده می‌کند و یک آرایه جدید با داده‌های تبدیل شده را باز می‌گرداند. مثال‌های محبوب دیگر در جاوااسکریپت forEach، filter و reduce هستند. یک تابع مرتبه بالاتر فقط نیازی به دستکاری آرایه‌ها ندارد، زیرا موارد استفاده زیادی برای بازگرداندن یک تابع از تابع دیگر وجود دارد. Function.prototype.bind یکی از این نمونه‌ها در جاوااسکریپت است.

Map

فرض کنید یک آرایه از نام‌ها داریم که باید هر رشته را به حروف بزرگ تبدیل کنیم.

const names = ['irish', 'daisy', 'anna'];

روش دستوری (imperative) به این صورت خواهد بود:

const transformNamesToUppercase = function (names) { const results = []; for (let i = 0; i < names.length; i++) { results.push(names[i].toUpperCase()); } return results; }; transformNamesToUppercase(names); // ['IRISH', 'DAISY', 'ANNA']

استفاده از .map(transformerFn) کد را کوتاه‌تر و اعلانی‌تر می‌کند.

const transformNamesToUppercase = function (names) { return names.map((name) => name.toUpperCase()); }; transformNamesToUppercase(names); // ['IRISH', 'DAISY', 'ANNA']

آیا می‌توانید مثالی از تجزیه شیء یا آرایه (destructuring) ارائه دهید؟

Destructuring یک عبارت موجود در ES6 است که روشی مختصر و راحت برای استخراج مقادیر اشیاء یا آرایه‌ها و قرار دادن آنها در متغیرهای متمایز را فعال می‌کند.

تجزیه آرایه (Array destructuring)

// انتساب متغیر. const foo = ['one', 'two', 'three']; const [one, two, three] = foo; console.log(one); // 'one' console.log(two); // 'two' console.log(three); // 'three'
// تعویض متغیرها let a = 1; let b = 3; [a, b] = [b, a]; console.log(a); // 3 console.log(b); // 1

تجزیه شیء (Object destructuring)

// انتساب متغیر. const o = { p: 42, q: true }; const { p, q } = o; console.log(p); // 42 console.log(q); // true

لیترال‌های قالب ES6 (Template Literals) انعطاف‌پذیری زیادی در تولید رشته‌ها ارائه می‌دهند، آیا می‌توانید مثالی ارائه دهید؟

لیترال‌های قالب (Template literals) به ساده‌سازی درون‌یابی رشته (string interpolation) یا گنجاندن متغیرها در یک رشته کمک می‌کنند. قبل از ES2015، انجام کاری مانند این رایج بود:

var person = { name: 'Tyler', age: 28 }; console.log( 'Hi, my name is ' + person.name + ' and I am ' + person.age + ' years old!', ); // 'Hi, my name is Tyler and I am 28 years old!'

با لیترال‌های قالب، اکنون می‌توانید همان خروجی را به این صورت ایجاد کنید:

const person = { name: 'Tyler', age: 28 }; console.log(`Hi, my name is ${person.name} and I am ${person.age} years old!`); // 'Hi, my name is Tyler and I am 28 years old!'

توجه داشته باشید که برای نشان دادن استفاده از یک لیترال قالب از بک‌تیک (``)، نه نقل قول، استفاده می‌کنید و می‌توانید عبارات را درون جای‌گیرنده‌های ${} قرار دهید.

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

console.log('This is line one.\nThis is line two.'); // This is line one. // This is line two.

یا اگر می‌خواستید آن را در کد خود به چند خط تقسیم کنید تا مجبور نباشید برای خواندن یک رشته طولانی در ویرایشگر متن خود به سمت راست اسکرول کنید، می‌توانستید آن را به این صورت نیز بنویسید:

console.log('This is line one.\n' + 'This is line two.'); // This is line one. // This is line two.

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

console.log(`This is line one. This is line two.`); // This is line one. // This is line two.

یک مورد استفاده دیگر از لیترال‌های قالب می‌تواند به عنوان جایگزینی برای کتابخانه‌های قالب‌بندی برای درون‌یابی متغیرهای ساده باشد:

const person = { name: 'Tyler', age: 28 }; document.body.innerHTML = ` <div> <p>Name: ${person.name}</p> <p>Age: ${person.age}</p> </div> `;

توجه داشته باشید که کد شما با استفاده از .innerHTML ممکن است در برابر XSS آسیب‌پذیر باشد. داده‌های خود را قبل از نمایش، اگر از کاربر آمده‌اند، پاک‌سازی کنید!

آیا می توانید مثالی از تابع کاری (curry function) و اینکه چرا این نحو مزیتی ارائه می دهد، ارائه دهید؟

Currying الگویی است که در آن یک تابع با بیش از یک پارامتر به چندین تابع تقسیم می شود که در صورت فراخوانی متوالی، تمام پارامترهای مورد نیاز را یکی یکی جمع آوری می کنند. این تکنیک می تواند برای خوانایی و ترکیب پذیری کدهای نوشته شده به سبک تابعی مفید باشد. مهم است که توجه داشته باشید که برای اینکه یک تابع curried شود، باید ابتدا به عنوان یک تابع شروع شود، سپس به دنباله ای از توابع تقسیم شود که هر کدام یک پارامتر را می پذیرند.

function curry(fn) { if (fn.length === 0) { return fn; } function _curried(depth, args) { return function (newArgument) { if (depth - 1 === 0) { return fn(...args, newArgument); } return _curried(depth - 1, [...args, newArgument]); }; } return _curried(fn.length, []); } function add(a, b) { return a + b; } var curriedAdd = curry(add); var addFive = curriedAdd(5); var result = [0, 1, 2, 3, 4, 5].map(addFive); // [5, 6, 7, 8, 9, 10]

مزایای استفاده از سینتکس spread چیست و چه تفاوتی با سینتکس rest دارد؟

سینتکس spread در ES6 هنگام کدنویسی در پارادایم تابعی بسیار مفید است زیرا می‌توانیم به راحتی از آرایه‌ها یا اشیاء کپی بسازیم بدون اینکه به Object.create، slice یا یک تابع کتابخانه‌ای متوسل شویم. این ویژگی زبانی اغلب در پروژه‌های Redux و RxJS استفاده می‌شود.

function putDookieInAnyArray(arr) { return [...arr, 'dookie']; } const result = putDookieInAnyArray(['I', 'really', 'don't', 'like']); // ['I', 'really', 'don't', 'like', 'dookie'] const person = { name: 'Todd', age: 29, }; const copyOfTodd = { ...person };

سینتکس rest در ES6 یک روش کوتاه برای گنجاندن تعداد دلخواه آرگومان‌ها برای ارسال به یک تابع ارائه می‌دهد. این مانند معکوس سینتکس spread است، داده‌ها را می‌گیرد و آنها را در یک آرایه قرار می‌دهد به جای باز کردن آرایه‌ای از داده‌ها، و در آرگومان‌های تابع، و همچنین در تخصیص‌های destructuring آرایه و شیء کار می‌کند.

function addFiveToABunchOfNumbers(...numbers) { return numbers.map((x) => x + 5); } const result = addFiveToABunchOfNumbers(4, 5, 6, 7, 8, 9, 10); // [9, 10, 11, 12, 13, 14, 15] const [a, b, ...rest] = [1, 2, 3, 4]; // a: 1, b: 2, rest: [3, 4] const { e, f, ...others } = { e: 1, f: 2, g: 3, h: 4, }; // e: 1, f: 2, others: { g: 3, h: 4 }

چگونه می توانید کد را بین فایل ها به اشتراک بگذارید؟

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

در سمت کلاینت (محیط مرورگر)، تا زمانی که متغیرها/توابع در محدوده سراسری (window) اعلام شده باشند، همه اسکریپت ها می توانند به آنها ارجاع دهند. به طور جایگزین، تعریف ماژول ناهمزمان (AMD) را از طریق RequireJS برای یک رویکرد ماژولارتر اتخاذ کنید.

در سمت سرور (Node.js)، روش رایج استفاده از CommonJS بوده است. هر فایل به عنوان یک ماژول در نظر گرفته می شود و می تواند متغیرها و توابع را با اتصال آنها به شیء module.exports صادر کند.

ES2015 یک نحو ماژول را تعریف می کند که هدف آن جایگزینی AMD و CommonJS است. این در نهایت در هر دو محیط مرورگر و Node پشتیبانی خواهد شد.

چرا ممکن است بخواهید اعضای کلاس استاتیک ایجاد کنید؟

اعضای کلاس استاتیک (ویژگی‌ها/متدها) به یک نمونه خاص از یک کلاس مرتبط نیستند و صرف نظر از اینکه کدام نمونه به آن ارجاع می‌دهد، مقدار یکسانی دارند. ویژگی‌های استاتیک معمولاً متغیرهای پیکربندی هستند و متدهای استاتیک معمولاً توابع ابزاری خالص هستند که به وضعیت نمونه وابسته نیستند.