قبل از شروع رسمی سری react باید چند نکته بسیار مهم از جاوا اسکریپت را به شما یادآوری کنم. این نکات مربوط به ویژگی های جدید ES6 نیستند اما موارد جزئی هستند که بسیاری از برنامه نویسان از آن ها عبور می کنند و یا در طولانی مدت فراموش می شوند.
مسئله اول بحث reference type و primitive type است. بگذارید در قالب یک مثال توضیح دهم. اگر در جاوا اسکریپت یک عدد ایجاد کنم:
const number = 1;
این متغیر از نوع primitive (به معنی «ابتدایی») است. یعنی اگر یک متغیر جدید ایجاد کنم و مقدار number را به آن بدهم:
const num2 = number;
یک کپی واقعی از number ساخته می شود و درون num2 قرار داده می شود. یعنی مقدار 1 واقعا کپی می شود و نسخه کپی شده درون num2 قرار میگیرد بنابراین از مقدار number مستقل است.
const number = 1; const num2 = number; console.log(num2);
همانطور که همه می دانیم خروجی این کد عدد 1 خواهد بود اما توجه داشته باشید که عدد 1 کپی شده و درون num2 قرار گرفته است. متغیرهای عددی، رشته ای و Boolean همگی از نوع primitive هستند. هر زمان که آن ها را re-assign کرده یا آن ها را درون متغیر دیگری قرار دهید (مانند مثال بالا)، مقدار واقعا کپی می شود.
اما اشیاء و آرایه ها از نوع refrence (به معنی «ارجاعی») هستند؛ اگر یک شیء به نام Person ایجاد کنم:
const Person = { name: 'Amir' }
سپس یک متغیر دیگر به نام secondPerson ایجاد کنم و مقدارش را برابر با Person قرار دهم و سپس از آن خروجی بگیرم:
const Person = { name: 'Amir' } const secondPerson = Person; console.log(secondPerson);
با اینکه خروجی این دستور همان Person (با نام Amir) است اما مقدار Person درون secondPerson کپی نشده است بلکه به آن ارجاع داده شده است! یعنی شیء Person (فقط curly braces ها و محتوای درونشان، نه خود متغیر Person) در مموری ذخیره شده است و سپس ثابت Person (متغیر Person) یک pointer به آن شیء ذخیره می کند (یعنی فقط به آن اشاره می کند).
شیء مورد نظر ما:
{ name: 'Amir' }
ثابتی که شیء در آن قرار گرفته است:
const Person
بنابراین زمانی که می گوییم:
const secondPerson = Person;
فقط همان pointer است که کپی می شود نه مقدار واقعی شیء!
به طور مثال بعد از کپی شدن اگر name را تغییر دهیم:
const Person = { name: 'Amir' } const secondPerson = Person; Person.name = 'Mahdi'; console.log(secondPerson);
خروجی این دستور نام Mahdi خواهد بود نه Amir! ما انتظار داریم که همان مقدار Amir نمایش داده شود چرا که مقدار Person را درون secondPerson گذاشته ایم و سپس از همان secondPerson خروجی گرفته ایم. مقداری که تغییر کرده مقدار Person است و اگر مقدار واقعا کپی شده باشد نباید secondPerson تغییری بکند.
بنابراین با تغییر Person مقدار secondPerson نیز تغییر کرد. چرا؟ به این دلیل که مقدار واقعی اصلا کپی نشده بود بلکه pointer ای که به مقدار واقعی اشاره می کرد کپی شده بود. با تغییر مقدار، pointer تغییری نمی کند و به همان مکان قبلی اشاره میکند. این مسئله برای آرایه ها نیز به همین شکل است.
ما می دانیم که برای مقادیر primitive اصلا چنین بحثی مطرح نبود و مقدار واقعا کپی می شد بنابراین با تغییر مقدار آن ها مقادیر دیگر تغییر پیدا نمیکرد.
درک تفاوت مقادیر primitive و reference در کار با React بسیار مهم است چرا که اگر اشیاء را به این شکل کپی کنیم باعث بروز مشکلات متعددی در برنامه خود می شویم. به طور مثال یک شیء را در هنگام کار با react تغییر میدهیم و متوجه می شویم مقدار آن در چند جای دیگر نیز تغییر کرده است و برنامه ما بهم می ریزد! بنابراین برای جلوگیری از این مسئله باید مقادیر را به شکل immutable کپی کنیم (یعنی خود شیء یا مقدار واقعی را واقعا کپی کنیم).
برای این کار از اپراتور spread کمک میگیریم و می گوییم:
const Person = { name: 'Amir' } const secondPerson = { ...Person }; Person.name = 'Mahdi'; console.log(secondPerson);
حالا خروجی این دستور همان مقدار Amir خواهد بود. در واقع با استفاده از اپراتور spread خصوصیات شیء Person را استخراج می کنیم و سپس با استفاده از curly braces (علامت های {}) یک شیء جدید می سازیم و این خصوصیات را درون آن قرار می دهیم:
const secondPerson = { ...Person };
توجه داشته باشید که curly braces ها شیء جدید می سازند.
بنابراین به دلیل اینکه خصوصیات Person واقعا در شیء جدیدی کپی شده است بنابراین با اینکه name را تغییر داده ایم مقدار secondPerson تغییری نمیکند.
مسئله دیگری که در طول دوره زیاد از آن استفاده می کنیم توابع کار با آرایه ها هستند. توابع خاصی وجود دارند که کارشان اجرای یک تابع روی تک تک اعضای یک آرایه است. در طول دوره زمانی که به هر کدام از این توابع می رسیم نحوه کار آن ها را توضیح خواهم داد اما فعلا یک مثال از تابع map برای شما می زنم تا ذهن شما با این دسته از توابع آشنا شود:
ابتدا یک آرایه تعریف می کنم:
const numbers = [1, 2, 3];
سپس با استفاده از map که تابعی را روی تک تک اعضا اجرا می کند اعضای این آرایه را دو برابر می کنم:
const doubleNumArray = numbers.map((num) => { return num * 2; })
اینجا از Arrow function ها استفاده کرده ایم اما شما می توانید از یک تابع عادی نیز استفاده کنید. همچنین همانطور که میدانید آرگومان این تابع (یعنی num) می تواند هر نامی که شما می خواهید داشته باشد. نکته مهم اینجاست که map یک تابع واقعی و جدید برمی گرداند بنابراین اگر بگویم:
const numbers = [1, 2, 3]; const doubleNumArray = numbers.map((num) => { return num * 2; }) console.log(numbers); console.log(doubleNumArray);
خروجی به شکل زیر خواهد بود:
[1, 2, 3] [2, 4, 6]
یعنی مقدار آرایه اصلی تغییر نکرده است.
برخی از این توابع را به همراه documentation آن ها برایتان آورده ام. در صورتی که علاقه دارید می توانید آن ها را مطالعه کنید.
همچنین برای جمع بندی، خلاصه ای از دروس ES6 را برایتان جمع آوری کرده ام => لینک دانلود
امیدوارم از این قسمت لذت برده باشید. از قسمت بعدی وارد یادگیری react خواهیم شد. در ابتدا به شما آموزش می دهم که چطور محیط کاری و کدنویسی برای react را آماده کنید و سپس وارد بحث های ابتدایی آن مانند syntax خواهیم شد.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.