در مقالات آموزشی ری اکت در بخش اول و دوم توضیحاتی در این حیطه ارائه کردیم، به ادامه آموزش بپردازیم.
بازگشت ضمنی (Implicit Return)
تابعهای Arrow امکان داشتن مقادیر بازگشتی ضمنی را فراهم ساختهاند. این مقادیر بدون استفاده از کلیدواژه return بازگشت مییابند. طرز کار این بازگشت به این صورت است که گزارههای تکخطی در بدنه تابع به صورت زیر تعریف میشوند:
۱ ۲ |
<span style="color: #000000;">const myFunction = () => 'test' myFunction() //'test'</span> |
مثال دیگر زمانی است که یک شیء بازگشت میدهیم. دقت کنید که باید آکولادها را درون پرانتزها قرار دهید تا با پرانتزهای تشکیل دهنده بدنه تابع اشتباه گرفته نشوند:
۱ ۲ |
<span style="color: #000000;">const myFunction = () => ({ value: 'test' }) myFunction() //{value: 'test'}</span> |
طرز کار this در تابعهای Arrow
This مفهومی است که شاید درک آن دشوار باشد، چون بسته به زمینه و همچنین بر اساس حالت جاوا اسکریپت (strict یا غیر آن) متفاوت است.
میبایست این نکته را روشن کنیم، زیرا تابعهای Arrow به طرزی کاملاً متفاوت از تابعهای معمولی عمل میکنند. زمانی که یک متد برای یک شیء تعریف میشود، در تابع معمولی this اشاره به شیء دارد و از این رو میتوان کد زیر را داشت:
۱ ۲ ۳ ۴ ۵ ۶ ۷ |
<span style="color: #000000;">const car = { model: 'Fiesta', manufacturer: 'Ford', fullName: function() { return `${this.manufacturer} ${this.model}` } }</span> |
بدین ترتیب فراخوانی ()car.fullName مقدار “Ford Fiesta” را بازگشت میدهد.
دامنه this در تابعهای Arrow از زمینه اجرایی به ارث میرسید. یک تابع Arrow به هیچ وجه به this اتصال نمییابد و از این رو مقدار آن در پشته فراخوانی جستجو میشود. بدین ترتیب کدی مانند ()car.fullName کار نخواهد کرد و رشته “undefined undefined” را بازگشت میدهد:
۱ ۲ ۳ ۴ ۵ ۶ ۷ |
<span style="color: #000000;">const car = { model: 'Fiesta', manufacturer: 'Ford', fullName: () => { return `${this.manufacturer} ${this.model}` } }</span> |
به همین دلیل، تابعهای Arrow به عنوان متدهای شیء مناسب نیستند. همچنین تابعهای Arrow نمیتوانند به عنوان سازنده (constructor) استفاده شوند، زیرا در هنگام مقداردهی اولیه یک خطای TypeError ایجاد میشود.
در این موارد باید از تابعهای معمولی استفاده کرد که زمینه دینامیک مورد نیاز نیست. همچنین این مورد در هنگام مدیرت رویدادها، موجب ایجاد مشکل میشود. شنوندههای رویداد DOM سعی میکنند this را روی عنصر هدف تنظیم کنند و اگر در handler رویداد روی this تکیه کنیم، به یک تابع معمولی نیاز خواهیم داشت:
۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ ۱۰ |
<span style="color: #000000;">const link = document.querySelector('#link') link.addEventListener('click', () => { // this === window }) const link = document.querySelector('#link') link.addEventListener('click', function() { // this === link })</span> |
Rest و Spread
میتوان یک آرایه، یک شیء یا یک رشته را با استفاده از عملگر spread بسط داد. توضیح خود را با مثالی از آرایه آغاز میکنیم. فرض کنید:
۱ |
<span style="color: #000000;">const a = [۱، ۲، ۳]</span> |
شما میتوانید یک آرایه جدید با کد زیر بسازید:
۱ |
<span style="color: #000000;">const c = [...a]</span> |
این کد برای شیء نیز به خوبی کار میکند. شیء را با دستور زیر کلون کنید:
۱ |
<span style="color: #000000;">const newObj = { ...oldObj }</span> |
با استفاده از رشتهها، عملگر spread یک آرایه با هر یک از کاراکترهای رشته ایجاد میکند:
۱ ۲ |
<span style="color: #000000;">const hey = 'hey' const arrayized = [...hey] // ['h'، 'e'، 'y']</span> |
این عملگر برخی کاربردهای بسیار مفید دارد. مهمترین کاربر توانایی استفاده از یک آرایه به عنوان آرگومان تابع به روشی بسیار ساده است:
۱ ۲ ۳ |
<span style="color: #000000;">const f = (foo، bar) => {} const a = [۱، ۲] f(...a)</span> |
در گذشته این کار را میتوانستید با استفاده از (f.apply(null، a انجام دهید اما این روش زیبا و خوانا نیست. عنصر rest زمانی مفید است که میخواهیم با تخریب آرایه (array destructuring):
۱ ۲ |
<span style="color: #000000;">const numbers = [۱، ۲، ۳، ۴، ۵] [first، second، ...others] = numbers</span> |
و spread عناصر کار کنیم:
۱ ۲ ۳ |
<span style="color: #000000;">const numbers = [۱، ۲، ۳، ۴، ۵] const sum = (a، b، c، d، e) => a + b + c + d + e const sum = sum(...numbers)</span> |
ES2018 مشخصات rest را معرفی کرده است که همین مفهوم اما در مورد شیء را داراست.
مشخصات Rest:
۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ ۱۰ ۱۱ ۱۲ |
<span style="color: #000000;">const { first, second, ...others } = { first: ۱, second: ۲, third: ۳, fourth: ۴, fifth: ۵ } first // ۱ second // ۲ others // { third: 3, fourth: 4, fifth: 5 }</span> |
مشخصات spread امکان ایجاد یک شیء جدید با ترکیب کردن مشخصات شیء ارسالی پس از عملگر spread را میدهد:
۱ ۲ |
<span style="color: #000000;">const items = { first, second, ...others } items //{ first: 1, second: 2, third: 3, fourth: 4, fifth: 5 }</span> |
تخریب شیء و آرایه
با فرض وجود یک شیء میتوان با استفاده از ساختار تخریب، تنها برخی از مقادیر را استخراج کرد و آنها را در «متغیرهای با نام» قرار داد:
۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹ |
<span style="color: #000000;">const person = { firstName: 'Tom', lastName: 'Cruise', actor: true, age: ۵۴ //made up } const { firstName: name, age } = person //name: Tom, age: 54</span> |
name و age شامل مقادیر مطلوب ما هستند. همین ساختار در مورد آرایهها نیز کار میکند:
۱ ۲ |
<span style="color: #000000;">const a = [۱، ۲، ۳، ۴، ۵] const [first، second] = a</span> |
این گزاره با دریافت آیتمها از اندیسهای ۰، ۱ و ۴، سه متغیر جدید از آرایه a ایجاد میکند:
۱ |
<span style="color: #000000;">const [first، second،،، fifth] = a</span> |
الفاظ قالبی (Template Literals)
الفاظ قالبی ویژگی جدید ES2015 / ES6 است که امکان کار با رشتهها به روشی کاملاً جدید نسبت به ES5 و قبلتر را فراهم ساخته است.
ساختار آن در نگاه اول بسیار ساده است و کافی است به جای گیومههای تکی یا جفتی از علامت backtick () استفاده کرد:
۱ |
<span style="color: #000000;">const a_string = `something`</span> |
دقت کنید که این الفاظ کاملاً منحصر به فرد هستند، زیرا ویژگیهای زیادی ارائه میکنند که رشتههای معمولی با گیومه ندارند. از آن جمله:
- ساختاری عالی دارند که امکان تعریف رشتههای چندخطی را میدهد.
- روش آسانی برای میانیابی متغیرها و عبارتها در داخل رشتهها در اختیار ما قرار میدهند.
- امکان ایجاد DSL با استفاده از تگهای قالبی را فراهم میسازند. DSL به معنی «زبان خاص یک حوزه» است و برای مثال در React در کامپوننتهای دارای سبک برای تعریف CSS کامپوننتها استفاده میشوند.)
هر کدام از جزییات فوق را در ادامه بررسی میکنیم.
رشتههای چندخطی
تا قبل از ES6 برای ایجاد یک رشته که در دو یا چند خط گسترش مییابد از کاراکتر \ در انتهای هر خط استفاده میکردیم:
۱ ۲ ۳ |
<span style="color: #000000;">const string = 'first part \ second part'</span> |
بدین ترتیب امکان ایجاد یک رشته ۲ خطی پدید میآمد؛ اما تنها در یک خط رندر میشد:
۱ |
<span style="color: #000000;">first part second part</span> |
برای رندر کردن رشته در چند خط باید به صورت زیر صریحاً از \n در انتهای هر خط استفاده میکردیم:
۱ ۲ ۳ |
<span style="color: #000000;">const string = 'first line\n \ second line'</span> |
یا
۱ |
<span style="color: #000000;">const string = 'first line\n' + 'second line'</span> |
الفاظ قالبی امکان تعریف رشتههای چندخطی را سادهتر ساختهاند.
زمانی که یک لفظ قالبی با backtick باز شود، میتوانید برای ایجاد یک خط جدید از اینتر استفاده کنید و دیگر نیازی به کاراکترهای خاص نیست و همچنان که دیده میشود رندر خواهد شد:
۱ ۲ ۳ ۴ ۵ ۶ |
<span style="color: #000000;">const string = `Hey this string is awesome!`</span> |
به خاطر داشته باشید که در این حالت فاصله معنیدار است. از این رو در کد زیر:
۱ |
<span style="color: #000000;">const string = `First</span> |
قصد داریم یک رشته مانند زیر ایجاد کنیم:
۱ ۲ |
<span style="color: #000000;">First Second</span> |
یک روش ساده برای اصلاح این مشکل آن است که یک خط خالی داشته باشیم و متد ()trim را درست پس از backtick پایانی قرار دهیم تا هر فاصلهای را پیش از کاراکتر اول حذف کند:
۱ ۲ ۳ |
<span style="color: #000000;">const string = ` First Second`.trim()</span> |
میانیابی
الفاظ قالبی یک روش آسان برای میانیابی متغیرها و عبارتهای درون رشتهها ارائه کردهاند.
این کار با استفاده از ساختار {…}$ ممکن است:
۱ ۲ |
<span style="color: #000000;">const var = 'test' const string = `something ${var}` //something test</span> |
درون {}$ میتوان هر چیزی حتی عبارتها را اضافه کرد:
۱ ۲ |
<span style="color: #000000;">const string = `something ${۱ + ۲ + ۳}` const string2 = `something ${foo() ? 'x' : 'y'}`</span> |