آرایهها متدهای زیادی را فراهم میکنند. برای سادهسازی، در این فصل متدها به چند گروه تقسیم شدهاند.
اضافه/حذف کردن عضوها
ما از قبل متدهایی که در آغاز یا انتهای آرایه چیزی را حذف یا اضافه میکنند را میشناسیم:
arr.push(...items)
– المانها را به انتها اضافه میکند،arr.pop()
– یک المان را از انتها خارج میکند،arr.shift()
– یک المان را از آغاز خارج میکند،arr.unshift(...items)
– یک المان را به آغاز اضافه میکند.
اینجا چند متد دیگر داریم.
متد splice
چطور یک المان را از آرایه حذف کنیم؟
آرایهها شیء هستند، پس میتوانیم از delete
استفاده کنیم:
let arr = ["I", "go", "home"];
delete arr[1]; // "go" حذف
alert( arr[1] ); // undefined
// now arr = ["I", , "home"];
alert( arr.length ); // 3
المان حذف شد، اما آرایه هنوز هم 3 عضو دارد که میتوانیم آن را با arr.length == 3
ببینیم.
این چیز طبیعی است چون delete obj.key
یک مقدار را با استفاده از key
حذف میکند. به طور کلی کارش همین است. برای شیءها مناسب است. اما برای آرایهها ما معمولا میخواهیم که بقیه المانها پخش شوند و فضای آزاد شده را اشغال کنند. توقع داریم که الان آرایهای کوتاهتر داشته باشیم.
بنابراین متدهای خاص باید استفاده شوند.
متد arr.splice یک شمشیر ارتشی سوئیسی برای آرایهها است. میتواند هر کاری کند: اضافه کند، حذف کند و المانها را جایگزین کند.
سینتکس آن اینگونه است:
arr.splice(start[, deleteCount, elem1, ..., elemN])
این متد arr
را از ایندکس start
تغییر میدهد: به تعداد deleteCount
المان حذف میکند و سپس elem1, ..., elemN
را در مکان خودشان اضافه میکند. آرایهای از المانهای حذف شده را برمیگرداند.
این متد را با مثال به راحتی متوجه میشوید.
بیایید با حذف کردن شروع کنیم:
let arr = ["I", "study", "JavaScript"];
arr.splice(1, 1); // از ایندکس 1 به تعداد 1 المان حذف کن
alert( arr ); // ["I", "JavaScript"]
راحت است، نه؟ از ایندکس 1
به تعداد 1
المان حذف کرد.
در مثال بعد ما 3 المان را حذف و آنها را با دو المان جایگزین میکنیم:
let arr = ["I", "study", "JavaScript", "right", "now"];
// سه المان ابتدایی را حذف کن و آنها را با المانهای دیگر جایگزین کن
arr.splice(0, 3, "Let's", "dance");
alert( arr ) // now ["Let's", "dance", "right", "now"]
اینجا میبینیم که splice
آرایهای از المانهای حذف شده را برمیگرداند:
let arr = ["I", "study", "JavaScript", "right", "now"];
// دو المان اول را حذف کن
let removed = arr.splice(0, 2);
alert( removed ); // "I", "study" <-- array of removed elements
متد splice
همچنین قادر به اضافه کردن المان بدون هیچ حذفیاتی است. برای این کار باید deleteCount
را 0
بگذاریم:
let arr = ["I", "study", "JavaScript"];
// از ایندکس 2
// به تعداد 0 حذف کن
// را اضافه کن "language" و "complex" سپس
arr.splice(2, 0, "complex", "language");
alert( arr ); // "I", "study", "complex", "language", "JavaScript"
اینجا و در دیگر متدهای آرایه، ایندکسهای منفی قابل استفاده هستند. آنها موقعیت را از انتهای آرایه مشخص میکنند، مثل اینجا:
let arr = [1, 2, 5];
// از ایندکس 1- (یک قدم قبل از انتها)
// به تعداد 0 المان حذف کن،
// سپس 3 و 4 را اضافه کن
arr.splice(-1, 0, 3, 4);
alert( arr ); // 1,2,3,4,5
متد slice
متد arr.slice از متد arr.splice
که از لحاظ ظاهری شبیه به آن است بسیار سادهتر است.
سینتکس اینگونه است:
arr.slice([start], [end])
این متد یک آرایه جدید که تمام المانها را از ایندکس start
تا end
(شامل خود end
نمیشود) کپی میکند، برمیگرداند. start
و end
هر دو میتوانند منفی باشند، که در این صورت موقعیت از انتهای آرایه حساب میشود.
این متد شبیه متد رشته str.slice
است، اما به جای زیر رشته، زیر آرایه ایجاد میکند.
برای مثال:
let arr = ["t", "e", "s", "t"];
alert( arr.slice(1, 3) ); // e,s (کپی کردن از 1 تا 3)
alert( arr.slice(-2) ); // s,t (کپی کردن از 2- تا انتها)
همچنین میتوانیم آن را بدون آرگومان هم صدا بزنیم: arr.slice()
که یک کپی از arr
میسازد. معمولا از این روش برای ایجاد یک کپی با هدف اینکه تغییرات آینده روی آرایه اصلی تاثیری نگذارد استفاده میکنند.
متد concat
متد arr.concat یک آرایه جدید میسازد که حاوی مقدارهای آرایههای دیگر و المانهای اضافی است.
سینتکس آن اینگونه است:
arr.concat(arg1, arg2...)
این متد به هر تعدادی آرگومان میپذیرد – چه آرایه باشند چه مقدار.
نتیجه آن یک آرایه جدید حاوی المانهای arr
، سپس arg1
، arg2
و غیره.
اگر آرگومان argN
یک آرایه باشد، سپس تمام المانهای آن کپی میشود. در غیر این صورت، خود آرگومان کپی میشود.
برای مثال:
let arr = [1, 2];
// و [3,4] arr :ساخت یک آرایه از
alert( arr.concat([3, 4]) ); // 1,2,3,4
// و [3,4] و [5,6] arr :ساخت یک آرایه از
alert( arr.concat([3, 4], [5, 6]) ); // 1,2,3,4,5,6
// و [3,4]، سپس اضافه کردن مقدارهای 5 و 6 arr :ساخت یک آرایه از
alert( arr.concat([3, 4], 5, 6) ); // 1,2,3,4,5,6
به طور معمول، این متد فقط المانها را از آرایهها کپی میکند. بقیه شیءها، حتی اگر شبیه آرایه باشند، به طور کلی اضافه میشوند:
let arr = [1, 2];
let arrayLike = {
0: "something",
length: 1
};
alert( arr.concat(arrayLike) ); // 1,2,[object Object]
…اما اگر یک شیء شبیه به آرایه یک ویژگی Symbol.isConcatSpreadable
داشته باشد، سپس concat
با آن به عنوان یک آرایه رفتار میکند: در عوض المانهای آن اضافه میشوند:
let arr = [1, 2];
let arrayLike = {
0: "something",
1: "else",
[Symbol.isConcatSpreadable]: true,
length: 2
};
alert( arr.concat(arrayLike) ); // 1,2,something,else
حلقه زدن: forEach
متد arr.forEach به ما این امکان را میدهد که یک تابع را روی تمام المانهای آرایه اجرا کنیم.
سینتکس اینگونه است:
arr.forEach(function(item, index, array) {
// ... با المان کاری انجام دهید
});
برای مثال، این کد هر المان آرایه را نشان میدهد:
// را صدا بزن alert برای هر المان
["Bilbo", "Gandalf", "Nazgul"].forEach(alert);
و این کد درباره موقعیت آنها در آرایه مورد نظر جزئیات بیشتری دارد:
["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => {
alert(`${item} is at index ${index} in ${array}`);
});
نتیجه تابع (اگر چیزی برگرداند) نادیده گرفته و دور ریخته میشود.
جستجو در آرایه
حال بیایید متدهایی را بخوانیم که در آرایه جستجو میکنند.
متدهای indexOf/lastIndexOf and includes
متدهای arr.indexOf و arr.includes سینتکس مشابه دارند و اساسا همان کار همتایان خود در رشتهها را انجام میدهند، اما به جای کاراکترها با المانها کار دارند:
arr.indexOf(item, from)
– با شروع از ایندکسfrom
به دنبالitem
میگردد و ایندکسی که المان در آن پیدا شد را برمیگرداند، در غیر این صورت1-
.arr.includes(item, from)
– با شروع از ایندکسfrom
به دنبالitem
میگردد، اگر پیدا کندtrue
را برمیگرداند.
معمولا این متدها تنها با یک آرگومان استفاده میشوند: المانی (item
) که جستجو برای آن انجام میشود. به طور پیشفرض، جستجو از ابتدا انجام میشود.
برای مثال:
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
توجه داشته باشید که متدها از مقایسه ===
استفاده میکنند. پس اگر ما به دنبال false
باشیم، متد دقیقا false
را پیدا میکند و نه صفر را.
اگر ما بخواهیم بررسی کنیم که item
درون آرایه وجود دارد یا نه و به دنبال ایندکس دقیق نیستیم، پس arr.includes
ترجیح داده میشود.
متد arr.lastIndexOf مانند indexOf
است اما از راست به چپ جستجو میکند.
let fruits = ['Apple', 'Orange', 'Apple']
alert( arr.indexOf('Apple') ); // 0 (Apple اولین)
alert( arr.lastIndexOf('Apple') ); // 2 (Apple آخرین)
````smart header="متد `includes` مقدار `NaN` را به درستی مدیریت میکند"
یک تفاوت بسیار کوچک `includes` این است که این متد به درستی `NaN` را کنترل میکند، درست برعکس `indexOf`:
```js run
const arr = [NaN];
alert( arr.indexOf(NaN) ); // -1 (اشتباه است، باید 0 باشد)
alert( arr.includes(NaN) );// true (درست است)
به این دلیل که includes
بسیار بعدتر به جاوااسکریپت اضافه شد و از درون از الگوریتمهای مقایسه بروزتری استفاده میکند.
### متدهای find و findIndex/findLastIndex
تصور کنید که یک آرایهای از شیءها داریم. چگونه باید یک شیء با شرطی مشخص را پیدا کنیم؟
اینجاست که متد [arr.find(fn)](mdn:js/Array/find) بدرد میخورد.
سینتکس آن اینگونه است:
```js
let result = arr.find(function(item, index, array) {
// برگردانده شود، المان برگردانده میشود و حلقهی تکرار متوقف میشود true اگر مقدار
// برگردانده میشود undefined مقدار falsy برای سناریوهای
});
```
تابع برای المانهای آرایه، یکی پس از دیگری، صدا زده میشود:
- `item` المان است.
- `index` ایندکس آن است.
- `array` خود آرایه است.
اگر `true` برگرداند، جستجو متوقف میشود، `item` برگردانده میشود. اگر چیزی پیدا نشود، `undefined` برگردانده میشود.
برای مثال، ما یک آرایهای از کاربران داریم، که هر کدام دارای `id` و `name` هستند. بیایید کاربری که `id == 1` داشته باشد را پیدا کنیم:
```js run
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` بسیار مفید است.
توجه داشته باشید که در مثال بالا ما تابع `item => item.id == 1` را همراه با یک آرگومان برای `find` در نظر گرفتیم. این چیز معمولی است، بقیه آرگومانهای این تابع به ندرت استفاده میشوند.
متد [arr.findIndex](mdn:js/Array/findIndex) سینتکس یکسانی دارد اما به جای خود المان ایندکسی که المان در آن پیدا شد را برمیگرداند. اگر چیزی پیدا نشد مقدار `1-` برگردانده میشود.
متد [arr.findLastIndex](mdn:js/Array/findLastIndex) مانند `findIndex` است اما مانند `lastIndexOf` از راست به چپ جستجو میکند.
اینجا یک مثال داریم:
```js run
let users = [
{id: 1, name: "John"},
{id: 2, name: "Pete"},
{id: 3, name: "Mary"},
{id: 4, name: "John"}
];
// را پیدا کن John ایندکس اولین
alert(users.findIndex(user => user.name == 'John')); // 0
// را پیدا کن John ایندکس آخرین
alert(users.findLastIndex(user => user.name == 'John')); // 3
```
### متد filter
متد `find` برای یک (اولین) المان که باعث شود تابع `true` برگرداند، جستجو میکند.
اگر ممکن باشد تعداد بیشتری موجود باشند، میتوانیم از [arr.filter(fn)](mdn:js/Array/filter) استفاده کنیم.
سینتکس آن مشابه `find` است اما `filter` یک آرایه از المانهای منطبق را برمیگرداند:
```js
let results = arr.filter(function(item, index, array) {
// باشد المان به نتیجهها اضافه میشود و حلقه تکرار ادامه پیدا میکند true اگر
// اگر چیزی پیدا نشود یک آرایه خالی برمیگرداند
});
```
برای مثال:
```js run
let users = [
{id: 1, name: "John"},
{id: 2, name: "Pete"},
{id: 3, name: "Mary"}
];
// آرایه شامل دو کاربر اول را برمیگرداند
let someUsers = users.filter(item => item.id < 3);
alert(someUsers.length); // 2
```
## تغییر شکل دادن آرایه
بیایید به سراغ متدهایی برویم که یک آرایه را تغییر شکل و نظم دوباره میدهند.
### متد map
متد [arr.map](mdn:js/Array/map) یکی از پرکاربردترین و متدوالترین متدهاست.
این متد یک تابع را برای هر المان آرایه صدا میزند و آرایهای از نتیجه را برمیگرداند.
سینتکس آن اینگونه است:
```js
let result = arr.map(function(item, index, array) {
// به جای المان، مقدار جدید را برمیگرداند
});
```
برای مثال، ما هر المان را به طول آن تغییر میدهیم:
```js run
let lengths = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length);
alert(lengths); // 5,7,6
```
### متد sort(fn)
صدازدن [arr.sort()](mdn:js/Array/sort) آرایه را *در محل* با تغییر دادن ترتیب المانها، مرتب میکند.
همچنین این متد آرایه مرتب شده را برمیگرداند، اما همانطور که خود `arr` تغییر داده میشود، مقدار برگردانده شده معمولا نادیده گرفته میشود.
برای مثال:
```js run
let arr = [ 1, 2, 15 ];
// را دوباره ترتیب بندی میکند arr این متد
arr.sort();
alert( arr ); // 1, 15, 2
```
چیز عجیبی را در نتیجه متوجه شدید؟
ترتیب المانها `1, 15, 2` شد. این اشتباه است. اما چرا؟
**المانها به صورت پیشفرض به عنوان رشته مرتب میشوند.**
به طور کلی، تمام المانها برای انجام مقایسه به رشته تبدیل میشوند. برای رشتهها، ترتیببندی لفتنامهای اعمال میشود و در این صورت `"2" > "15"` است.
برای استفاده از ترتیببندی خودمان، ما نیاز داریم که یک تابع را به عنوان آرگومان `arr.sort()` قرار دهیم.
تابع باید دو مقدار دلخواه را مقایسه کند و چیزی را برگرداند:
```js
function compare(a, b) {
if (a > b) return 1; // اگر مقدار اول بزرگتر از دومی باشد
if (a == b) return 0; // اگر مقدارها برابر باشند
if (a < b) return -1; // اگر مقدار اول کمتر از دومی باشد
}
```
برای مثال، برای مرتب کردن به عنوان اعداد:
```js run
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
```
حالا همانطور که انتظار میرفت کار میکند.
بیایید کمی عقب بمانیم و ببینیم چه چیزی در حال اتفاق افتادن است. `arr` میتواند آرایهای از هر چیزی باشد نه؟ ممکن است شامل اعداد یا رشتهها یا شیءها یا هرچیز دیگری باشد. ما دستهای از *چیزها* داریم. برای مرتب کردن آن، ما به یک *تابع مرتبکننده* که میداند چگونه المانهای دسته را مقایسه کند، نیاز داریم. ترتیب رشتهای پیشفرض است.
متد `arr.sort(fn)` یک الگوریتم مرتبسازی کلی را پیادهسازی میکند. ما نیازی نداریم که بدانیم درون آن چه اتفاقی میافتد (اکثر اوقات از یک [مرتبسازی سریع](https://fa.wikipedia.org/wiki/مرتب%E2%80%8Cسازی_سریع) یا [Timsort](https://fa.wikipedia.org/wiki/مرتب%E2%80%8Cسازی_تیم) بهینهشده استفاده میشود). این متد آرایه را طی میکند، المانهای آن را با استفاده از تابع فراهم شده مقایسه میکند و آنها را مرتب میکند، تمام آن چیزی که ما نیاز داریم این است که یک `fn` فراهم کنیم که مقایسه را انجام دهد.
راستی، اگر ما بخواهیم بدانیم که کدام المانها مقایسه میشوند -- چیزی ما را از alert کردن آنها متوقف نمیکند:
```js run
[1, -2, 15, 2, 0, 8].sort(function(a, b) {
alert( a + " <> " + b );
return a - b;
});
```
الگوریتم ممکن است یک المان را با چند المان دیگر در حین فرایند مقایسه کند، اما تلاش میکند که تا جایی که میتواند مقایسههای کمی انجام دهد.
````smart header="یک تابع مقایسه میتواند هر عددی برگرداند"
در واقع یک تابع مقایسه فقط نیاز دارد که یک عدد مثبت را برای اینکه بگوید «بزرگتر» است برگرداند و یک عدد منفی را برای گفتن «کمتر» است.
این ویژگی سبب میشود که تابعهای کوتاهتری نوشته شود:
```js run
let arr = [ 1, 2, 15 ];
arr.sort(function(a, b) { return a - b; });
alert(arr); // 1, 2, 15
```
تابعهای پیکانی را به یاد دارید؟ ما میتوانیم از آنها برای مرتبسازی تمیزتر استفاده کنیم:
arr.sort( (a, b) => a - b );
این کد دقیقا مانند نسخه طولانیتر بالایی کار میکند.
localeCompare
استفاده کنیدالگوریتم مقایسه رشتهها را به یاد دارید؟ این الگوریتم به صورت پیشفرض حروف را با کدهای آنها مقایسه میکند.
برای بساری از حروف الفبا، بهتر است از متد str.localeCompare
برای مرتبکردن صحیح حروف استفاده شود، مانند Ö
.
برای مثال، بیایید چند کشور را به زبان آلمانی مرتب کنیم:
let countries = ['Österreich', 'Andorra', 'Vietnam'];
alert( countries.sort( (a, b) => a > b ? 1 : -1) ); // Andorra, Vietnam, Österreich (اشتباه است)
alert( countries.sort( (a, b) => a.localeCompare(b) ) ); // Andorra,Österreich,Vietnam (درست است!)
متد reverse
متد arr.reverse ترتیب المانها را arr
برعکس میکند.
برای مثال:
let arr = [1, 2, 3, 4, 5];
arr.reverse();
alert( arr ); // 5,4,3,2,1
همچنین این متد ارایه arr
را بعد از برعکس شدن برمیگرداند.
متدهای split and join
یک موقعیت در زندگی واقعی را میگوییم. ما در حال نوشتن یک برنامه پیامرسان هستیم و شخص لیستی از دریافت کنندگان که با کاما جدا شدهاند را وارد میکند: John, Pete, Mary
. اما یک آرایهای از اسمها بسیار راحتتر از یک رشته خواهد بود. چگونه آن را دریافت کنیم؟
متد str.split(delim) دقیقا همین کار را انجام میدهد. این متد رشته را با استفاده از جداکنندهی داده شده delim
به یک آرایه تقسیم میکند.
در مثال بالا، ما توسط یک کاما که بعد آن space میآید رشته را جدا میکنیم:
let names = 'Bilbo, Gandalf, Nazgul';
let arr = names.split(', ');
for (let name of arr) {
alert( `A message to ${name}.` ); // A message to Bilbo (و بقیه اسمها)
}
متد split
یک آرگومان اختیاری دوم هم دارد – یک محدودیت برای طول آرایه. اگر این آرگومان اضافه شود، سپس المانهای دیگر نادیده گرفته میشوند. گرچه در عمل به ندرت استفاده میشود:
let arr = 'Bilbo, Gandalf, Nazgul, Saruman'.split(', ', 2);
alert(arr); // Bilbo, Gandalf
صدا زدن split(s)
با یک s
خالی رشته را به آرایهای از حروف جدا میکند:
let str = "test";
alert( str.split('') ); // t,e,s,t
صدا زدن arr.join(glue) عمل برعکس split
را انجام میهد. این متد یک رشته از arr
میسازد که توسط glue
المانها متصل شدهاند.
برای مثال:
let arr = ['Bilbo', 'Gandalf', 'Nazgul'];
let str = arr.join(';'); // آرایه را با استفاده از ; به یک رشته تبدیل کنید
alert( str ); // Bilbo;Gandalf;Nazgul
متد reduce/reduceRight
زمانی که ما نیاز داشته باشیم که در یک آرایه حلقه بزنیم، میتوانیم از forEach
، for
یا for..of
استفاده کنیم.
زمانی که ما نیاز داشته باشیم در المانها حلقه بزنیم و داده را برای هر المان برگردانیم، میتوانیم از map
استفاده کنیم.
متدهای arr.reduce و arr.reduceRight همچنین به این دسته تعلق دارند، اما کمی پیچیدهتر هستند. آنها برای محاسبه یک مقدار بر اساس آرایه، استفاده میشوند.
سینتکس اینگونه است:
let value = arr.reduce(function(accumulator, item, index, array) {
// ...
}, [initial]);
تابع روی تمام المانهای آرایه اعمال میشود و نتیجه خود را به فراخوانی بعدی «منتقل میکند».
آرگومانها:
accumulator
– نتیجه قبلی فراخوانی تابع است، دفعه اول باinitial
برابر است (اگرinitial
وجود داشته باشد).item
– المان کنونی آرایه است.index
– موقعیت آن است.array
– آرایه است.
همانطور که تابع اعمال میشود، نتیجه فراخوانی قبلی به عنوان آرگومان اول به فراخوانی بعدی منتقل میشود.
بنابراین، اولین آرگومان اساسا همان حافظهای است که نتیجه ترکیب شده تمام فراخوانیهای قبلی را ذخیره کرده است. و در پایان تبدیل به نتیجه reduce
میشود.
بنظر پیچیده میآید؟
راحتترین راه برای فهمیدن این قضیه، توسط مثال است.
اینجا ما حاصل جمع یک آرایه را در یک خط میگیریم:
let arr = [1, 2, 3, 4, 5];
let result = arr.reduce((sum, current) => sum + current, 0);
alert(result); // 15
تابعی که به reduce
داده شد تنها از 2 آرگومان استفاده میکند که معمولا کافی است.
بیایید جزئیات چیزی که در حال انجام است را ببینیم.
- در اجرای اول،
sum
برابر با مقدارinitial
است (آخرین آرگومانreduce
)، که برابر با0
است، وcurrent
اولین المان آرایه است، که برابر با1
است. پس نتیجه تابع1
است. - در اجرای دوم،
sum = 1
، که ما المان دوم آرایه (2
) را به آن اضافه و برمیگردانیم. - در اجرای سوم،
sum = 3
و ما یک المان دیگر به آن اضافه میکنیم و…
گردش محاسبه:
یا به شکل یک جدول که هر ردیف نشاندهنده یک فراخوانی تابع روی المان بعدی آرایه است:
sum |
current |
نتیجه | |
---|---|---|---|
فراخوانی اول | 0 |
1 |
1 |
فراخوانی دوم | 1 |
2 |
3 |
فراخوانی سوم | 3 |
3 |
6 |
فراخوانی چهارم | 6 |
4 |
10 |
فراخوانی پنجم | 10 |
5 |
15 |
اینجا ما میتوانیم به صورت شفاف ببینیم که نتیجه فراخوانی قبلی به اولین آرگومان فراخوانی بعدی تبدیل میشود.
ما همچنین میتوانیم مقدار اولیه را حذف کنیم:
let arr = [1, 2, 3, 4, 5];
// حذف شد (بدون 0) reduce مقدار اولیه از
let result = arr.reduce((sum, current) => sum + current);
alert( result ); // 15
نتیجه یکسان است. به دلیل اینکه اگر مقدار اولیهای وجود نداشته باشد، سپس reduce
اولین المان آرایه را به عنوان مقدار اولیه انتخاب میکند و حلقهزدن را از دومین المان شروع میکند.
جدول محاسبات مانند بالا است، منتها ردیف اول را ندارد.
اما استفاده کردن به این صورت به دقت بسیار بالایی نیاز دارد. اگر آرایه خالی باشد، سپس فراخوانی reduce
بدون مقدار اولیه ارور میدهد.
یک مثال اینجا داریم:
let arr = [];
// Error: Reduce of empty array with no initial value
// .آن را برای آرایه خالی برمیگرداند reduce ،اگر مقدار اولیه وجود داشت
arr.reduce((sum, current) => sum + current);
بنابراین توصیه میشود همیشه مقدار اولیه را تعیین کنید.
متد arr.reduceRight کار یکسان را انجام میهد، اما از راست به چپ.
##متد Array.isArray
آرایهها شکل جدیدی از انواع داده را شکل نمیدهند. آنها بر اساس شیءها هستند.
بنابراین typeof
برای تشخیص یک شیء ساده از آرایه کمکی نمیکند:
alert(typeof {}); // object
alert(typeof []); // object (یکسان)
…اما آرایهها به دلیل اینکه اغلب اوقات استفاده میشوند، یک متد خاص برای این کار دارند: Array.isArray(value). این متد اگر value
یک آرایه باشد true
برمیگرداند و در غیر این صورت false
.
alert(Array.isArray({})); // false
alert(Array.isArray([])); // true
اکثر متدها از “thisArg” پشتیبانی میکنند
تقریبا تمام متدهای آرایه که تابعی را صدا میزنند – مانند find
، filter
، map
، همچنین یک استثنا از sort
، پارامتر اختیاری اضافی thisArg
را قبول میکنند.
این پارامتر به دلیل اینکه به ندرت استفاده میشود، در قسمتهای بالایی گفته نشد. اما برای کامل بودن ما باید آن را پوشش دهیم.
سینتکس کامل این متدها در زیر آمده است:
arr.find(func, thisArg);
arr.filter(func, thisArg);
arr.map(func, thisArg);
// ...
// آرگومان اختیاری آخر است thisArg
مقدار thisArg
برای func
برابر با this
خواهد بود.
برای مثال، اینجا ما از متد شیء army
به عنوان یک فیلتر استفاده میکنیم، و thisArg
محتوا را رد و بدل میکند:
let army = {
minAge: 18,
maxAge: 27,
canJoin(user) {
return user.age >= this.minAge && user.age < this.maxAge;
}
};
let users = [
{age: 16},
{age: 20},
{age: 23},
{age: 30}
];
// برمیگرداند را پیدا کن true به ازای آنها army.canJoin هایی کهuser
let soldiers = users.filter(army.canJoin, army);
alert(soldiers.length); // 2
alert(soldiers[0].age); // 20
alert(soldiers[1].age); // 23
اگر در مثال بالا ما از users.filter(army.canJoin)
استفاده میکردیم، سپس army.canJoin
به عنوان یک تابع جداگانه صدا زده میشد که this=undefined
، بنابراین درجا به یک ارور برمیخوردیم.
صدازدن users.filter(army.canJoin, army)
میتواند با users.filter(user => army.canJoin(user))
جایگزین شود، که هردو یکسان هستند. نوع دوم بیشتر استفاده میشود، چون برای اکثر مردم مقداری قابل فهمتر است.
خلاصه
برگ تقلبی از متدهای آرایه:
-
برای اضافه/حذف کردن المانها:
push(...items)
– المانها را به آخر اضافه میکند،pop()
– یک المان را از آخر حذف میکند،shift()
– یک المان را از آغاز حذف میکند،unshift(...items)
– المانهایی را به آغاز اضافه میکند.splice(pos, deleteCount, ...items)
– در ایندکسpos
به تعدادdeleteCount
المان حذف وitems
را اضافه میکند.slice(start, end)
– با ساختن یک آرایه جدید، المانها را از ایندکسstart
تاend
(شامل نمیشود) در آن کپی میکند.concat(...items)
– یک آرایه جدید را برمیگرداند: تمام عضوهای آرایه کنونی را کپی میکند وitems
را به آن اضافه میکند. اگر هر کدام ازitems
آرایه باشد، سپس المانهای آن اضافه میشوند.
-
برای جستجو در بین المانها:
indexOf/lastIndexOf(item, pos)
– با شروع از موقعیتpos
به دنبالitem
میگردد، ایندکس آن را برمیگرداند و در صورتی که پیدا نشود1-
را برمیگرداند.includes(value)
– اگر آرایه دارایvalue
باشد، مقدارtrue
را برمیگرداند در غیر این صورتfalse
.find/filter(func)
– المانها را از طریق تابع فیلتر میکند، اولین/تمام مقدارهایی که سبب میشوند تابعtrue
برگرداند را برمیگرداند.findIndex
مانندfind
است اما به جای مقدار ایندکس را برمیگرداند.
-
برای حلقه زدن در یک آرایه:
forEach(func)
– برای تمام المانها تابعfunc
را صدا میزند، چیزی را برنمیگرداند.
-
برای تغییر شکل یک آرایه:
map(func)
– از نتایج صدازدنfunc
برای هر المان، یک آرایه جدید میسازد.sort(func)
– آرایه را در محل مرتب میکند، سپس آن را برمیگرداند.reverse()
– آرایه را در محل برعکس میکند، سپس آن را برمیگرداند.split/join
– یک رشته را به آرایه تبدیل میکند و برعکس.reduce/reduceRight(func, initial)
– با صدا زدنfunc
برای هر المان و رد و بدل کردن یک نتیجه واسطه بین هر فراخوانی، یک مقدار مفرد را در آرایه محاسبه میکند.
-
علاوه بر این:
Array.isArray(arr)
بررسی میکند کهarr
یک آرایه باشد و اگر بود مقدارtrue
را برمیگرداند در غیر این صورتfalse
.
لطفا در نظر داشته باشید که متدهای sort
، reverse
و splice
خود آرایه را تغییر میدهند.
متدهای ذکر شده بیشترین استفاده را دارند، آنها 99% موارد استفاده را پوشش میدهند. اما چند متد دیگر هم هست:
-
arr.some(fn)/arr.every(fn) آرایه را بررسی میکنند.
تابع
fn
رو تمام المانهای آرایه صدا زده میشود درست شبیهmap
. اگر تمام نتایجtrue
بود، مقدارtrue
را برمیگرداند، در غیر این صورتfalse
.این متدها تقریبا شبیه عملگرهای
||
و&&
رفتار میکنند: اگرfn
مقدار truthy را برگرداند،arr.some()
درجاtrue
را برمیگرداند و حلقه زدن روی بقیه المانها را متوقف میکند؛ اگرfn
یک مقدار falsy برگرداند،arr.every()
فوراfalse
را برمیگرداند و حلقه زدن در بقیه المانها را متوقف میکند.ما میتوانیم از
every
برای مقایسه آرایهها استفاده کنیمfunction arraysEqual(arr1, arr2) { return arr1.length === arr2.length && arr1.every((value, index) => value === arr2[index]); } alert( arraysEqual([1, 2], [1, 2])); // true
-
arr.fill(value, start, end) – آرایه را با مقدار تکرار شونده
value
از ایندکسstart
تاend
پر میکند. -
arr.copyWithin(target, start, end) – المانهای خود را از موقعیت
start
تا موقعیتend
در خودش و در موقعیتtarget
کپی میکند (جایگزین المان موجود میشود). -
arr.flat(depth)/arr.flatMap(fn) آرایهای یک دست را از آرایهای چند بعدی میسازند.
برای دیدن لیست کامل، از راهنما استفاده کنید.
با اولین نگاه ممکن است به نظر برسد که متدهای بسیار زیادی وجود دارد و به حافظه سپردن آنها مشکل است. اما در واقع بسیار آسانتر است.
برای داشتن شناخت از آنها به برگه تقلب نگاه بیاندازید. سپس تکلیفهای این فصل را برای تمرین انجام دهید تا نسبت به متدهای آرایه تجربه بدست بیاورید.
پس از آن هر موقع که نیاز داشتید با یک آرایه کاری انجام دهید، و نمیدانید چگونه، به این صفحه بیایید، به برگه تقلب نگاهی بیاندازید و متد مناسب را پیدا کنید. مثالها به شما در نوشتن درست آن کمک میکنند. به زودی به طور خودکار شما متدها را به حافظه میسپارید، بدون تلاش خاصی از جانب خودتان.