آموزش جاوا اسکریپت – جلسه ۹ – آرایه [Array]
![آموزش جاوا اسکریپت – جلسه 9 – آرایه [Array]](https://rahkarino.ir/wp-content/uploads/2020/06/js-part9-array.jpg)
در جلسه قبل، درباره انواع داده در javascript یا DataTypes صحبت کردیم. در جلسه نهم می خواهیم تمام مباحث کاربردی و مهم جاوا اسکریپت در رابطه با آرایه ها (Arrays) را آموزش دهیم.
گاهی اوقات نیاز داریم یک لیست مرتب از آیتم ها داشته باشیم. مانند لیستی از نام کاربران یا محصولات و…
در اینگونه موارد استفاده از آبجکت ها نمی تواند کارایی داشته باشد زیرا اشیاء هیچگونه متدی برای مرتب سازی آیتم ها ندارد و اصلا مناسب کارهای این چنینی نمی باشد. مثلا نمی توان یک property جدید به لیست propertyهای موجود اضافه کرد.
برای این منظور آرایه ها (Array) معرفی شدند. ساختاری برای ذخیره مجموعه های مرتب.
تعریف آرایه (Array Declaration):
دو راه برای تعریف یک آرایه خالی وجود دارد:
let arr = new Array(); let arr = [];
در اغلب موارد روش دوم استفاده می شود. برای مقداردهی اولیه آیتم های آرایه داریم:
let fruits = ["Apple", "Orange", "Plum"];
ایندکس های آرایه از نوع عددی هستند که از عد 0 شروع می شود. برای دسترسی به مقدار هر آیتم در آرایه می توان از براکت به شکل زیر استفاده کرد:
let fruits = ["Apple", "Orange", "Plum"]; alert( fruits[0] ); // Apple alert( fruits[1] ); // Orange alert( fruits[2] ); // Plum
براحتی می توان مقدار یک آیتم را تغییر داد:
fruits[2] = 'Pear'; // now ["Apple", "Orange", "Pear"]
یا یک آیتم جدید به آرایه افزود:
fruits[3] = 'Lemon'; // now ["Apple", "Orange", "Pear", "Lemon"]
یا تعداد کل آیتم های آرایه را بدست آورد:
let fruits = ["Apple", "Orange", "Plum"]; alert( fruits.length ); // 3
یا تمام آیتم های آرایه را در alert نمایش داد:
let fruits = ["Apple", "Orange", "Plum"]; alert( fruits ); // Apple,Orange,Plum
یک آرایه می تواند انواع مختلف داده را در خود ذخیره کند:
// mix of values let arr = [ 'Apple', { name: 'John' }, true, function() { alert('hello'); } ]; // get the object at index 1 and then show its name alert( arr[1].name ); // John // get the function at index 3 and run it arr[3](); // hello
ویرگول انتهای آیتم های آرایه (Trailing Comma):
هر آرایه (مانند آبجکت) می تواند با کاما (ویرگول) تمام شود.
let fruits = [ "Apple", "Orange", "Plum", ];
تعریف ویرگول trailing باعث می شود راحت تر یک آیتم را اضافه یا حذف کرد.
تعریف آرایه توسط new Array:
روش دیگری که می توان یک آرایه تعریف کرد:
let arr = new Array("Apple", "Pear", "etc");
از روش فوق برای تعریف آرایه به ندرت استفاده می شود. زیرا کد براکت [] کوتاه تر است.
نکته: اگر از new Array برای تعریف یک آرایه جدید که فقط یک آرگومان با نوع عددی دارد استفاده کنیم، یک آرایه بدون آیتم و با طول مشخص شده ایجاد می شود:
let arr = new Array(2); // will it create an array of [2] ? alert( arr[0] ); // undefined! no elements. alert( arr.length ); // length 2
در کد فوق دستور new Array(number) باعث شده تمام آیتم های آرایه undefined شوند. برای پیشگیری از بروز چنین مشکلاتی باید از براکت به منظور تعریف آرایه استفاده کنید.
آرایه های چند بعدی (Multidimensional arrays):
آرایه می تواند آیتمی داشته باشد که خود آن آیتم نیز آرایه باشد. بعنوان مثال برای ذخیره ماتریکس داریم:
let matrix = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]; alert( matrix[1][1] ); // 5, the central element
متدهای pop/push, shift/unshift:
مفهوم صف (queue) یکی از کاربردی ترین مفاهیم در آرایه ها در جاوا اسکریپت می باشد.
اکشن های اصلی صف:
صف دو اکشن اصلی دارد:
- Push: یک آیتم به انتهای آرایه اضافه می شود.
- Shift: گرفتن اولین آیتم از آرایه. در اینصورت دومین آیتم در پوزیشن آیتم اول قرار می گیرد.
در عمل قابلیت صف (queue) در آرایه ها کاربرد زیادی دارد. مثلا نمایش لیست پیام های کاربر در روی صفحه. صف (queue) بصورت FiFo (First-in First-out) کار می کند.
قابلیت دیگری که آرایه ها دارند مفهوم پشته (stack) می باشد.
اکشن های اصلی پشته:
دو اکشن اصلی در پشته تعریف می شود:
- push: درج یک آیتم در انتهای آرایه.
- Pop: گرفتن یک آیتم از انتهای آرایه.
بنابراین هر دو اکشن در stack روی آخرین آیتم در انتهای آرایه کار می کنند. پشته یا stack بصورت LiFo (Last-in First-out) کار می کند.
آرایه ها در javascript می توانند به هر دو شکل صف و پشته کار کنند.
آرایه ها در javascript می توانند به هر دو شکل صف و پشته کار کنند. آرایه ها این امکان را دارند که یک آیتم را هم به انتهای آنها اضافه کنیم و هم به ابتدای آرایه. به همین ترتیب حذف آیتم از آرایه.
متدهایی که با انتهای آرایه کار می کنند:
در این بخش، متدهایی را که یک یا چند آیتم به انتهای آرایه اضافه می کنند و یا از انتهای آرایه یک یا چند آیتم را حذف می کنند را معرفی می کنیم.
متد pop:
آخرین آیتم آرایه را استخراج کرده و return می کند.
let fruits = ["Apple", "Orange", "Pear"]; alert( fruits.pop() ); // remove "Pear" and alert it alert( fruits ); // Apple, Orange
متد push:
یک آیتم را به انتهای آرایه اضافه می کند.
let fruits = ["Apple", "Orange"]; fruits.push("Pear"); alert( fruits ); // Apple, Orange, Pear
دقت کنید که خروجی متد fruits.push(…) با fruits[fruits.length] = … یکسان است.
متدهایی که با ابتدای آرایه کار می کنند:
در این بخش، متدهایی را که یک یا چند آیتم به ابتدای آرایه اضافه می کنند و یا از ابتدای آرایه یک یا چند آیتم را حذف می کنند را معرفی می کنیم.
متد Shift:
اولین آیتم آرایه را استخراج کرده و return می کند.
let fruits = ["Apple", "Orange", "Pear"]; alert( fruits.shift() ); // remove Apple and alert it alert( fruits ); // Orange, Pear
متد unshift:
یک آیتم را به ابتدای آرایه اضافه می کند.
let fruits = ["Orange", "Pear"]; fruits.unshift('Apple'); alert( fruits ); // Apple, Orange, Pear
متدهای push و unshift می توانند همزمان چند آیتم را به آرایه اضافه کنند:
let fruits = ["Apple"]; fruits.push("Orange", "Peach"); fruits.unshift("Pineapple", "Lemon"); // ["Pineapple", "Lemon", "Apple", "Orange", "Peach"] alert( fruits );
مقایسه متدهای درج/حذف از لحاظ کارایی (Performance):
مطابق تصویر زیر، متدهای pop/push سریع اجرا می شوند اما متدهای unshift و shift کند اجرا می شوند. در ادامه دلیلش را بیان می کنیم.
دلیل سرعت بیشتر متدهای pop/push نسبت به unshift/shift:
اما چرا وقتی آیتمی را به انتهای آرایه اضافه/حذف می کنیم سریع تر انجام می شود نسبت به ابتدای آرایه؟
بیایید ببینیم چه اتفاقی می افتد:
fruits.shift(); // take 1 element from the start
نکته اینجاست که در متد shift فقط برداشتن اولین آیتم از آرایه کافی نیست! بلکه باید ایندکس تمام آیتم های بعدی آرایه نیز آپدیت شود و یکی به عقب بروند:
در تصویر بالا مشخص است که پس از برداشتن اولین آیتم از ابتدای آرایه توسط متد shift، ایندکس آیتم 1 باید به 0 تبدیل شود، آیتم 2 به 1 و… در انتها نیز باید length آرایه یکی کم شود.
هر چه تعداد المان های آرایه بیشتر باشد، زمان و کار بیشتری صرف انجام عملیات shift در memory خواهد شد.
در متد unshift هم کاری شبیه shift صورت می گیرد. با این تفاوت که یک آیتم جدید به آرایه اضافه می شود و نیاز است تمام المان های بعدی آرایه یکی به راست بروند و ایندکس آنها یک واحد افزایش یابد.
اما در متدهای pop/push نیازی به جابجایی آیتم ها و آپدیت ایندکس آنها نمی باشد. فقط length آرایه آپدیت خواهد شد.
fruits.pop(); // take 1 element from the end
به تصویر زیر دقت کنید:
پس متدهای pop و push نیاز به صرف زمان و کار کمتری در مموری دارند و مسلما سریع تر اجرا خواهند شد.
اجرای حلقه (Loop) روی آیتم های آرایه:
یکی از روش های کلاسیک کار با آیتم های یک آرایه، لوپ زدن روی ایندکس های آن است:
let arr = ["Apple", "Orange", "Pear"]; for (let i = 0; i < arr.length; i++) { alert( arr[i] ); }
اما روش مدرن تری برای انجام اینکار وجود دارد. استفاده از ساختار for..of:
let fruits = ["Apple", "Orange", "Plum"]; // iterates over array elements for (let fruit of fruits) { alert( fruit ); }
همانطور که مشاهده می کنید دستور در حلقه for..of ما دسترسی به طول آرایه نداریم و صرفا می خواهیم تمام آیتم های آرایه را چاپ کنیم. صرف نظر از اینکه آرایه چند آیتم دارد. حلقه for..of در اینگونه موارد کاربرد دارد.
از لحاظ تکنیکی، آرایه ها ازنوع آبجکت می باشند پس می توان توسط حلقه for..in روی آیتم های آن لوپ زد:
let arr = ["Apple", "Orange", "Pear"]; for (let key in arr) { alert( arr[key] ); // Apple, Orange, Pear }
حلقه for..in اصولا برای آبجکت ها کارایی بیشتری دارد. اگر از آن برای لوپ زدن در آرایه استفاده کنیم فقط روی ایندکس آیتم های آرایه لوپ نمی زند بلکه روی تمام property های آرایه حلقه اجرا می شود و باعث کندی اجرای حلقه برای آرایه ها می شود. پس سعی کنید از for..in فقط در آبجکت ها استفاده کنید. زیرا استفاده از آن در آرایه ها باعث کندی 10 تا 100 برابری اجرای حلقه خواهد شد.
طول آرایه (Length):
هر زمان که یک آیتم به آرایه اضافه یا از آن کم کنیم، طول آرایه (length property) بطور اتوماتیک آپدیت می شود. طول آرایه با تعداد آیتم های داخل آرایه یکی نیست. بلکه در واقع طول آرایه برابر است با بزرگترین ایندکس بعلاوه یک.
let fruits = []; fruits[123] = "Apple"; alert( fruits.length ); // 124
در پروژه عملی ما معمولا بصورت فوق آرایه را تعریف نمی کنیم.
واقعیت جالب دیگری که درباره طول آرایه وجود دارد اینست که Length آرایه قابل ویرایش است!
اگر طول آرایه را بطور دستی کم کنیم آیتم های آرایه به همان مقدار کاهش می یابند:
let arr = [1, 2, 3, 4, 5]; arr.length = 2; // truncate to 2 elements alert( arr ); // [1, 2] arr.length = 5; // return length back alert( arr[3] ); // undefined: the values do not return
و سپس اگر طول آرایه را افزایش دهیم آیتم های حذف شده بر نمی گردند (برای همیشه پاک شده اند).
نکته: ساده ترین راه برای خالی کردن آرایه در جاوا اسکریپت دستور arr.length = 0 می باشد.
متد toString:
وقتی می خواهیم آیتم های یک array را در alert نمایش دهیم جاوا اسکریپت بطور خودکار متد toString را برای هر یک از المان های آرایه اجرا کرده و آنها را با یک ویرگول از هم جدا می کند. مطابق زیر:
let arr = [1, 2, 3]; alert( arr ); // 1,2,3 alert( String(arr) === '1,2,3' ); // true
سایر متدهای کاربردی در کار با آرایه ها:
تا اینجا متدهای مربوط به افزودن/ حذف آیتم از ابتدا/انتهای آرایه را معرفی کرده ایم:
- arr.push(…items): افزودن آیتم جدید به انتهای آرایه
- ()arr.pop: خارج کردن یک آیتم از انتهای آرایه
- ()arr.shift: خارج کردن یک آیتم از ابتدای آرایه
- arr.unshift(…items): افزودن آیتم جدید به ابتدای آرایه
در این بخش می خواهیم سایر متدهای کاربردی در کار با آرایه ها را معرفی کنیم.
متد Splice:
چگونه می توان یک آیتم را از آرایه حذف کرد؟ نوع داده ای آرایه ها object می باشد پس می توان توسط متد delete آیتم (یا آیتم ها) را از آرایه حذف کرد.
let arr = ["I", "go", "home"]; delete arr[1]; // remove "go" alert( arr[1] ); // undefined // now arr = ["I", , "home"]; alert( arr.length ); // 3
همانطور که مشاهده می شود آیتم دوم یعنی arr[1] را حذف کردیم اما طول آرایه همچنان 3 است!
رفتار فوق طبیعی است زیرا متد delete obj.key یک آیتم را توسط کلید آن حذف می کند. اینکار در مبحث آبجکت ها کاملا صحیح است زیرا در کار با اشیاء فقط می خواهیم آیتم را حذف کنیم. اما در آرایه ها نیاز است پس از حذف آیتم از آرایه، سایر آیتم ها جابجا شوند و جای خالی آیتم حذف شده را پر کنند. بنابراین باید از متدهای ویژه آرایه استفاده کرد.
متد arr.splice(start) در آرایه ها می تواند تقریبا هر کاری انجام دهد. درج، حذف و جایگزینی آیتم.
فرمت متد splice به این صورت است:
arr.splice(index[, deleteCount, elem1, ..., elemN])
توضیح دستور فوق: از پوزیشن index شروع می کند. سپس آیتم های deleteCount را حذف می کند و سپس آیتم های elem1, … elemNرا جایگزین آنها می کند.
حذف آیتم توسط Splice:
در مثال زیر، می خواهیم آیتم دوم (study) آرایه را پاک کنیم:
let arr = ["I", "study", "JavaScript"]; arr.splice(1, 1); // from index 1 remove 1 element alert( arr ); // ["I", "JavaScript"]
در کد فوق، متد splice از ایندکس 1 (معادل آیتم دوم) شروع کرده و یک آیتم را حذف می کند. در مثال زیر می خواهیم سه آیتم را از آرایه حذف کنیم و آنها را با دو آیتم جدید جایگزین کنیم:
let arr = ["I", "study", "JavaScript", "right", "now"]; // remove 3 first elements and replace them with another arr.splice(0, 3, "Let's", "dance"); alert( arr ) // now ["Let's", "dance", "right", "now"]
بازگرداندن لیست آیتم های حذف شده توسط Splice:
در مثال زیر می خواهیم آرایه های از آیتم های حذف شده از آرایه اصلی را به خروجی بدهیم:
let arr = ["I", "study", "JavaScript", "right", "now"]; // remove 2 first elements let removed = arr.splice(0, 2); alert( removed ); // "I", "study" <-- array of removed elements
درج آیتم در آرایه بدون حذف توسط Splice:
در مثال زیر می خواهیم دو آیتم جدید به وسط آرایه اضافه کنیم (بدون اینکه آیتمی حذف شود):
let arr = ["I", "study", "JavaScript"]; // from index 2 // delete 0 // then insert "complex" and "language" arr.splice(2, 0, "complex", "language"); alert( arr ); // "I", "study", "complex", "language", "JavaScript"
باید آیتم deleteCount را در این مورد برابر 0 قرار دهیم.
نکته: در تمام متدهای آرایه در جاوااسکریپت می توان ایندکس منفی تعریف کرد. در این حالت، ایندکس مشخص کننده موقعیت آیتم موردنظر از انتهای آرایه می باشد. (بر خلاف ایندکس مثبت که مشخص کننده جایگاه آیتم از ابتدای آرایه است)
let arr = [1, 2, 5]; // from index -1 (one step from the end) // delete 0 elements, // then insert 3 and 4 arr.splice(-1, 0, 3, 4); alert( arr ); // 1,2,3,4,5
متد Slice:
متد arr.slice از متد قبلی یعنی arr.splice ساده تر است. فرمت متد slice به صورت زیر است:
arr.slice([start], [end])
توضیح دستور فوق: یک آرایه جدید بر می گرداند که کپی تمام المان های آرایه اصلی از start تا end در آن قرار دارد (خود المان end را شامل نمی شود). هر دو عدد start و end می تواند منفی باشد.
کار متد slice مانند متد str.slice است در نوع داده ای رشته (string). فقط بجای substring یک subarray برمی گرداند.
بعنوان مثال:
let arr = ["t", "e", "s", "t"]; alert( arr.slice(1, 3) ); // e,s (copy from 1 to 3) alert( arr.slice(-2) ); // s,t (copy from -2 till the end)
اگر متد slice را بدون آرگومان فراخوانی کنیم (arr.slice()) یک کپی از آرایه اصلی ایجاد می شود.
متد concat:
متد arr.concat یک آرایه جدید می سازد که آیتم های آن شامل آیتم های سایر آرایه ها می باشد. فرمت این متد به شکل زیر است:
arr.concat(arg1, arg2...)
متد concat می تواند بی نهایت آرگومان ورودی داشته باشد. خروجی آن آرایه ای است شامل تمام آیتم های arr1 و arr2 و …
نکته: اگر آرگومان arrN یک آرایه باشد تمام آیتم های آرایه در آرایه مقصد کپی می شود، در غیر اینصورت خود آرگومان کپی می شود. به مثال زیر توجه کنید:
let arr = [1, 2]; // create an array from: arr and [3,4] alert( arr.concat([3, 4]) ); // 1,2,3,4 // create an array from: arr and [3,4] and [5,6] alert( arr.concat([3, 4], [5, 6]) ); // 1,2,3,4,5,6 // create an array from: arr and [3,4], then add values 5 and 6 alert( arr.concat([3, 4], 5, 6) ); // 1,2,3,4,5,6
متد forEach:
متد forEach این امکان را می دهد که یک تابع را برای تمام آیتم های آرایه اجرا کنید. فرمت استفاده:
arr.forEach(function(item, index, array) { // ... do something with item });
بعنوان مثال در کد زیر توسط forEach تمام آیتم های آرایه را در alert نمایش می دهیم:
// for each element call alert ["Bilbo", "Gandalf", "Nazgul"].forEach(alert);
در مثال زیر هریک از آیتم های آرایه بهمراه ایندکس آنها نمایش داده می شود:
["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => { alert(`${item} is at index ${index} in ${array}`); });
متدهای indexOf/lastIndexOf و include:
کار متدهای arr.indexOf و arr.include و arr.lastIndexOf همانند کار این متدها در مبحث رشته ها می باشد با این تفاوت که بجای کار با کاراکتر، با آیتم های آرایه کار می کنند:
arr.indexOf(item, from): در آرایه arr از ایندکس from بدنبال آیتم item می گردد. اگر item در arr موجود باشد ایندکس آن را بر می گرداند و اگر item یافت نشود عدد 1- بر می گردد.
arr.lastIndexOf(item, from): همانند متد indexOf است با این تفاوت که از انتهای آرایه جستجو می کند.
arr.includes(item, from): در آرایه arr از ایندکس from بدنبال آیتم item می گردد. اگر item در arr موجود باشد true بر می گردد وگرنه false.
بعنوان مثال:
let arr = [1, 0, false]; alert( arr.indexOf(0) ); // 1 alert( arr.indexOf(false) ); // 2 alert( arr.indexOf(null) ); // -1 alert( arr.includes(1) ); // true
نکته: متدهای فوق عمل بررسی تساوی را توسط عملگر === انجام می دهند. یعنی علاوه دو آیتمی که با هم مقایسه می شوند باید کاملا با هم مساوی باشند تا true برگردد. مثلا حاصل شرط false == 0 برابر true است اما حاصل false === 0 برابر false است.
اگر فقط می خواهید بدانید آیا یک آرایه شامل یک آیتم خاص است یا خیر بهتر است (و ایندکس آن برایتان مهم نیست) از متد includes استفاده کنید.
تفاوت کوچکی که متد includes با indexOf و lastIndexOf دارد اینست که می تواند NaN را شناسایی کند:
const arr = [NaN]; alert( arr.indexOf(NaN) ); // -1 (should be 0, but === equality doesn't work for NaN) alert( arr.includes(NaN) );// true (correct)
متد find و findIndex:
فرض کنید یک آرایه ای از آبجکت ها دارید. چگونه می توانید بر اساس شرایط خاصی بدنبال آبجکت موردنظر خود بگردید؟ اینجاست که متد arr.find(func) بکار می آید.
فرمت استفاده از آن:
let result = arr.find(function(item, index, array) { // if true is returned, item is returned and iteration is stopped // for falsy scenario returns undefined });
فانکشن فوق روی تمام آیتم های آرایه arr اجرا می شود. اگر آیتم موردنظر در arr پیدا شود (شرط true شود) مقدار آیتم بر می گردد و حلقه متوقف می شود وگرنه مقدار undefined به خروجی خواهد رفت.
بعنوان مثال فرض کنید آرایه ای از کاربران داریم و می خواهیم کاربر با آیدی 1 را پیدا کنیم. داریم:
let users = [ {id: 1, name: "John"}, {id: 2, name: "Pete"}, {id: 3, name: "Mary"} ]; let user = users.find(item => item.id == 1); alert(user.name); // John
متد find در آرایه ها بسیار کاربردی است و در جاوا اسکریپت استفاده فراوان دارد. متد findIndex برای زمانیست که می خواهیم ایندکس آیتم یافت شده را بر گردانیم. اگر آیتم پیدا نشود عدد 1- برمی گردد.
متد filter:
متد find با رسیدن به اولین آیتمی که در شرط صدق کند true می شود و مقدار آن آیتم را برمی گرداند اما اگر بخواهیم تمام آیتم هایی را که شرط را true می کنند بدست آوریم باید از متد filter استفاده کنیم.
فرمت استفاده:
let results = arr.filter(function(item, index, array) { // if true item is pushed to results and the iteration continues // returns empty array if nothing found });
بنابراین خروجی متد filter آرایه ای از آیتم هایی خواهد بود که در شرط صدق می کند. برای مثال:
let users = [ {id: 1, name: "John"}, {id: 2, name: "Pete"}, {id: 3, name: "Mary"} ]; // returns array of the first two users let someUsers = users.filter(item => item.id < 3); alert(someUsers.length); // 2
متد map:
متد arr.map یکی از پرکاربردترین متدهای آرایه در جاوا اسکریپت می باشد. Map یک فانکشن را روی تمام المان های آرایه اجرا می کند و آرایه جدید را بصورت خروجی بر می گرداند.
فرمت استفاده:
let result = arr.map(function(item, index, array) { // returns the new value instead of item });
در مثال زیر می خواهیم تمام آیتم های آرایه را با طول هریک از آنها جایگزین کنیم.
let lengths = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length); alert(lengths); // 5,7,6
متد sort:
متد arr.sort می تواند المان های آرایه را در جا مرتب کند.
بعنوان مثال:
let arr = [ 1, 2, 15 ]; // the method reorders the content of arr arr.sort(); alert( arr ); // 1, 15, 2
حتما متوجه رفتار عجیب متد sort در مثال بالا شده اید. ترتیب اعداد 1,15,2 شده است که اشتباه است.
نکته: المان های آرایه بطور پیش فرض بصورت رشته ای مرتب می شوند.
یعنی المان های آرایه ابتدا به رشته تبدیل می شوند سپس با هم مقایسه می شوند. مثلا رشته “2” بزرگتر از “15” می باشد. برای اینکه متد sort بدرستی برای اعداد کار کند باید یک تابع برای متد sort فراهم کنیم. این تابع می تواند چیزی شبیه کد زیر باشد:
function compare(a, b) { if (a > b) return 1; // if the first value is greater than the second if (a == b) return 0; // if values are equal if (a < b) return -1; // if the first value is less than the second }
بنابراین برای مرتب سازی آرایه ای از اعداد داریم:
function compareNumeric(a, b) { if (a > b) return 1; if (a == b) return 0; if (a < b) return -1; } let arr = [ 1, 2, 15 ]; arr.sort(compareNumeric); alert(arr); // 1, 2, 15
الان کد بالا همانطور که می خواهیم کار خواهد کرد.
متد localeCompare:
مقایسه رشته ها را در بخش های قبلی این آموزش بخاطر دارید؟ بصورت کاراکتر به کاراکتر کد دو رشته باهم مقایسه می شود. برای مقایسه رشته ها و مرتب سازی آرایه های رشته ای توصیه می کنیم از متد str.localeCompare استفاده کنید. زیرا برای کاراکترهای ویژه مانند Ö بدرستی عمل می کند.
let countries = ['Österreich', 'Andorra', 'Vietnam']; alert( countries.sort( (a, b) => a > b ? 1 : -1) ); // Andorra, Vietnam, Österreich (wrong) alert( countries.sort( (a, b) => a.localeCompare(b) ) ); // Andorra,Österreich,Vietnam (correct!)
متد reverse:
توسط متد arr.reverse می توان ترتیب المان های آرایه را برعکس کرد. از آخر به اول.
let arr = [1, 2, 3, 4, 5]; arr.reverse(); alert( arr ); // 5,4,3,2,1
متد reverse پس از اعمال تغییرات در ترتیب المان ها، آرایه را بر می گرداند.
متد split:
فرض کنید لیستی از اسامی کاربران داریم که با علامت ویرگول از هم جدا شده اند. مثلا John, Jack, Josef و می خواهیم هر یک از نام ها را بصورت جدا داشته باشیم. توسط متد str.split(delim) می توان اینکار را براحتی انجام داد.
let names = 'Bilbo, Gandalf, Nazgul'; let arr = names.split(', '); for (let name of arr) { alert( `A message to ${name}.` ); // A message to Bilbo (and other names)
آرگومان delim همان علامت جداکننده آیتم ها می باشد. در مثال بالا، اسامی در ابتدا در یک متغیر رشته ای تعریف شده اند سپس بوسیله متد split هر یک از اسامی را در یکی از خانه های آرایه arr درج کرده ایم.
آرگومان دوم متد split اختیاری است و برای اعمال محدودیت در طول آرایه خروجی بکار می رود.
let arr = 'Bilbo, Gandalf, Nazgul, Saruman'.split(', ', 2); alert(arr); // Bilbo, Gandalf
در مثال بالا گفتیم رشته arr را توسط متد split به آرایه ای با طول 2 تبدیل کن.
نکته: اگر آرگومان اول یعنی delima را در متد split تعریف نکنیم، آرایه خروجی شامل تمام کاراکترهای رشته مبدا خواهد شد.
let str = "test"; alert( str.split('') ); // t,e,s,t
متد join:
متد arr.join(glue) کار برعکس split را انجام می دهد. یعنی آرایه را به رشته تبدیل می کند و تمام المان های آرایه را با آرگومان glue به هم می چسباند.
let arr = ['Bilbo', 'Gandalf', 'Nazgul']; let str = arr.join(';'); // glue the array into a string using ; alert( str ); // Bilbo;Gandalf;Nazgul
در مثال بالا، آیتم های آرایه arr را با علامت ; به هم متصل کرده ایم و در رشته str درج کردیم.
متدهای reduce و reduceRight:
وقتی می خواهیم روی یک آرایه حلقه اجرا کنیم می توان از متدهای for..of و for و forEach استفاده کرد.
وقتی می خواهیم روی المان های یک آرایه پیمایش کنیم و مقدار هر یک از المان ها را بر گردانیم از map استفاده می شود.
متدهای reduce و reduceRight کاری نسبتا پیچیده ای انجام می دهند. آنها بر اساس آرایه، مقداری را محاسبه کرده و بر می گردانند.
فرمت استفاده:
let value = arr.reduce(function(accumulator, item, index, array) { // ... }, [initial]);
متد reduce فانکشن بالا را روی تمام المان های آرایه اجرا کرده و نتیجه را در فراخوانی های بعدی نگه می دارد.
آرگومان های متد reduce:
- accumulator: برابر خروجی تابع در فراخوانی قبل است. اگر اولین فراخوانی باشد برابر initial خواهد بود.
- item: برابر با آیتم جاری آرایه می باشد.
- index: برابر با پوزیشن آیتم است.
- array: خود آرایه است.
نکته: آرگومان accumulator برابر با خروجی تمام اجراهای قبلی تابع می باشد و در نهایت پس از آخرین اجرای تابع، برابر با خروجی نهایی متد reduce خواهد بود.
شاید کمی پیچیده بنظر برسد. با یک مثال ساده reduce را بهتر متوجه خواهید شد:
let arr = [1, 2, 3, 4, 5]; let result = arr.reduce((sum, current) => sum + current, 0); alert(result); // 15
در این مثال reduce را با دو آرگومان فراخوانی کردیم که معمولا در بیشتر موارد همین دو آرگومان کافی هستند.
بیایید چک کنیم که در متد reduce فوق چه اتفاقاتی می افتد:
- در اجرای اول آرگومان sum برابر مقدار پیش اولیه (آخرین آرگومان متد reduce) یعنی 0 می باشد. آرگومان current برابر اولین المان آرایه یعنی 1 است. بنابراین نتیجه تابع برابر 1 خواهد شد.
- در اجرای بعدی، sum برابر 1 است و با آیتم جاری یعنی 2 جمع می شود و خروجی برابر 3 می شود.
- در اجرای بعدی، sum = 3 است و آیتم جاری هم 3 است که جمعا می شود 6 و به همین ترتیب اجرای reduce تا آخرین آیتم آرایه ادامه خواهد یافت.
خروجی مثال فوق را در جدول داریم:
نکته: اگر آرگومان آخر یعنی مقدار اولیه را تعریف نکنیم متد reduce اولین آیتم آرایه را بعنوان مقدار اولیه در نظر می گیرد و اجرای reduce از آیتم دوم شروع می شود. مثال زیر:
let arr = [1, 2, 3, 4, 5]; // removed initial value from reduce (no 0) let result = arr.reduce((sum, current) => sum + current); alert( result ); // 15
اما در استفاده از روش دوم (عدم تعریف مقدار اولیه برای reduce) باید احتیاط کنید. زیرا اگر آرایه خالی باشد اجرای تابع با خطا مواجه می شود:
let arr = []; // Error: Reduce of empty array with no initial value // if the initial value existed, reduce would return it for the empty arr. arr.reduce((sum, current) => sum + current);
متد isArray:
در جاوا اسکریپت آرایه نوع داده ای مجزای خود را ندارد. بلکه از نوع object است و اگر از typeof استفاده کنیم، مانند زیر، این موضوع مشخص می شود:
alert(typeof {}); // object alert(typeof []); // same
اما آرایه ها متد مختص خود را دارند. یعنی برای اینکه بطور مشخص بررسی کنیم آیا یک متغیر آرایه است یا خیر از متد isArray استفاده می کنیم:
alert(Array.isArray({})); // false alert(Array.isArray([])); // true
در کد بالا، دستور اول false است زیرا {} یک آبجکت است. اما دستور دوم یعنی [] یک آرایه است پس نتیجه true می شود.
در این جلسه، مفهوم آرایه و متدهای آن را در جاوا اسکریپت مورد بررسی قرار دادیم. اما برای اینکه بتوانید متدهای اصلی آرایه را بصورت ویژوال مشاهده کنید، تصویر زیر را در نظر بگیرید:
در جلسه دهم از آموزش جامع جاوا اسکریپت، ساختارهای داده ای پیچیده Set و Map را مورد بررسی قرار خواهیم داد.
دیدگاهتان را بنویسید