با قسمتی دیگر از مرور ویژگی های جدید ES6 در خدمت شما هستیم. در این قسمت اپراتورهای spread (به معنی «گسترش دادن» یا «پهن کردن») و rest (به معنی «استراحت کردن) را بررسی می کنیم که هر دو یک شکل دارند: علامت سه نقطه «...»!
بله شکل این اپراتورها کمی عجیب است و بسته به نحوه استفاده از آن نام های spread یا rest را می گیرد. زمانی که spread را مد نظر داشته باشیم یعنی می خواهیم اعضای یک آرایه یا خصوصیات یک شیء را از هم جدا کنیم. مثلا فرض کنید یک آرایه قدیمی داشته باشیم و بخواهیم اعضای این آرایه قدیمی را به یک آرایه دیگر منتقل کنیم و چند عضو دیگر نیز به آرایه جدید اضافه کنیم می توانیم بگوییم:
const newArray = […oldArray, 1, 2]
این سه نقطه تمام اعضای آرایه oldArray را از هم جدا کرده و به عنوان اعضای جدید داخل آرایه newArray می ریزد.
اگر بخواهیم این کار را برای خصوصیات (propery) یک شیء انجام دهیم می گوییم:
const newObject = {…oldObject, newProp: 5}
اپراتور rest زمانی است که از علامت سه نقطه برای جمع کردن آرگومان های یک تابع در یک آرایه استفاده کنیم! شاید در ابتدا کمی گیج کننده باشد. فرض کنید یک تابع داریم و نمی دانیم چه تعداد آرگومانی قرار است بگیرد. در این صورت می نویسیم:
function sortArgs (…args) { return args.sort(); }
حالا هر تعداد آرگومانی که به این تابع بدهیم توسط اپراتور rest جمع شده و در یک آرایه قرار می گیرد. وقت مثال عملی است!
برای اپراتور spread می توان گفت:
const numbers = [1, 2, 3]; const newNumbers = [...numbers, 4]; console.log(newNumbers);
به نظر شما خروجی این کد چیست؟ بله خروجی این کد [1, 2, 3, 4] است.
سوال: اگر بدون استفاده از اپراتور spread خود آرایه (numbers) را درون آرایه جدید بگذاریم چه می شود؟
پاسخ: آرایه جدید تبدیل به یک آرایه دو بعدی می شود. یعنی خروجی به این شکل خواهد بود:
[[1, 2, 3], 4]
در صورتی که با اپراتور spread اعضای آرایه قبلی در آرایه جدید قرار می گرفتند نه خود آرایه:
[1, 2, 3, 4]
برای اپراتور spread در اشیاء هم می توان گفت:
const Person = { name: 'Amir' } const newPerson = { ...Person, age: 24 } console.log(newPerson);
با استفاده از اپراتور spread توانستیم خصوصیات (propery) شیء Person را درون شیء newPerson کپی کنیم.
به نظر شما خروجی این کد چه خواهد بود؟ بله خروجی بدین صورت است:
[object Object] { age: 24, name: "Amir" }
نکته: در syntax بالا JSBin به شما خطا می دهد که مشکلی نیست و می توانید آن را نادیده بگیرید. در دوره ما این syntax کاملا پذیرفته است.
حالا برای اپراتور rest (که کمتر از آن استفاده می شود) می توان گفت:
const filter = (...args) => { return args.filter(el => el === 1); } console.log(filter(1, 2, 3));
در این کد از یک تابع Arrow استفاده کرده ایم (ر.ک به جلسات قبل) سپس با استفاده از اپراتور rest گفته ایم تمامی آرگومان های تابع را در یک آرایه قرار بده. سپس از تابع ()filter استفاده کرده ایم که یک تابع پیش ساخته در خود جاوا اسکریپت است و یک تابع را روی تک تک اعضای یک آرایه اجرا می کند. برای آرگومان های تابع filter باز هم از یک Arrow Function استفاده کرده ایم (حالت خلاصه شده arrow function که در جلسات قبل از آن صحبت شد) و گفته ایم در صورتی که el === 1 (یعنی عنصر ما برابر با 1 باشد) مقدار true برگردانده شود.
حالا زمانی که نتیجه را console.log کنیم خروجی به این شکل خواهد بود:
[1]
به نظر شما چرا خروجی به شکل آرایه است؟ اپراتور rest تمام آرگومان ها را به صورت یک آرایه در می آورد بنابراین زمانی که این آرایه فیلتر شود خروجی نیز همان آرایه خواهد بود.
یکی دیگر از ویژگی های ES6 مبحث destructuring است. این قابلیت به شما اجازه می دهد که عناصر آرایه ها و یا خصوصیات اشیاء را به راحتی استخراج کرده و درون یک متغیر قرار دهید. این تعریف در ابتدا شبیه به اپراتور spred است اما کاملا متفاوت است. spread تمام اعضای آرایه یا خصوصیات یک شیء را می گیرد و آن ها را درون یک شیء یا آرایه جدید قرار می دهد در حالی که destructuring به شما اجازه می دهد یکی از خصوصیات شئ یا اعضای آرایه را بگیرید و آن را درون متغیرها قرار بدهید.
برای آرایه ها می توانیم این مثال را بزنیم: فرض کنید آرایه ای با دو عضو داریم: Hello و Amir
اگر بخواهیم با destructuring این دو عضو را درون دو متغیر متفاوت قرار دهیم می گوییم:
[a, b] = [‘Hello’, ‘Amir’] console.log(a) // Hello خروجی می شود console.log(b) // Amir خروجی می شود
توجه کنید که a و b متغیر هستند و destructuring در واقع همان [a, b] است. آن را با آرایه اشتباه نگیرید.
اگر بخواهیم همین مثال را برای اشیاء توضیح دهیم می گوییم فرض کنید شیء ای با دو خصوصیت داشته باشیم:
{name: ‘Amir’, age: 24}
حالا می توانیم این کار را انجام دهیم:
{name} = {name: ‘Amir’, age: 24} console.log(name) // Amir خروجی می شود console.log(age) // undefined خطای
بنابراین در آرایه ها ترتیب مهم است (a و b به ترتیب اعضای اول و دوم آرایه را میگیرند) اما در اشیاء نام خصوصیت (property name) است که تعیین کننده است.
بیایید مثال عملی دیگری نیز ببینیم:
const numbers = [1, 2, 3]; [num1, num2] = numbers; console.log(num1, num2);
خروجی این مثال اعداد 1 و 2 خواهند بود. همانطور که می بینید در انتخاب نام متغیر کاملا آزاد هستید (مجبور به انتخاب a و b نیستید)
سوال: اگر بخواهیم عضو اول (عدد 1) و سوم (عدد 3) را دریافت کنیم اما عضو دوم را دریافت نکنیم چطور؟
پاسخ: برای این کار می توانید کدها را به شکل زیر بنویسید:
[num1, ,num3] = numbers;
یعنی جای عضو دوم را با اسپیس خالی گذاشته ایم. توجه داشته باشید که می توانید به جای num3 هر نام دلخواه دیگری را قرار دهید:
const numbers = [1, 2, 3]; [num1, ,learningJSwithRoxo] = numbers; console.log(num1, learningJSwithRoxo);
نام متغیر را learning js with Roxo قرار داده ام و می بینید که این دستور هنوز هم اعداد 1 و 3 را به عنوان خروجی نمایش می دهد.
متاسفانه Destructuring برای اشیاء در JSbin پشتیبانی نمی شود اما syntax همان شکلی است که بالاتر گفته شد. در طول پروژه نیز از تمام این موارد استفاده خواهیم کرد (هر چند به ندرت).
این قسمت آخرین قسمت از مرور ویژگی های مهم ES6 بود. در قسمت بعد چند نکته تکمیلی در رابطه با جاوا اسکریپت را بررسی می کنیم و سپس در جلسات بعدی آن وارد react خواهیم شد. امیدوارم از این قسمت لذت برده باشید.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.