۱۰ مه ۲۰۲۴

پلیفیل‌ها و ترنسپایلرها

زبان جاوااسکریپت پیوسته در حال تکامل است. پیشنهادهایی برای بهتر شدن آن به‌طور منظم صورت می‌گیرد، این پیشنهاد‌ها بررسی می‌شوند و اگر ارزشمند باشند، به لیست https://tc39.github.io/ecma262/ اضافه می‌شوند و سپس برای مشخصات زبان (specification) پیش می‌روند.

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

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

یک صفحه‌ی خوب برای این که ببینید در حال حاضر چه چیزهایی پشتیبانی می‌شود اینجاست https://compat-table.github.io/compat-table/es6/ (خیلی بزرگ است، ما چیزهای زیادی برای مطالعه داریم).

به عنوان توسعه‌دهنده، ما همیشه دوست داریم از ویژگی‌ها و امکانات جدید استفاده کنیم. هر چه جدیدتر، بهتر!

از طرف دیگر، دوست داریم کدهایمان روی مرورگرهای قدیمی‌تر که امکانات جدید را نمی‌فهمند هم کار کنند. اما چطور می‌شود این کار را انجام داد؟

دو ابزار برای این کار وجود دارد:

  1. ترنسپایلرها (Transpilers).
  2. پلیفیل‌ها (Polyfills).

هدف ما در این فصل این است که درک کنیم این دو چگونه کار می‌کنند و جایگاه آن‌ها در توسعه وب چیست.

ترنسپایلرها

یک ترنسپایلر در واقع قطعه‌ای نرم‌افزار است که می‌تواند کد مدرن و جدید را parse کند (“بخواند و بفهمد”) و سپس همان کد را با syntax قدیمی بازنویسی کند به‌طوری که خروجی کد یکسان باشد.

برای مثال جاوااسکریپت تا سال ۲۰۲۰ “nullish coalescing عملگر” ?? را نداشت. و اگر کاربری از یک مرورگر منسوخ‌شده استفاده کند، ممکن است کدی مانند height = height ?? 100 را متوجه نشود.

یک ترنسپایلر این کد را آنالیز می‌کند و height ?? 100 را به‌صورت (height !== undefined && height !== null) ? height : 100 بازنویسی می‌کند.

// قبل از اجرا شدن ترنسپایلر
height = height ?? 100;

// بعد از اجرا شدن ترنسپایلر
height = height !== undefined && height !== null ? height : 100;

کد بازنویسی شده مناسب موتورهای قدیمی‌تر جاوااسکریپت است.

معمولا توسعه‌دهنده ترنسپایلر را روی کامپیوتر خودش اجرا می‌کند و سپس کد transpileشده را روی سرور deploy می‌کند.

حالا که صحبتش شد، بهتر است بدانید Babel یکی از برجسته‌ترین ترنسپایلرها است.

سیستم‌های build پروژه مدرن مثل webpack این امکان را می‌دهند که بعد از هر بار تغییر کد، ترنسپایلر به‌صورت اتوماتیک اجرا شود و برای همین ادغام کردن آن در روند توسعه کار بسیار ساده‌ای است.

پلیفیل‌ها

فیچر‌ها و امکانات جدید یک زبان می‌توانند علاوه بر syntax و عملگرهای جدید، تابع‌های جدید نیز باشند.

برای مثال Math.trunc(n) یک تابع است که بخش دهدهی یک عدد را حذف می‌کند. مانند Math.trunc(1.23) که 1 را بر می‌گرداند.

در برخی از موتورهای (خیلی قدیمی) جاوااسکریپت تابع Math.trunc وجود ندارد و چنین کدی اجرا نمی‌شود.

از آن‌جایی که داریم راجع‌به تابع‌های جدید صحبت می‌کنیم و بحث تغییر syntax نیست، اینجا چیزی برای transpile وجود ندارد. فقط باید تابع ناموجود را تعریف کنیم.

اسکریپتی که تابع‌های جدید آپدیت و یا اضافه می‌کند، «پلیفیل» نام دارد. در واقع جای خالی را پر می‌کند و پیاده‌سازی‌های لازم را انجام می‌دهد.

در این مثال خاص، پلیفیلی که برای Math.trunc وجود دارد یک اسکریپت است که آن را پیاده‌سازی کرده است. مانند زیر:

if (!Math.trunc) { // اگر چنین تابعی وجود ندارد
  // آن زا پیاده‌سازی کن
  Math.trunc = function (number) {
    // Math.ceil و Math.floor جتی در موتورهای قدیمی جاوااسکریپت هم حضور دارند
    // و در همین tutorial جلوتر آموزش داده می‌شوند
    return number < 0 ? Math.ceil(number) : Math.floor(number);
  };
}

جاوااسکریپت یک زبان به‌شدت داینامیک است. اسکریپت‌ها می‌توانند هر تابعی را تغییر دهند یا اضافه کنند. حتی تابع‌های built-in.