در طی ماههای اخیر، پی بردم که ۴ اشتباه رایج در بحثها مطرح میشد. حتی خود من هم تمام این اشتباهات را انجام میدادم. پس بیایید آنها را مرور کنیم و مطمئن شویم که از متدهای آرایه به درستی استفاده میکنیم.
جایگزینی Array.indexOf با Array.includes
به یاد دارم که در دوره یادگیری JavaScript خود، این جمله را دیدیم: «اگر به دنبال چیزی در آرایه خود میگردید، از Array.indexOf استفاده کنید.» بدون شک این جمله کاملا درست است.
Array.indexOf محلی که عنصر داده شده میتواند در آن یافته شود را بر میگرداند. پس اگر از محل برگردانده شده بعدا در کد خود استفاده کنیم، Array.indexOf راه حل ماست.
اما اگر فقط میخواهیم بدانیم که آیا آرایه ما مقداری را در خود دارد یا نه چه؟ این به نظر یک سوال بله / خیر، یا به عبارتی که سوال Boolean میآید. برای این مورد، من استفاده از Array.includes را پیشنهاد میکنم، که یک مقدار Boolean را بر میگرداند.
'use strict';
const characters = [
'ironman',
'black_widow',
'hulk',
'captain_america',
'hulk',
'thor',
];
console.log(characters.indexOf('hulk'));
// 2
console.log(characters.indexOf('batman'));
// -1
console.log(characters.includes('hulk'));
// true
console.log(characters.includes('batman'));
// false
استفاده از Array.find به جای Array.filter
Array.filter یک متد بسیار کاربردی است. این متد یک آرایه، از یک آرایه دیگر به همراه تمام آیتمهای آن میسازد. همانطور که از نامش پیداست، باید از این متد برای فیلتر کردن، و برای دریافت یک آرایه کوتاهتر استفاده کنیم.
اما اگر میدانیم که تابع callback ما فقط میتواند یک آیتم را برگرداند، آن را پیشنهاد نمیکنم. برای مثال، هنگام استفاده از یک فیلتر کردن آرگومان callback از طریق یک ID خاص. در این مورد، Array.filter یک آرایه جدید که فقط شامل یک آیتم است را بر میگرداند. با گشتن به دنبال یک ID مشخص، خواسته ما میتواند استفاده از تنها مقدار موجود در آرایه باشد، که در نتیجه باعث میشود این آرایه بی استفاده شود.
بیایید درباره کارایی صحبت کنیم. Array.filter برای برگرداندن تمام آیتمهای مطابق با تابع callback، باید کل آرایه را مرور کند. علاوه بر این، فرض کنید که صدها آیتم در آرگومان callback خود داریم. آرایه فیلتر شده ما بسیار بزرگ خواهد بود.
برای جلوگیری از این موقعیتها، استفاده از Array.find را پیشنهاد میکنم. این متد به یک آرگومان callback مانند Array.filter نیاز دارد، و مقدار اولین عنصر موجود در این callback را بر میگرداند. علاوه بر این، Array.find به محض این که یک مقدار یافت شود، متوقف میشود. پس در نتیجه نیازی به مرور کل آرایه نیست. همچنین، با استفاده از Array.find برای پیدا کردن یک آیتم، ایده واضحتری از خواسته خود میدهیم.
'use strict';
const characters = [
{ id: 1, name: 'ironman' },
{ id: 2, name: 'black_widow' },
{ id: 3, name: 'captain_america' },
{ id: 4, name: 'captain_america' },
];
function getCharacter(name) {
return character => character.name === name;
}
console.log(characters.filter(getCharacter('captain_america')));
// [
// { id: 3, name: 'captain_america' },
// { id: 4, name: 'captain_america' },
// ]
console.log(characters.find(getCharacter('captain_america')));
// { id: 3, name: 'captain_america' }
جایگزینی Array.find با Array.some
اعتراف میکنم که من هم تعداد دفعات زیادی این اشتباه را انجام دادهام. این مورد بسیار شبیه به مورد Array.indexOf / Array.includes در بالا است.
در مورد قبلی، دیدیم که Array.find به یک callback به عنوان یک آرگومان نیاز دارد و یک عنصر را بر میگرداند. آیا زمانی که میخواهیم بدانیم که یک آرایه یک مقدار را در خود دارد یا نه، Array.find بهترین راه حل است؟ احتمالا نه؛ زیرا یک مقدار را بر میگرداند، نه یک Boolean.
برای این مورد، من استفاده از Array.some را پیشنهاد میکنم که یک Boolean را بر میگرداند. همچنین استفاده از Array.some این نکته که ما به آیتم یافت شده نیازی نداریم را برجسته میکند.
'use strict';
const characters = [
{ id: 1, name: 'ironman', env: 'marvel' },
{ id: 2, name: 'black_widow', env: 'marvel' },
{ id: 3, name: 'wonder_woman', env: 'dc_comics' },
];
function hasCharacterFrom(env) {
return character => character.env === env;
}
console.log(characters.find(hasCharacterFrom('marvel')));
// { id: 1, name: 'ironman', env: 'marvel' }
console.log(characters.some(hasCharacterFrom('marvel')));
// true
استفاده از Array.reduce به جای زنجیر کردن Array.filter و Array.map
درک Array.reduce آسان نیست. اما اگر Array.filter را اجرا کنیم، در هنگام استفاده از Array.map حس میکنیم که یک نکته را جا انداختهایم.
ما در اینجا آرایه را دو بار مرور میکنیم. اولین بار برای این که آن را فیلتر کنیم و یک آرایه کوتاهتر بسازیم، دومین بار برای این که (مجددا) یک آرایه جدید بسازیم که مقادیر مورد نظر را بر حسب آنهایی که از Array.filter به دست آوردیم، در خود دارد. برای دریافت آرایه جدید خود، ما از دو متد آرایه استفاده میکنیم. هر متد تابع callback خود، و یک آرایه که ما نمیتوانیم بعدا استفاده کنیم را دارد؛ آرایهای که با استفاده از Array.filter ساختیم.
برای جلوگیری از کارایی پایین بر روی این مورد، پیشنهاد من این است که در عوض از Array.reduce استفاده کنید. با این کار همان نتیجه را با کد بهتری به دست میاورید. Array.reduce شما را قادر میسازد تا آیتمها را فیلتر کرده، و به یک مخزن اضافه کنید. به عنون مثال، این مخزن میتواند یک عدد باشد که آن را افزایش دهیم، یک آبجکت باشد که آن را پر کنیم، یا یک رشته یا آرایه باشد تا آن را concat کنیم.
در این مورد، از آنجایی که ما از Array.map استفاده میکنیم، پیشنهاد میکنم که از Array.reduce با یک آرایه استفاده کنید تا آن را به عنوان یک مخزن concat کنید. در مثال زیر، ما env را بر حسب مقدار آن به مخزن خود اضافه میکنیم، یا آن را به همان شکل رها میکنیم.
'use strict';
const characters = [
{ name: 'ironman', env: 'marvel' },
{ name: 'black_widow', env: 'marvel' },
{ name: 'wonder_woman', env: 'dc_comics' },
];
console.log(
characters
.filter(character => character.env === 'marvel')
.map(character => Object.assign({}, character, { alsoSeenIn: ['Avengers'] }))
);
// [
// { name: 'ironman', env: 'marvel', alsoSeenIn: ['Avengers'] },
// { name: 'black_widow', env: 'marvel', alsoSeenIn: ['Avengers'] }
// ]
console.log(
characters
.reduce((acc, character) => {
return character.env === 'marvel'
? acc.concat(Object.assign({}, character, { alsoSeenIn: ['Avengers'] }))
: acc;
}, [])
)
// [
// { name: 'ironman', env: 'marvel', alsoSeenIn: ['Avengers'] },
// { name: 'black_widow', env: 'marvel', alsoSeenIn: ['Avengers'] }
// ]
همین!
امیدوارم که این نکات درباره آرایهها به شما کمک کنند.
دیدگاه و پرسش
در حال دریافت نظرات از سرور، لطفا منتظر بمانید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید