آموزش جاوا اسکریپت – جلسه ۱۹ – مفاهیم rest و spread

در مقاله قبل، یعنی جلسه 18 از سری آموزشی جامع جاوا اسکریپت، نحوه رفع مشکل Block Rendering را توسط اتریبیوت های async و defer آموزش دادیم. در این مقاله می خواهیم پارامترهای Rest و Spread را در جاوا اسکریپت تشریح کنیم.
بسیاری از توابع جاوا اسکریپتی از تعداد آرگومان های دلخواه بعنوان ورودی پشتیبانی می کنند. برای اینکه بتوانیم تعداد نامحدودی آرگومان به توابع پاس دهیم باید از ساختار REST استفاده کنیم. بعنوان مثال به توابع زیر توجه کنید:
- max(arg1, arg2, …, argN) که بزرگترین مقدار را بر می گرداند.
- assign(dest, src1, …, srcN) که property های آبجکت های src1, … srcN را در آبجکت dest کپی می کند.
پارامترهای Rest در جاوا اسکریپت:
تابع می تواند با تعداد نامحدودی از پارامترها تعریف شود.
مثال (بدون استفاده از پارامترهای rest…):
function sum(a, b) { return a + b; } alert( sum(1, 2, 3, 4, 5) );
در این مثال خطایی وجود ندارد اما تابع sum را با 5 پارامتر فراخوانی کرده ایم اما در تعریف تابع فقط دو آرگومان ورودی داریم. پس این تابع دو آرگومان اول یعنی 1 و 2 را جمع می کند (و بقیه آرگومان ها را نادیده می گیرد) و خروجی برابر 3 خواهد بود.
مثال (با استفاده از پارامترهای rest…):
با تعریف سه نقطه (…) در پشت متغیر پارامتر می توان از قابلیت rest بهره برد و سایر پارامترها را بصورت آرایه در آن جای داد.
بعنوان مثال برای جای دادن تمام آرگومان های ورودی در پارامتر args می توان به شکل زیر عمل کرد:
function sumAll(...args) { // args is the name for the array let sum = 0; for (let arg of args) sum += arg; return sum; } alert( sumAll(1) ); // 1 alert( sumAll(1, 2) ); // 3 alert( sumAll(1, 2, 3) ); // 6
البته می توان مثلا دو پارامتر اول را به شکل سابق تعریف کرد و پارامترهای سوم به بعد را بصورت …rest تعریف کرد.
بعنوان مثال در تابع زیر دو آرگومان firstName و lastName در حالت عادی تعریف شده اند و می خواهیم بقیه متغیرها را در …titles جای دهیم.
function showName(firstName, lastName, ...titles) { alert( firstName + ' ' + lastName ); // Julius Caesar // the rest go into titles array // i.e. titles = ["Consul", "Imperator"] alert( titles[0] ); // Consul alert( titles[1] ); // Imperator alert( titles.length ); // 2 } showName("Julius", "Caesar", "Consul", "Imperator");
نکته: دقت شود که پارامتر rest باید حتما در انتهای لیست آرگومان های ورودی تابع تعریف شود وگرنه مانند زیر ارور خواهد داد:
function f(arg1, ...rest, arg2) { // arg2 after ...rest ?! // error }
دریافت لیست تمام آرگومان های تابع توسط arguments:
آبجکتی است در جاوا اسکریپت که لیست تمام آرگومان های ورودی تابع را بر می گرداند.
بعنوان مثال:
function showName() { alert( arguments.length ); alert( arguments[0] ); alert( arguments[1] ); // it's iterable // for(let arg of arguments) alert(arg); } // shows: 2, Julius, Caesar showName("Julius", "Caesar"); // shows: 1, Ilya, undefined (no second argument) showName("Ilya");
در نسخه های قبلی جاوا اسکریپت امکان استفاده از rest وجود نداشت زیرا هنوز معرفی نشده بود. تنها راه مشاهده لیست آرگومان های ورودی یک تابع استفاده از arguments می بود. دقت کنید argument شبیه آرایه است اما نمی توان از متدهای آرایه در آن استفاده کرد. مثلا arguments.map(…) جواب نمی دهد.
توجه کنید که متغیر arguments لیست تمام آرگومان های تابع را بر می گرداند و نمی توان از آن برای گرفتن بخشی از آرگومان های تابع استفاده کرد.
ساختار Spread در جاوااسکریپت:
تا اینجا نحوه تعریف آرگومان های نامحدود برای یک تابع جاوا اسکریپتی و نیز دریافت لیست تمام آرگومان های تابع را آموختیم.
فرض کنید می خواهیم بزرگترین مقدار یک آرایه را توسط تابع Math.max بدست بیاوریم. مثال زیر را برای تعداد محدودی از اعداد در نظر بگیرید:
alert( Math.max(3, 5, 1) ); // 5
اما اگر اعداد ما در آرایه تعریف شده باشند قضیه به چه شکل خواهد شد:
let arr = [3, 5, 1]; alert( Math.max(arr) ); // NaN
همانطور که مشاهده می شود کد بالا مقدار موردنظر را بر نمی گرداند. دقت کنید که تابع max نیاز به لیستی از اعداد بعنوان آرگومان ورودی خود دارد اما در مثال بالا یک آرایه به آن پاس داده ایم و خطا می دهد.
مسلما ما نمی توانیم تمام آیتم های آرایه را بصورت مجزا (به شکل زیر) در تابع max تعریف کنیم. زیرا هم کد طولانی می شود و هم نمی دانیم آرایه دقیقا چه تعداد المان در خود دارد.
Math.max(arr[0], arr[1], arr[2])
راه حل این مشکل استفاده از ساختار spread است. باید بصورت زیر از سه نقطه استفاده کنیم:
let arr = [3, 5, 1]; alert( Math.max(...arr) ); // 5 (spread turns array into a list of arguments)
spread شبیه rest است اما کاری کاملا متفاوت را انجام می دهد. یعنی تعداد نامشخصی از آرگومان را به یک آرگومان نسبت می دهد. اما rest برعکس بود و یک آرگومان مثلا …args را به چند آرگومان نامحدود نسبت می داد.
در مثال تابع max همچنین می توانیم چند متغیر spread را به عنوان آرگومان ورودی تابع max تعریف کنیم:
let arr1 = [1, -2, 3, 4]; let arr2 = [8, 3, -8, 1]; alert( Math.max(...arr1, ...arr2) ); // 8
حتی می توانیم ترکیبی از اعداد و آرایه را بعنوان آرگومان ورودی max تعریف کنیم:
let arr1 = [1, -2, 3, 4]; let arr2 = [8, 3, -8, 1]; alert( Math.max(1, ...arr1, 2, ...arr2, 25) ); // 25
اگر از عملگر spread برای یک رشته استفاده کنید آن را به آرایه ای از کاراکترهای آن رشته تبدیل خواهد کرد:
let str = "Hello"; alert( [...str] ); // H,e,l,l,o
کپی کردن یک آبجکت یا آرایه:
همانطور که قبلا عرض کردیم می توان تمام property های یک آبجکت را توسط متد object.assign() در یک آبجکت دیگر کپی کرد. روش دیگر برای انجام اینکار استفاده از عملگر spread می باشد.
let arr = [1, 2, 3]; let arrCopy = [...arr]; // spread the array into a list of parameters // then put the result into a new array // do the arrays have the same contents? alert(JSON.stringify(arr) === JSON.stringify(arrCopy)); // true // are the arrays equal? alert(arr === arrCopy); // false (not same reference) // modifying our initial array does not modify the copy: arr.push(4); alert(arr); // 1, 2, 3, 4 alert(arrCopy); // 1, 2, 3
در این مقاله، یعنی بخش نوزدهم آموزش js ، پارامترهای Rest، نحوه کپی کردن آبجکت یا آرایه، دریافت لیست کامل آرگومان های یک تابع توسط arguments و ساختار Spread را یاد گرفتیم. در مقاله بعدی نحوه مدیریت خطا یا Error Handling را توسط بلاک Try-Catch آموزش خواهیم داد.
دیدگاهتان را بنویسید