آشنایی با تغییرات ساختار ایمپورت و اکسپورت در ES6 — راهنمای جامع
در این مقاله تلاش کردهایم در مورد تغییرهای ساختار ایمپورت و اکسپورت در ES6 بررسی جامعی به عمل آوریم. تا پیش از ES6 با چندین تگ اسکریپت در یک فایل HTML منفرد مواجه بودیم که فایلهای جاوا اسکریپت مختلفی را ایمپورت میکردند:
1<script type="text/javascript" src="home.js"></script>
2<script type="text/javascript" src="profile.js"></script>
3<script type="text/javascript" src="user.js"></script>
بنابراین در صورتی که متغیری با نام یکسان در فایلهای جاوا اسکریپت مختلف داشته باشیم، با تعارض نامها مواجه میشویم و مقداری که مورد انتظار ما است با مقداری که متغیر میگیرد، متفاوت خواهد بود. ES6 این مشکل را با معرفی مفهوم ماژولها کرده است.
هر فایل جاوا اسکریپت که مینویسیم به عنوان یک ماژول شناخته میشود و متغیرها و تابعهایی که در هر فایل تعریف میشوند تا زمانی که به صورت خاص به فایل دیگری اکسپورت نشده باشد و در آن فایل نیز ایمپورت نشده باشد، در اختیار آن قرار نمیگیرد.
بنابراین تابعها و متغیرهای تعریفشده در هر فایل، برای آن فایل خصوصی هستند و نمیتوانند از خارج از فایل مورد دسترسی قرار گیرند، مگر این که آنها را اکسپورت کنیم. دو روش برای اکسپورت کردن وجود دارد:
- اکسپورت نامدار (Named Exports): در یک فایل منفرد میتوان چندین اکسپورت نامدار داشت.
- اکسپورت پیشفرض (Default Exports): در هر فایل منفرد، تنها یک اکسپورت پیشفرض میتواند وجود داشته بشد.
اکسپورتهای نامدار
برای اکسپورت کردن یک مقدار منفرد به صورت اکسپورت نامدار باید به صورت زیر عمل کنیم:
1export const temp = "This is some dummy text";
همچنین میتوانیم گزاره را به جای این که در جلوی اعلام متغیر اکسپورت کنیم، این کار را روی خط متفاوتی انجام دهیم و چیزهایی که باید اکسپورت شوند را داخل آکولاد تعیین کنیم:
1const temp1 = "This is some dummy text1";
2const temp2 = "This is some dummy text2";
3export { temp1, temp2 };
توجه کنید که ساختار اکسپورت یک ساختار لفظی شیء نیست. از این رو در ES6 برای اکسپورت یک چیز نمیتوانیم جفت کلید-مقداری مانند زیر استفاده کنیم:
1// This is invalid syntax of export in ES6
2export { key1: value1, key2: value2 }
برای ایمپورت کردن موارد اکسپورت شده به صورت نامدار باید از ساختار زیر استفاده کنیم:
1import { temp1, temp2 } from './filename';
توجه داشته باشید که وقتی چیزی را از فایل ایمپورت میکنیم، نیازی به اضافه کردن پسوند.js به آن نداریم، چون به صورت پیشفرض چنین تلقی میشود:
1// import from functions.js file from current directory
2import { temp1, temp2 } from './functions';
3// import from functions.js file from parent of current directory
4import { temp1 } from '../functions';
نکته مهم: نامی که در زمان اکسپورت کردن استفاده میشود، باید با نام زمان ایمپورت هماهنگ باشد. بنابراین اگر اکسپورت به صورت زیر باشد:
1// constants.js
2export const PI = 3.14159;
در زمان ایمپورت باید از کد زیر استفاده کنیم:
1import { PI } from './constants';
ما نمیتوانیم از هیچ نام دیگری مانند زیر استفاده کنیم:
1import { PiValue } from './constants'; // This will throw an error
اما اگر از قبل متغیری داشته باشیم که از همان نام اکسپورت شده استفاده میکند، میتوانیم در زمان ایمپورت کردن، نام ساختار را تغییر دهیم:
1import { PI as PIValue } from './constants';
در کد فوق مقدار PI را به PIValue تغییر دادیم، چون نمیتوانیم از نام متغیر PI استفاده کنیم. بنابراین برای دریافت مقدار اکسپورت شده PI باید نام آن را به PIValue عوض کنیم. همچنین میتوانیم از تغییر نام ساختار در زمان اکسپورت کردن استفاده کنیم:
1// constants.js
2const PI = 3.14159;
3export { PI as PIValue };
سپس در زمان ایمپورت کردن باید به صورت زیر از PIValue استفاده کنیم:
1import { PIValue } from './constants';
برای اکسپورت چیزی به صورت اکسپورت نامدار، باید ابتدا آن را اعلان کنیم:
1export 'hello'; // this will result in error
2export const greeting = 'hello'; // this will work
3export { name: 'David' }; // This will result in error
4export const object = { name: 'David' }; // This will work
نکته: ترتیب ایمپورت کردن چندین اکسپورت نامدار اهمیتی ندارد.
فرض کنید یک کامپوننت به نام validations.js به صورت زیر داریم و تابع اعتبارسنجی را در خط آخر آن اکسپورت میکنیم:
1const isValidEmail = function(email) {
2 if (/^[^@ ]+@[^@ ]+\.[^@ \.]{2,}$/.test(email)) {
3 return "email is valid";
4 } else {
5 return "email is invalid";
6 }
7};
8
9const isValidPhone = function(phone) {
10 if (/^[\\(]\d{3}[\\)]\s\d{3}-\d{4}$/.test(phone)) {
11 return "phone number is valid";
12 } else {
13 return "phone number is invalid";
14 }
15};
16
17function isEmpty(value) {
18 if (/^\s*$/.test(value)) {
19 return "string is empty or contains only spaces";
20 } else {
21 return "string is not empty and does not contain spaces";
22 }
23}
24
25export { isValidEmail, isValidPhone, isEmpty };
سپس در فایل دیگری مانند index.js تابعهای اعتبارسنجی را به صورت زیر ایمپورت میکنیم:
1import React from "react";
2import ReactDOM from "react-dom";
3import { isEmpty, isValidEmail } from "./components/validations";
4
5console.log("isEmpty:", isEmpty("abcd"));
6console.log("isValidEmail:", isValidEmail("abc@11gmail.com"));
7
8const template = (
9 <div>
10 <h1>ES6 Import Export Demo</h1>
11 <h4>Open Console to see the output</h4>
12 </div>
13);
14const rootElement = document.getElementById("root");
15ReactDOM.render(template, rootElement);
چنان که میبینید، میتوانیم تنها موارد اکسپورت شده مورد نیاز را ایمپورت کنیم و این کار با هر ترتیب دلخواه قابل اجرا است. از این رو لازم نیست ترتیب اکسپورت آنها را در فایل دیگر بررسی کنیم. این زیبایی اکسپورتهای نامدار است.
اکسپورت پیشفرض
چنان که پیشتر گفتیم، در هر فایل، حداکثر یک اکسپورت پیشفرض میتواند وجود داشته باشد. در مجموع امکان داشتن چندین اکسپورت نامدار و یک اکسپورت پیشفرض در هر فایل منفرد وجود دارد.
برای اعلان یک اکسپورت پیشفرض باید کلیدواژه default را در جلوی کلیدواژه export مانند زیر بیاوریم:
1//constants.js
2const name = 'David';
3export default name;
برای ایمپورت اکسپورت پیشفرض لازم نیست آکولادها را مانند آنچه در مورد اکسپورت نامدار انجام میدادیم، بیاوریم:
1import name from './constants';
اگر چندین اکسپورت نامدار و یک اکسپورت پیشفرض مانند زیر داشته باشیم:
1// constants.js
2export const PI = 3.14159;
3export const AGE = 30;
4const NAME = "David";
5export default NAME;
برای ایمپورت کردن همه آنها در یک خط منفرد از متغیر اکسپورت پیشفرض پیش از آکولاد استفاده میکنیم:
1// NAME is default export and PI and AGE are named exports here
2import NAME, { PI, AGE } from './constants';
یک خصوصیت اکسپورت پیشفرض این است که میتوانیم نام متغیر اکسپورت شده را در زمان ایمپورت کردن عوض کنیم:
1// constants.js
2const AGE = 30;
3export default AGE;
همچنین در فایل دیگر میتوانیم از نام دیگری در زمان ایمپورت کردن استفاده کنیم:
1import myAge from ‘./constants’;
2console.log(myAge); // 30
بدین ترتیب در کد فوق نام متغیر اکسپورت پیشفرض را از AGE به myAge عوض کردهایم. دلیل عملی بودن این کار آن است که تنها یک اکسپورت پیشفرض میتواند وجود داشته باشد و از این رو نام آن میتواند هر چیزی که میخواهیم باشد.
نکته: کلیدواژه اکسپورت پیشفرض (export default) نمیتواند مانند کد زیر پیش از اعلان متغیر بیاید:
1// constants.js
2export default const AGE = 30; // This is an error and will not work
بنابراین باید از کلیدواژه export default در خط متمایزی استفاده کنیم:
1// constants.js
2const AGE = 30;
3export default AGE;
با این حال میتوانیم export default را بدون اعلان متغیر به صورت زیر داشته باشیم:
1//constants.js
2export default {
3name: "Billy",
4age: 40
5};
و در فایل دیگر به صورت زیر عمل میکنیم:
1import user from './constants';
2console.log(user.name); // Billy
3console.log(user.age); // 40
روش دیگری برای ایمپورت کردن همه متغیرهای اکسپورت شده در فایل با استفاده از ساختار زیر وجود دارد:
1import * as constants from './constants';
در این کد همه اکسپورتهای نامدار و پیشفرض را در فایل constants.js داریم و در متغیر constants ذخیره میکنیم. بنابراین constants اینک به یک شیء تبدیل شده است:
1// constants.js
2export const USERNAME = "David";
3export default {
4name: "Billy",
5age: 40
6};
در فایل دیگر از آن به صورت زیر استفاده میکنیم:
1// test.js
2import * as constants from './constants';
3console.log(constants.USERNAME); // David
4console.log(constants.default); // { name: "Billy", age: 40 }
5console.log(constants.default.age); // 40
اگر نخواهید اکسپورتهای پیشفرض و نامدار را در خطوط متفاوتی داشته باشید، میتوانید آنها را به صورت زیر ترکیب کنید:
1// constants.js
2const PI = 3.14159;
3const AGE = 30;
4const USERNAME = "David";
5const USER = {
6name: "Billy",
7age: 40
8};
9export { PI, AGE, USERNAME, USER as default };
در کد فوق USER را به صورت اکسپورت پیشفرض و بقیه را به صورت اکسپورت نامدار میبینیم. در فایل دیگر نیز به صورت زیر از آن استفاده میکنیم:
1import USER, { PI, AGE, USERNAME } from "./constants";
سخن پایانی
در ES6 دادههایی که در یک فایل اعلان میشوند، در فایل دیگر قابل دسترسی نیستند، مگر این که از فایل اول اکسپورت شده و در فایل دوم ایمپورت شوند.
اگر مورد منفردی مانند اعلان یک کلاس در یک فایل باشد که بخواهیم اکسپورت شود از اکسپورت پیشفرض استفاده میکنیم، در غیر این صورت از اکسپورت نامدار بهره میگیریم. امکان استفاده ترکیبی از اکسپورت پیشفرض و اکسپورت نامدار نیز در یک فایل منفرد وجود دارد.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای برنامهنویسی
- آموزش JavaScript ES6 (جاوااسکریپت)
- مجموعه آموزشهای JavaScript (جاوا اسکریپت)
- حذف موارد تکراری از آرایه های جاوا اسکریپت (ES6) — به زبان ساده
- آشنایی با دوازده قابلیت ES10 با دوازده مثال — راهنمای کاربردی
==