۲۵ ژوئیه ۲۰۲۲

ماژول ها، معرفی

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

تا مدت ها، جاوااسکریپت سینتکسی برای نوشتن ماژول ها در سطح زبان نداشت.

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

این ها نمونه هایی از این کتابخانه ها است (این بخش صرفا جنبه تاریخی دارد):

  • AMD – یکی از قدیمی ترین سیستم های ماژول بندی، که اولین بار توسط کتابخانه require.js پیاده سازی شد .
  • CommonJS – سیستم ماژول بندی که برای سرورها Node.js درست شد.
  • UMD – یک سیستم ماژول بندی که به عنوان یک سیستم جهانی شناخته شده و با هردو سیستم AMD و CommonJS همخوانی دارد.

همه این سیستم ها کم کم تبدیل به بخشی از تاریخ شدند اما هنوز هم می توان آن ها را در اسکریپت های قدیمی مشاهده کرد.

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

ماژول چیست؟

ماژول در اصل یک فایل است. هر اسکریپت یک ماژول است. به همین سادگی.

ماژول ها می توانند یکدیگر را لود کرده و به وسیله توابع خاصی مانند export و import بین هم تابع و کارایی رد و بدل کنند، به وسیله صدا زدن تابعی از یک ماژول در یک ماژول دیگر:

  • export این کلید واژه متغیرها و توابعی را مشخص می کند که باید بیرون از این ماژول قابل دسترسی باشند.
  • import به ما اجازه ایمپورت کردن و استفاده از توانایی های دیگر ماژول ها را می دهد.

برای مثال، اگر ما یک فایل با نام sayHi.js داشته باشیم که یک تابع را اکسپورت:

// 📁 sayHi.js
export function sayHi(user) {
  alert(`Hello, ${user}!`);
}

…در این حالت یک فایل دیگر می تواند این ماژول را ایمپورت کرده و از این تابع استفاده کند:

// 📁 main.js
import {sayHi} from './sayHi.js';

alert(sayHi); // تابع...
sayHi('John'); // Hello, John!

تابع import ماژول را بر اساس مسیر ./sayHi.js که بر مبنای فایل فعلی است، بارگذاری کرده، سپس تابع اکسپورت شده sayHi را به متغیر مناسب اختصاص می دهد.

بگذارید تا این مثال را در مرورگر امتحان کنیم.

از آن جایی که ماژول ها از کلیدواژه ها و امکانات خاصی استفاده می کنند، ما باید به وسیله مشخصه <script type="module"> به مرورگر بگوییم که این اسکریپت یک ماژول است.

مانند مثال زیر:

نتیجه
say.js
index.html
export function sayHi(user) {
  return `Hello, ${user}!`;
}
<!doctype html>
<script type="module">
  import {sayHi} from './say.js';

  document.body.innerHTML = sayHi('John');
</script>

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

ماژول ها تنها در پروتکل HTTP(s) قابل استفاده اند، و در فایل های محلی نمی توان از آن ها استفاده کرد.

اگر سعی کنید که یک صفحه وب را به صورت محلی، از طریق پروتکل file:// باز کنید، توابع import/export کار نمی کنند. برای این کار از یک وب سرور لوکال استفاده کنید، مانند static-server یا از قابلیت “سرور زنده” ویرایشگر متن خود استفاده کنید، مانند VS Code Live Server Extension برای تست ماژول خود.

امکانات اصلی ماژول ها

چه مواردی در ماژول ها با اسکریپت های “معمولی” متفاوت است؟

بعضی از این امکانات، در هر دو محیط مرورگر و سرور معتبر هستند.

حالت “use strict” به صورت پیش فرض فعال است.

در ماژول ها حالت use strict به صورت پیش فرض فعال است، برای مثال اختصاص دادن مقدار به یک متغیر که از قبل تعریف نشده است باعث بوجود آمدن خطا می شود.

<script type="module">
  a = 5; // خطا
</script>

محدوده/اسکوپ سطح ماژول

هر ماژول اسکوپ سطح بالای خود را دارد. به عبارت دیگر، توابع و متغیر های سطح بالا در یک ماژول قابل دسترسی توسط اسکریپت های دیگر نیستند.

در مثال پایین، دو اسکریپت ایمپورت شده اند، و hello.js سعی در استفاده از متغیر user که در فایل user.js تعریف شده است، کرده و شکست خورده است.

نتیجه
hello.js
user.js
index.html
alert(user); // no such variable (each module has independent variables)
let user = "John";
<!doctype html>
<script type="module" src="user.js"></script>
<script type="module" src="hello.js"></script>

در موقع کار با ماژول ها انتظار می رود که هر چیزی که قرار است از بیرون قابل دسترسی باشد export و هر چیزی که آن ها در اسکریپت خود نیاز دارند import شود.

  • user.js باید متغیر user را اکسپورت کند.
  • hello.js باید آن را از ماژول user.js ایمپورت کند.

به عبارتی دیگر، در ماژول‌ها ما از import/export به جای متغیرهای سراسری (global) استفاده می‌کنیم.

این نمونه درست این کد است:

نتیجه
hello.js
user.js
index.html
import {user} from './user.js';

document.body.innerHTML = user; // John
export let user = "John";
<!doctype html>
<script type="module" src="hello.js"></script>

در مرورگر، یک اسکوپ سطح بالا ی مستقل هم برای هر تگ <script type="module"> وجود دارد:

اینجا دو اسکریپت در یک صفحه وجود دارد، هر دو از نوع type="module" هستند. آن‌ها متغیرهای سطح بالا(top-level) هم را نمی‌بینند:

<script type="module">
  // متغیر تنها در اسکریپت ماژول قابل دسترسی است.
  let user = "John";
</script>

<script type="module">
  alert(user); // Error: user is not defined
</script>
لطفاً توجه کنید:

در مرورگر، ما می‌توانیم یک متغیر window-level گلوبال بسازیم با اختصاص دادن آن صریحاً به یک مقدار window، برای مثال: windows.user = "John".

پس همه اسکریپت‌ها آن را خواهند دید، هم با type="module" و هم بدون آن.

گرچه به این روش اشاره شد، ولی استفاده از چنین متغیرهای گلوبالی توصیه‌شده نیست. لطفاً تلاش کنید که از آن استفاده نکنید.

کد یک ماژول تنها اولین بار که به اسکریپت ما ایمپورت شده، ارزیابی می شود.

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

این رفتار عواقب مهمی دارد، که باید از آن‌ها آگاه باشیم.

بگذارید تا آن ها را در مثال بررسی کنیم:

اول از همه، اگر اجرای کد ما باعث افتادن یک سری اتفاقات شود، مانند نشان دادن یک پیغام ، در این صورت چندین بار ایمپورت کردن کد تنها باعث یک بار اجرا شدن این پیغام می شود. ---- تنها بار اول.

// 📁 alert.js
alert("Module is evaluated!");
// ایمپورت کردن یک ماژول مشابه در دو فایل متفاوت

// 📁 1.js
import `./alert.js`; // ماژول ارزیابی و اجرا می شود.

// 📁 2.js
import `./alert.js`; // (پیغامی نمایش داده نمی شود.)

ایمپورت دوم چیزی را نشان نمی‌دهد، چون ماژول پیش از این ارزیابی شده است.

یک قانون وجود دارد: ماژول‌های top-level باید برای مقداردهی اولیه استفاده شوند، ساختن ساختارهای داده‌ای داخلی. اگر ما نیاز به ساخت چیزی داریم که چندین بار آن را فراخوانی کنیم – باید آن را به عنوان یک تابع اکسپورت کنیم، مانند کاری که با sayHi در بالا کردیم.

خب، حال با هم یک مثال پیشرفته تر را می بینیم.

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

// 📁 admin.js
export let admin = {
  name: "John"
};

اگر این ماژول چند مرتبه در چند فایل ایمپورت شود، ماژول تنها در مرتبه اول ارزیابی می شود، این به این معناست که آبجکت admin یک بار درست شده، و سپس به جاهای دیگر ایمپورت می شود.

همه مکانهایی که ماژول ایمپورت شده است، دقیقا یک و تنها یک آبجکت admin دریافت می کنند.

// 📁 1.js
import {admin} from './admin.js';
admin.name = "Pete";

// 📁 2.js
import {admin} from './admin.js';
alert(admin.name); // Pete

// هر دو فایل ‍1.js و 2.js یک آبجکت مشابه را ایمپورت می کنند.
// هر تغییری که در فایل 1.js ایجاد شود، در فایل 2.js نیز قابل مشاهده است.

همانطور که می‌بینید، وقتی 1.js مقدار name را در admin ایمپورت شده تغییر می‌دهد، سپس 2.js می‌تواند مقدار جدید admin.name را ببیند.

این دقیقاً به خاطر این است که ماژول فقط یک بار اجرا شده است. اکسپورت‌ها تولیدشده‌اند، و سپس بین ایمپورت‌ها به اشتراک گذاشته‌شده‌اند، پس اگر چیزی شیء admin را تغییر دهد، بقیهٔ ایمپورت‌ها هم آن را می‌بینند.

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

به عبارتی دیگر، یک ماژول می‌تواند عملکردی عمومی ارائه‌دهد که نیاز به راه‌اندازی دارد. برای مثال احراز هویت نیازمند مدارک است. پس می‌تواند یک شی configuration اکسپورت کند و انتظار داشته باشد تا کد بیرونی آن را مقداردهی کند.

اینجا الگوی کلاسیک را می‌بینید:

  1. یک ماژول مقادیر قابل کافیگ‌شدن را اکسپورت می‌کند، مثلاً: یک شی قابل کانفیگ
  2. در ایمپورت اول، آن را مقداردهی می‌کنیم، در مقادیر آن می‌نویسیم. برنامهٔ top-level ما آن را انجام می‌دهد.
  3. ایمپورت‌های آتی از ماژول استفاده می‌کنند.

برای مثال، ماژول admin.js ممکن است یک سری قابلیت ها به ما بدهد، اما از ما انتظار دارد که یک سری متغیر ها از بیرون آبجکت admin به آن پاس دهیم;

// 📁 admin.js
export let config = { };

export function sayHi() {
  alert(`Ready to serve, ${config.user}!`);
}

در اینجا، admin.js ‍شی config را اسکپورت می‌کند (مقدار اولیه خالی، ولی ممکن مقادیر پیش‌فرض نیز داشته باشد).

سپس در init.js، اولین اسکریپت برنامهٔ ما، ما config را از این ایمپورت می‌کنیم و config.user را مقداردهی می‌کنیم.

// 📁 init.js
import {config} from './admin.js';
config.user = "Pete";

…حالا ماژول admin.js کانفیگ‌شده است.

ایمپورت‌های آتی می‌توانند آن را فراخوانی کنند، و آن به درستی شی user فعلی را نمایش می‌دهد:

// 📁 another.js
import {sayHi} from './admin.js';

sayHi(); // Ready to serve, Pete!

شئ import.meta

آبجکت ‍import.meta دارای یک سری اطلاعات درباره ماژول فعلی است.

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

<script type="module">
  alert(import.meta.url); // آدرس اسکریپت
  // برای یک اسکریپت این‌لاین - آدرس صفحهٔ فعلی HTML
</script>

در یک ماژول، “this” تعریف نشده است

این یک قابلیت جزئی است، اما برای کامل بودن آموزش به آن اشاره می کنیم.

در یک ماژول، ‍this سطح بالا undefined است.

مقایسه آن با اسکریپت های غیر ماژول، که در آن ها this آبجکت جهانی است:

<script>
  alert(this); // window
</script>

<script type="module">
  alert(this); // undefined
</script>

قابلیت های مخصوص محیط مرورگر

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

اگر این اولین بار است که این آموزش را می خوانید، یا از جاوااسکریپت در مرورگر استفاده نمی کنید، می توانید این بخش را رد کنید.

اسکریپت های ماژولی به تعویق افتاده اند. (deferred)

اسکریپت ها از نوع ماژول همیشه به تعویق افتاده اند، دقیقا مانند خصوصیت defer (در فصل [] (info:script-async-defer) توضیح داده شده است.)، برای هر دو نوع اکسترنال و اینلاین.

به عبارت دیگر:

  • دانلود اسکریپت های از نوع ماژول خارجی (external) ‍<script type="module" src="..."> جلوی پردازش HTML را نمی گیردند، این اسکریپت ها موازی با دیگر منابع بارگیری می شوند.
  • اسکریپت های ماژولی تا بارگیری کامل اسناد HTML صبر می کنند (حتی با وجود اینکه این اسکریپت ها کوچک بوده و سریع تر از HTML بارگیری می شوند)، و سپس اجرا می شوند.
  • اسکریپت ها به همان ترتیبی که نوشته می شوند، اجرا می شوند: اسکریپتی که در فایل ها اول آمده است، اول اجرا می شود.

به عنوان یک عارضه جانبی، اسکریپت های ماژولی همیشه صفحه HTML کامل بارگیری شده را “می بینند”، از جمله عناصری که در متن جلوتر از آن ها قرار دارند.

برای مثال:

<script type="module">
  alert(typeof button); // آبجکت: اسکریپت می تواند دکمه ای که زیر آن هست را "ببیند".
  // به دلیل اینکه ماژول ها به تعویق افتاده اند، اسکریپت بعد از بارگیری کل صفحه اجرا می شود.
</script>

در مقایسه با اسکریپت معمولی زیر:

<script>
  alert(typeof button); // دکمه undefined است، به دلیل اینکه اسکریپت نمی تواند عناصر زیر را ببیند.
  // اسکریپت های معمولی بالافاصله قبل از اینکه بقیه صفحه پردازش شود، اجرا می شوند.
</script>

<button id="button">Button</button>

توجه کنید که: اسکریپت دوم در حقیقت قبل از اولی اجرا می شود! در نتیجه ما ابتدا undefined و سپس object را می بینیم.

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

وقتی که از ماژول ها استفاده می کنیم، باید به این نکته توجه کنیم که صفحات HTML همان طور که بارگیری می شوند، به کاربر نشان داده می شوند و ماژول های جاوااسکریپت بعد از آن اجرا می شوند، پس کاربر صفحه را قبل از اینکه برنامه جاوااسکریپت اجرا شود، می بیند. بعضی از قابلیت ها ممکن است که کار نکنند. ما باید از یک “مشخص کننده مقدار بارگیری شده” استفاده کنیم، یا مطمئن شویم که این پدیده باعث سردرگم شدن کاربر نمی شود.

Async در اسکریپت های اینلاین معتبر است.

در اسکریپت های غیر ماژولی، مشخصه async تنها در اسکریپت های اکسترنال کار می کنند. اسکریپت های غیر ترتیبی به محض آماده شدن، اجرا می شوند، بدون توجه به اسکریپت های دیگر یا کد های HTML.

برای اسکریپت های ماژولی، در حالت اینلاین هم معتبر است.

برای مثال،‌ اسکریپت اینلاین زیر async دارد، در نتیجه برای هیچ چیزی صبر نمی کند.

اسکریپت، ایمپورت (fetche ./analytics.js) را انجام می دهد و وقتی که آماده شد، اجرا می شود. حتی اگر سند HTML یا دیگر اسکریپت ها آماده نباشند.

این رفتار برای قابلیت هایی که به هیچ چیز دیگری وابسته نیستند، خوب هست، مانند شمارنده ها، تبلیغات، event listener های در سطح سند.

<!-- همه وابستگی ها دریافت شده(analytics.js)، و اسکریپت اجرا می شود. -->
<!-- برای دیگر سندها یا تگ های <script> منتظر نمی شود. -->
<script async type="module">
  import {counter} from './analytics.js';

  counter.count();
</script>

اسکریپت های اکسترنال

اسکریپت های اکسترنال که از نوع module ‍‍type="module" هستند، دو خصوصیت متفاوت دارند:

  1. اسکریپت های اکسترنال با src مشابه تنها یک مرتبه اجرا می شوند:

    <!-- اسکریپت my.js تنها یکبار دریافت و اجرا می شود -->
    <script type="module" src="my.js"></script>
    <script type="module" src="my.js"></script>
  2. اسکریپت های اکسترنالی که از یک منبع دیگر (مانند یک سایت دیگر) دریافت شده اند. به CORS header نیاز دارند، همانگونه که در فصل Fetch: Cross-Origin Requests توضیح داده شد. به عبارت دیگر، اگر یک اسکریپت ماژولی از یک منبع دیگر دریافت شده باشد، سرور دیگر باید هدر Access-Control-Allow-Origin را ست کرده باشد تا دریافت امکان پذیر باشد.

    <!-- یک سایت دیگر مانند another-site.com باید Access-Control-Allow-Origin را فراهم کرده باشد. -->
    <!-- در غیر این صورت، اسکریپت اجرا نخواهد شد. -->
    <script type="module" src="http://another-site.com/their.js"></script>

    این قابلیت به صورت پیش فرض باعث افزایش امنیت می شود.

ماژول های “bare” غیر مجاز هستند.

در مرورگر، import باید یک لینک رلتیو یا ابسولوت دریافت کند. ماژول هایی که هیچونه آدرسی یا مسیری ندارند را “bare” یا برهنه می نامیم. چنین ماژول هایی در ‍import مجاز نیستند.

برای مثال، import زیر مجاز نیست:

import {sayHi} from 'sayHi'; // Error, "bare" module
// ماژول باید یک مسیر داشته باشد، برای مثال ‍'./sayHi.js' یا هر ماژولی که هست.

بعضی محیط ها مانند Node.js یا ابزارهای bundle اجازه استفاده از ماژول های برهنه را می دهند، بدون هیچ مسیری ، به این دلیل که این محیط ها روش های دیگری برای پیدا کردن ماژول ها و هوک ها و تنظیم آن ها دارند. اما مرورگر ها در حال حاضر از ماژول های برهنه پشتیبانی نمی کنند.

سازگاری، “nomodule”

مرورگرهای قدیمی منظور را از type="module" نمی فهمند. اسکریپت هایی از نوع ناشناخته نادیده گرفته می شوند. برای این موارد این امکان وجود دارد که یک حالت استثنا به وسیله nomodule تعریف کنید:

<script type="module">
  alert("اجرا در مرورگرهای مدرن");
</script>

<script nomodule>
  alert("مرورگرهای مدرن هر دو مورد type=modeule و nomodule را می فهمند، پس از این مورد در می شوند.")
  alert("مرورگرهای قدیمی اسکریپت از نوع ناشناخته را نادیده می گیرند type=module اما این مورد را اجرا می کنند.");
</script>

ابزارهای ساخت

در زندگی واقعی، ماژول های مرورگر به ندرت در حالت “خام” خود استفاده می شوند. معمولا، ما این اسکریپت ها را با ابزارهایی مانند Webpack با هم استفاده می کنیم و در سرور نهایی اعمال می کنیم.

یکی از مزایای استفاده از باندلرها – اینها به ما کنترل بیشتر بر روی اینکه ماژول ها چگونه اجرا می شوند، می دهد، اجازه اجرا شدن ماژول های برهنه و بسیار کارهای دیگر، مانند ماژول های CSS/HTML.

ابزارهای ساخت کارهای زیر را انجام می دهند:

  1. ماژول “اصلی”، همان ماژولی که قرار است توی <script type="module"> در HTML قرار بگیرد را بردار.
  2. وابستگی های آن را بررسی کن: importهای آن و سپس importهای importهای آن و تا به آخر.
  3. یک فایل با تمام ماژول ها بساز(یا چند فایل، این مورد قابل تنظیم است)، جایگزینی ‍import های صدا زده شده با توابع باندلر، تا این کار شدنی باشد. ماژول های “خاص” مانند ماژول های HTML/CSS هم پشتیبانی می شوند.
  4. در حین عملیات، تبدیل ها و ارتقاهای دیگری هم ممکن است انجام شود:
    • کدهایی که هیچ وقت اجرا نمی شوند، حذف می شوند.
    • exportهایی که استفاده نمی شوند، پاک می شوند.(“tree-shaking”).
    • عباراتی که مخصوص زمان توسعه نرم افزار هستند مانند console و debugger حذف می شوند.
    • سینتکس و املای مدرن جاوااسکریپت ممکن است به نمونه های قدیمی با عملکرد مشابه توسط Babel تبدیل شوند.
    • فایل نهایی فشرده می شود. (فاصله های پاک می شوند، متغیرها با نام های کوتاه تر جایگزین می شوند و غیره)

اگر ما از ابزارهای باندل استفاده کنیم، در این صورت تمام اسکریپت ها با هم در یک فایل ( یا تعداد کمی فایل ) جمع می شوند، عبارات import/export داخل اسکریپت ها با توابع خاص باندلر ها جایگزین می شوند. در نتیجه اسکریپت باندل نهایی هیچ عبارت import/export ندارد، این اسکریپت نیازی به type="module" ندارد، و ما می توانیم آن را در یک اسکریپت معمولی بگذاریم.

<!-- با فرض اینکه ما bundle.js را از یک ابزار مانند Webpack گرفته ایم -->
<script src="bundle.js"></script>

با این حساب، ماژول ها بومی و نیتیو هم قابل استفاده هستند. در نتیجه ما از Webpack در اینجا استفاده نمی کنیم: شما می توانید آن را در آینده تنظیم کنید.

خلاصه

برای خلاصه کردن، مفاهیم اصلی اینها هستند:

  1. هر ماژول یک فایل است. برای اینکه عبارات import/export کار بکنند، مرورگرها نیاز به <script type="module"> دارند. ماژول های چندین تفاوت با اسکریپت های معمولی دارند:
    • به صورت پیش فرض به تعویق افتاده (Deferred) هستند.
    • در اسکریپت های inline Async جواب می دهد.
    • برای بارگزاری اسکریپت های خارجی(external) از منابع دیگر (دامنه/پروتکل/پورت)، هدر های CORS نیاز هستند.
    • اسکریپت های مشابه external نادیده گرفته می شوند.
  2. ماژول های اسکوپ سطح بالای خود را دارند و از طریق عبارات ‍import/export کارایی های خود را با دیگر اسکریپت های به اشتراک می گذارند.
  3. ماژول ها همیشه در حالت ‍use strict هستند.
  4. کد ماژول ها تنها یک مرتبه اجرا می شوند. Exportها تنها یک مرتبه ساخته شده و سپس بین تمام importer ها به اشتراک گذاشته می شوند.

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

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

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

نقشه آموزش

نظرات

قبل از نظر دادن این را بخوانید…
  • اگر پیشنهادی برای بهبود ترجمه دارید - لطفا یک ایشوی گیت‌هاب یا یک پول‌ریکوئست به جای کامنت‌گذاشتن باز کنید.
  • اگر چیزی را در مقاله متوجه نمی‌شوید – به دقت توضیح دهید.
  • برای قراردادن یک خط از کد، از تگ <code> استفاده کنید، برای چندین خط – کد را درون تگ <pre> قرار دهید، برای بیش از ده خط کد – از یک جعبهٔ شنی استفاده کنید. (plnkr، jsbin، codepen…)