مروری بر ویژگی‌های ES6: مفاهیم import و export و کلاس‌ها

Overview of ES6 Features: Import and Export Concepts and Classes

23 بهمن 1399
مروری بر ویژگی های ES6: مفاهیم import و export و کلاس ها

مفاهیم Import و Export در ری اکت

در ادامه بررسی ویژگی های جدید ES6 به مبحث Import و Export در ری اکت می رسیم. ES6 به شما اجازه می دهد که کدهای ماژولار بنویسید؛ یعنی کدهایتان را در چندین فایل مختلف نگهداری کنید. شاید با خودتان بگویید در حال حاضر هم می توانیم کدهای جاوا اسکریپت خود را در چند فایل مختلف قرار دهیم و فقط کافی است که با ترتیب صحیح آن ها را در فایل HTML وارد کنیم.

باید بگویم بحث import و export متفاوت است؛ در نوشتن کدهای ماژولار با این دستورات هدف این است که در خود فایل های جاوا اسکریپت از قسمتی از یک فایل جاوا اسکریپت دیگر استفاده کنیم تا خود فایل های جاوا اسکریپت وابستگی های خود را بدانند.

به طور مثال فرض کنید که یک فایل به نام person.js داشته باشیم که دارای یک شیء به نام person باشد:

const person = {
  mame: 'Amir'
}

export default person;

این کد شیء ما را export می کند تا بعدا آن را در فایلی import کنیم. کلیدواژه Default یعنی خروجی پیش فرض این فایل person است.

مثال دیگری هم داریم. مثلا فایلی به نام utility.js داشته باشیم که در آن چندین چیز را export کنیم:

export const clean = () => {...}
export const baseData = 10;

حالا فایلی به نام app.js داریم که می خواهیم این دو فایل را در آن import کنیم بنابراین می گوییم:

import person from './person.js'
import prs from './person.js'

import {baseData} from './utility.js'
import {clean} from './utility.js'

توضیح این کد:

از آنجا که در فایل person.js برای export کردن شیء person از کلیدواژه default استفاده کرده ایم در هنگام import فقط همان شیء person برای ما import می شود نه هیچ کد دیگری. بنابراین می توانیم هر اسمی که خواستیم برایش تعیین کنیم. در کد بالا من این شیء را دو بار و هر بار با نام های مختلف (person و prs) وارد (import) کرده ام؛ هر دو کد دقیقا یک کار را انجام می دهند. در این حالت تنها نام import شده به دست شما است و دیگر نمی توانید بگوییم به غیر از شیء person چیز دیگری را import کند.

اما از آنجا که برای utility.js از default استفاده نکردیم باید مشخص کنیم که چه قسمتی را می خواهیم import کنیم. همانطور که می بینید در کد بالا با استفاده از curly braces توانسته ایم نام تابع و نام ثابت خود را مشخص کنیم تا import شوند. به این موارد named export می گوییم چرا که بر اساس نام import یا export می کند.

نکته: شما می توانید کد دوم را به صورت یک دستور بنویسید و مقادیر baseData و clean را با استفاده از کاما (ویرگول انگلیسی) جدا کنید.

البته اگر شما دوست دارید مانند حالت default از نام دلخواه خودتان برای import کردن named export ها استفاده کنید می توانید یک alias برای آن تعیین کنید. مثال:

import {clean as myFavoriteName} from './utility.js'

در اینجا با استفاده از کلیدواژه As یک alias (نام مستعار) برای مقدار import شده تعیین کرده ایم تا بعدا در کدهایمان به صورت دلخواه از آن استفاده کنیم.

همچنین اگر چندین مقدار در فایلی دارید که می خواهید همه را با هم وارد کنید می توانید از حالت زیر استفاده کنید:

import * as bundled from './utility.js'

در این حالت bundled (که نام دلخواه ما بوده است) یک شیء جاوا اسکریپت خواهد بود که حاوی تمام const ها و اطلاعات دیگری است که از طرف فایل مبدا export شده باشند. بنابراین می توانید به این صورت به آن ها دسترسی داشته باشید:

bundled.clean
bundled.baseData

متاسفانه برخی از این ویژگی های جدید ES6 در مدرن ترین مرورگرها هم پشتیبانی نمی شوند. بنابراین باید با استفاده از یک ابزار خاص (که در جلسات بعدی و پس از اتمام بررسی ES6 توضیح داده می شود) این کدها را تبدیل به کدهای قدیمی کنیم تا در مرورگر اجرا شود.

سوال: چرا از ES6 استفاده می کنیم در حالی که در مرورگرها پشتیبانی نمی شود؟

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

مفهوم class

یکی دیگر از ویژگی های جدید ES6 کلاس ها هستند. اگر دوره PHP شیء گرای ما را گذرانده باشید می دانید که کلاس ها به زبان ساده نقشه کلی برای اشیاء هستند و شکل شماتیک آنها بدین صورت است:

class Person {
  name = 'Amir'
  call = () => {...}
}

توجه: این syntax صحیح جاوا اسکریپت نیست! و تنها برای درک ساده تر مفاهیم خصوصیت و متد به این شکل خلاصه نوشته شده است.

کلاس ها می توانند property (خصوصیت) داشته باشند مانند name که برابر با Amir است. همچنین می توانند method داشته باشند که تابعی مثل call خواهد بود. به زبان ساده property ها متغیر هایی هستند که به کلاس تعلق دارند در حالی که method ها توابعی هستند که متعلق به کلاس می باشند.

برای ساخت یک شیء از یک کلاس (نمونه سازی) می توانیم بدین صورت عمل کنیم:

const myPerson = new Person()

در این حالت می توانیم به شکل زیر به خصوصیات یا متدهای کلاس دسترسی داشته باشیم:

myPerson.call()
console.log(myPerson.name)

در کلاس ها مبحث وراثت (inheritance) را نیز داریم. یعنی یک کلاس می تواند خصوصیات و متدها (کدهای) یک کلاس دیگر را به ارث ببرد (از آن ها استفاده کند) بدون اینکه بخواهیم کدها را دوباره تکرار کنیم:

class Person extends Master

به شما پیشنهاد می دهم به دوره آموزشی شیء گرایی PHP نگاهی بیندازید. با اینکه syntax در زبان PHP ممکن است متفاوت باشد اما مفاهیم همگی یکی هستند و به این صورت می توانید درک عمیق تری از مبحث کلاس ها به دست بیاورید.

بگذارید یک مثال عملی از این بحث را ببینیم!

نحوه صحیح نوشتن property ها در جاوا اسکریپت به این شکل است که آن را در یک تابع از پیش تعریف شده به نام constructor بدهید. متدها نیز تنها با نام متد و مانند توابع عادی نوشته می شوند. به مثال زیر دقت کنید:

class Person {
  constructor(){
    this.name = 'Amir';
  }
  
  printMyName () {
    console.log(this.name);
  }
}

در کلاس Person ابتدا یک خصوصیت به نام name تعریف کرده ایم. همانطور که گفته شد برای تعریف خصوصیت ها باید از یک تابع constructor به همراه کلیدواژه this استفاده کنید. سپس متدی به نام printMyName تعریف کرده ایم که name را نمایش می دهد. this.name یعنی همین name ای که در همین کلاس تعریف شده است.

حالا می توانید یک نمونه (شیء) از این کلاس بسازیم:

class Person {
  constructor() {
    this.name = 'Amir';
  }
  
  printMyName() {
    console.log(this.name);
  }
}

const person = new Person();
person.printMyName();

با اجرای این دستور خروجی Amir نمایش داده می شود.

حالا برای مبحث وراثت می توانیم کلاس دیگری به این شکل تعریف کنیم:

class Human {
  constructor (){
    this.gender = 'male';
  }
  
  printGender() {
    console.log(this.gender);
  }
}

حالا اگر کلاس Person کلاس Human را extend کند (یعنی بسط و گسترش دهد – همان وراثت) می تواند از خصوصیات و متدهای Human نیز استفاده کند!

class Person extends Human {
  constructor() {
    this.name = 'Amir';
  }
  
  printMyName() {
    console.log(this.name);
  }
}

gender در انگلیسی به معنای جنسیت (مذکر یا مونث) است.

حالا اگر کد زیر را بنویسیم چه می شود؟

person.printGender();

به خطا برمیخوریم! در جاوا اسکریپت اگر کلاسی دارید که کلاس دیگری را extend می کند و از constructor هم استفاده می کند (الزامی به استفاده از constructor نیست، اگر نیاز به آن داشتید) باید از متد خاصی به نام ()super در constructor کلاس خود استفاده کنید. بنابراین برای کلاس Person می گوییم:

class Person extends Human {
  constructor() {
    super();
    this.name = 'Amir';
  }
  
  printMyName() {
    console.log(this.name);
  }
}

حالا می توانیم دستور زیر را اجرا کنیم:

person.printGender();

خروجی عبارت male (به معنی مذکر) خواهد بود.

مشاهده این کد به صورت کامل در JSBin

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

شما می توانید به کلاس خود رفته و مقدار gender را نیز تغییر بدهید!

class Person extends Human {
  constructor() {
    super();
    this.name = 'Amir';
    this.gender = 'female';
  }
  
  printMyName() {
    console.log(this.name);
  }
}

اگر از این کلاس خروجی بگیریم مقدار Female نمایش داده می شود. بنابراین می توانید این خصوصیات را در کلاس فرزند تغییر دهید.

امیدوارم از این قسمت لذت برده باشید.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری دوره جامع آموزش ری اکت توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما (5 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

علی
18 شهریور 1400
سلام واقعا فوق العاده و صادقانه نوشتین دمتون گرم برعکس برنامه نویسایی که مخصوصا میخوان گمراه کنن که کسی برنامه نویس نشه دستتون درد نکنه خدا با شماست

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

محمد مهدی عابدینی
03 شهریور 1400
اقا دمت گرم خیلی باحالی عالی توضیح دادی خدا پدر و مادرتو بیامرزه بازم دمت گرم

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

a_bahoush
02 فروردین 1399
سلام ببخشید اشتباه از من بود

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

a_bahoush
02 فروردین 1399
سلام در همین صفحه یعنی درس سوم دوره جامع ری اکت گفتید:نحوه ی صحیح نوشتن property ها در جاوا اسکریپت به این شکل است:یتیتگشنزنوزگز چجح چجح چجخچطجحچر چج حچج حچجطحظچجج ................. درحالی که درستش این هست: در کلاس Person ابتدا یک خصوصیت به نام name تعریف کرده ایم. همانطور که گفته شد برای تعریف خصوصیت ها باید از یک تابع constructor به همراه کلیدواژه ی this استفاده کنید. سپس متدی به نام printMyName تعریف کرده ایم که name را نمایش می دهد. this.name یعنی همین name ای که در همین کلاس تعریف شده است.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

امیر خ
24 اسفند 1398
سلام استاد من دیونه شدم... اول امدم کلی سلول خاکستری سوزوندم که بحث extend رو بفهمم -بعد توی مثال اخر برای این که بتونیم مقدار gender رو تغیر بدیم ، دوباره امدین نوشتیم this.gender -یعنی در واقع دوباره تعریفش کردیم... خو اگر قراره برای اینکه بتونیم مقدارش رو تغیر بدیم ،دوباره تعریفش کنیم -خو برای چی بیاییم الکی بحث extend یاد بگیریم... . توی مثال اخر شما امدی نوشتی extends Human و بعدش دوباره this.gender رو تعریف کردین ... خو وقتی در تابع خودمون تعریفش کردیم ، چ نیازیه از هومن ارث گیری کنیم؟؟؟ . میدونم اساس بحث extend برای زمان هایی که مقدار متغیر تغیر نکنه... و ی سوال دیگه استاد -راه ساده تری نیست که بتونیم بدون تعریف دوباره مقدارش رو تغیر بدیم... ؟

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

امیر زوارمی
26 اسفند 1398
سلام دوست عزیز بحث extend که به هر حال برای ارث بری هست و مشکلی نیست. من فقط خواستم توی اون مثال به شما نشون بدم که کلاس فرزند میتونه کلاس پدر رو override کنه (باطل کنه و مقدار جدیدی برش بزاره)، همین. برخی اوقات توی بعضی از شرایط نیاز هست که کلاس فرزند، مقداری در کلاس پدر رو تغییر بده (که البته حالت های کمی پیش میاد که اینطوری بشه). این مثال به درد اونجا می خوره. البته در حالت عادی چنین کاری نمی کنیم. در ضمن قضیه «تعریف دوباره» نیست. کلا عوض کردن مقدار یک خصوصیت در برنامه نویسی شیء گرا به همین شکل هست و راه دیگه ای نداره. حتی توی زبان php هم به همین شکل کار می کنیم.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.