Latviešu

Atklājiet funkcionālās programmēšanas spēku ar JavaScript masīviem. Apgūstiet, kā efektīvi transformēt, filtrēt un samazināt datus, izmantojot iebūvētās metodes.

Funkcionālās programmēšanas apguve ar JavaScript masīviem

Tīmekļa izstrādes ainavā, kas nepārtraukti attīstās, JavaScript joprojām ir stūrakmens. Lai gan objektorientētās un imperatīvās programmēšanas paradigmas ilgu laiku ir dominējušas, funkcionālā programmēšana (FP) iegūst ievērojamu popularitāti. FP uzsver nemainību, tīras funkcijas un deklaratīvu kodu, tādējādi radot robustākas, vieglāk uzturamas un prognozējamākas lietojumprogrammas. Viens no spēcīgākajiem veidiem, kā ieviest funkcionālo programmēšanu JavaScript, ir izmantot tās vietējās masīvu metodes.

Šis visaptverošais ceļvedis aplūkos, kā izmantot funkcionālās programmēšanas principus, lietojot JavaScript masīvus. Mēs izpētīsim galvenās koncepcijas un demonstrēsim, kā tās pielietot, izmantojot tādas metodes kā map, filter un reduce, mainot veidu, kā jūs apstrādājat datu manipulācijas.

Kas ir funkcionālā programmēšana?

Pirms iedziļināties JavaScript masīvos, īsi definēsim funkcionālo programmēšanu. Tās pamatā FP ir programmēšanas paradigma, kas aprēķinu uzskata par matemātisko funkciju novērtēšanu un izvairās no stāvokļa un mainīgu datu maiņas. Galvenie principi ietver:

Šo principu pieņemšana var novest pie koda, ko ir vieglāk analizēt, testēt un atkļūdot, īpaši sarežģītās lietojumprogrammās. JavaScript masīvu metodes ir lieliski piemērotas šo koncepciju ieviešanai.

JavaScript masīvu metožu spēks

JavaScript masīvi ir aprīkoti ar plašu iebūvētu metožu kopumu, kas ļauj veikt sarežģītas datu manipulācijas, neizmantojot tradicionālās cilpas (piemēram, for vai while). Šīs metodes bieži atgriež jaunus masīvus, veicinot nemainību, un pieņem atzvanīšanas funkcijas, nodrošinot funkcionālu pieeju.

Izpētīsim visfundamentālākās funkcionālās masīvu metodes:

1. Array.prototype.map()

Metode map() izveido jaunu masīvu, kas aizpildīts ar rezultātiem, ko iegūst, izsaucot norādīto funkciju katram elementam izsaucošajā masīvā. Tā ir ideāli piemērota katra masīva elementa pārveidošanai par kaut ko jaunu.

Sintakse:

array.map(callback(currentValue[, index[, array]])[, thisArg])

Galvenās iezīmes:

Piemērs: Katra skaitļa dubultošana

Iedomājieties, ka jums ir skaitļu masīvs un vēlaties izveidot jaunu masīvu, kurā katrs skaitlis ir dubultots.

const numbers = [1, 2, 3, 4, 5];

// Izmantojot map transformācijai
const doubledNumbers = numbers.map(number => number * 2);

console.log(numbers); // Izvade: [1, 2, 3, 4, 5] (oriģinālais masīvs ir nemainīgs)
console.log(doubledNumbers); // Izvade: [2, 4, 6, 8, 10]

Piemērs: Īpašību izgūšana no objektiem

Bieži sastopams lietošanas gadījums ir specifisku īpašību izgūšana no objektu masīva. Pieņemsim, ka mums ir lietotāju saraksts un vēlamies iegūt tikai viņu vārdus.

const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 3, name: 'Charlie' }
];

const userNames = users.map(user => user.name);

console.log(userNames); // Izvade: ['Alice', 'Bob', 'Charlie']

2. Array.prototype.filter()

Metode filter() izveido jaunu masīvu ar visiem elementiem, kas iztur pārbaudi, ko veic norādītā funkcija. Tā tiek izmantota elementu atlasīšanai, pamatojoties uz nosacījumu.

Sintakse:

array.filter(callback(element[, index[, array]])[, thisArg])

Galvenās iezīmes:

Piemērs: Pāru skaitļu filtrēšana

Filtrēsim skaitļu masīvu, lai paturētu tikai pāra skaitļus.

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Izmantojot filter pāra skaitļu atlasei
const evenNumbers = numbers.filter(number => number % 2 === 0);

console.log(numbers); // Izvade: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(evenNumbers); // Izvade: [2, 4, 6, 8, 10]

Piemērs: Aktīvo lietotāju filtrēšana

No mūsu lietotāju masīva filtrēsim lietotājus, kuri ir atzīmēti kā aktīvi.

const users = [
  { id: 1, name: 'Alice', isActive: true },
  { id: 2, name: 'Bob', isActive: false },
  { id: 3, name: 'Charlie', isActive: true },
  { id: 4, name: 'David', isActive: false }
];

const activeUsers = users.filter(user => user.isActive);

console.log(activeUsers); 
/* Izvade:
[
  { id: 1, name: 'Alice', isActive: true },
  { id: 3, name: 'Charlie', isActive: true }
]
*/

3. Array.prototype.reduce()

Metode reduce() izpilda lietotāja nodrošinātu “reducer” atzvanīšanas funkciju katram masīva elementam secīgi, nododot atgriezto vērtību no aprēķina iepriekšējam elementam. Reducera darbības beigu rezultāts visiem masīva elementiem ir viena vērtība.

Šī ir, iespējams, vispusīgākā no masīvu metodēm un ir daudzu funkcionālās programmēšanas modeļu stūrakmens, ļaujot “samazināt” masīvu līdz vienai vērtībai (piemēram, summai, reizinājumam, skaitam vai pat jaunam objektam vai masīvam).

Sintakse:

array.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

Galvenās iezīmes:

Piemērs: Skaitļu summēšana

Sasummēsim visus skaitļus mūsu masīvā.

const numbers = [1, 2, 3, 4, 5];

// Izmantojot reduce skaitļu summēšanai
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0); // 0 ir initialValue

console.log(sum); // Izvade: 15

Paskaidrojums:

Piemērs: Objektu grupēšana pēc īpašības

Mēs varam izmantot reduce, lai pārveidotu objektu masīvu par objektu, kurā vērtības ir grupētas pēc noteiktas īpašības. Grupēsim mūsu lietotājus pēc viņu `isActive` statusa.

const users = [
  { id: 1, name: 'Alice', isActive: true },
  { id: 2, name: 'Bob', isActive: false },
  { id: 3, name: 'Charlie', isActive: true },
  { id: 4, name: 'David', isActive: false }
];

const groupedUsers = users.reduce((acc, user) => {
  const status = user.isActive ? 'active' : 'inactive';
  if (!acc[status]) {
    acc[status] = [];
  }
  acc[status].push(user);
  return acc;
}, {}); // Tukšs objekts {} ir initialValue

console.log(groupedUsers);
/* Izvade:
{
  active: [
    { id: 1, name: 'Alice', isActive: true },
    { id: 3, name: 'Charlie', isActive: true }
  ],
  inactive: [
    { id: 2, name: 'Bob', isActive: false },
    { id: 4, name: 'David', isActive: false }
  ]
}
*/

Piemērs: Gadījumu skaitīšana

Saskaitīsim katra augļa biežumu sarakstā.

const fruits = ['apple', 'banana', 'apple', 'orange', 'banana', 'apple'];

const fruitCounts = fruits.reduce((acc, fruit) => {
  acc[fruit] = (acc[fruit] || 0) + 1;
  return acc;
}, {});

console.log(fruitCounts); // Izvade: { apple: 3, banana: 2, orange: 1 }

4. Array.prototype.forEach()

Lai gan forEach() neatgriež jaunu masīvu un bieži tiek uzskatīta par imperatīvāku, jo tās galvenais mērķis ir izpildīt funkciju katram masīva elementam, tā joprojām ir fundamentāla metode, kas spēlē lomu funkcionālajās paradigmās, īpaši, ja nepieciešami blakusefekti vai ja tiek iterēts bez transformētas izvades nepieciešamības.

Sintakse:

array.forEach(callback(element[, index[, array]])[, thisArg])

Galvenās iezīmes:

Piemērs: Katra elementa reģistrēšana

const messages = ['Hello', 'Functional', 'World'];

messages.forEach(message => console.log(message));
// Izvade:
// Hello
// Functional
// World

Piezīme: Transformācijām un filtrēšanai, map un filter ir vēlams to nemainības un deklaratīvās dabas dēļ. Izmantojiet forEach, ja jums ir īpaši jāveic darbība katrai precei, neapkopojot rezultātus jaunā struktūrā.

5. Array.prototype.find() un Array.prototype.findIndex()

Šīs metodes ir noderīgas, lai atrastu specifiskus elementus masīvā.

Piemērs: Lietotāja atrašana

const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 3, name: 'Charlie' }
];

const bob = users.find(user => user.name === 'Bob');
const bobIndex = users.findIndex(user => user.name === 'Bob');
const nonExistentUser = users.find(user => user.name === 'David');
const nonExistentIndex = users.findIndex(user => user.name === 'David');

console.log(bob); // Izvade: { id: 2, name: 'Bob' }
console.log(bobIndex); // Izvade: 1
console.log(nonExistentUser); // Izvade: undefined
console.log(nonExistentIndex); // Izvade: -1

6. Array.prototype.some() un Array.prototype.every()

Šīs metodes pārbauda, vai visi masīva elementi iztur pārbaudi, ko veic norādītā funkcija.

Piemērs: Lietotāja statusa pārbaude

const users = [
  { id: 1, name: 'Alice', isActive: true },
  { id: 2, name: 'Bob', isActive: false },
  { id: 3, name: 'Charlie', isActive: true }
];

const hasInactiveUser = users.some(user => !user.isActive);
const allAreActive = users.every(user => user.isActive);

console.log(hasInactiveUser); // Izvade: true (jo Bobs ir neaktīvs)
console.log(allAreActive); // Izvade: false (jo Bobs ir neaktīvs)

const allUsersActive = users.filter(user => user.isActive).length === users.length;
console.log(allUsersActive); // Izvade: false

// Alternatīva, tieši izmantojot every
const allUsersActiveDirect = users.every(user => user.isActive);
console.log(allUsersActiveDirect); // Izvade: false

Masīvu metožu ķēde sarežģītām darbībām

Funkcionālās programmēšanas patiesais spēks ar JavaScript masīviem parādās, ja jūs šīs metodes savienojat kopā. Tā kā lielākā daļa šo metožu atgriež jaunus masīvus (izņemot forEach), jūs varat nemanāmi nodot vienas metodes izvadi citas ievadei, radot elegantus un salasāmus datu cauruļvadus.

Piemērs: Aktīvo lietotāju vārdu atrašana un viņu ID dubultošana

Atrodim visus aktīvos lietotājus, izgūstam viņu vārdus un pēc tam izveidojam jaunu masīvu, kurā katrs vārds ir priekšā ar numuru, kas atspoguļo tā indeksu *filtrētajā* sarakstā, un viņu ID ir dubultoti.

const users = [
  { id: 1, name: 'Alice', isActive: true },
  { id: 2, name: 'Bob', isActive: false },
  { id: 3, name: 'Charlie', isActive: true },
  { id: 4, name: 'David', isActive: true },
  { id: 5, name: 'Eve', isActive: false }
];

const processedActiveUsers = users
  .filter(user => user.isActive) // Iegūst tikai aktīvos lietotājus
  .map((user, index) => ({      // Pārveido katru aktīvo lietotāju
    name: `${index + 1}. ${user.name}`,
    doubledId: user.id * 2
  }));

console.log(processedActiveUsers);
/* Izvade:
[
  { name: '1. Alice', doubledId: 2 },
  { name: '2. Charlie', doubledId: 6 },
  { name: '3. David', doubledId: 8 }
]
*/

Šī ķēdes pieeja ir deklaratīva: mēs norādām soļus (filtrēt, tad kartēt) bez skaidras cilpu pārvaldības. Tā ir arī nemainīga, jo katrs solis rada jaunu masīvu vai objektu, atstājot oriģinālo users masīvu neskartu.

Nemainība praksē

Funkcionālā programmēšana lielā mērā balstās uz nemainību. Tas nozīmē, ka esošo datu struktūru modificēšanas vietā jūs izveidojat jaunas ar vēlamajām izmaiņām. JavaScript masīvu metodes, piemēram, map, filter un slice, dabiski atbalsta to, atgriežot jaunus masīvus.

Kāpēc nemainība ir svarīga?

Ja jums ir jāveic darbība, kas tradicionāli mutētu masīvu (piemēram, elementa pievienošana vai noņemšana), jūs varat panākt nemainību, izmantojot tādas metodes kā slice, izklājuma sintakse (...) vai apvienojot citas funkcionālās metodes.

Piemērs: Elementa pievienošana nemainīgi

const originalArray = [1, 2, 3];

// Imperatīvais veids (modificē originalArray)
// originalArray.push(4);

// Funkcionālais veids, izmantojot izklājuma sintaksi
const newArrayWithPush = [...originalArray, 4];
console.log(originalArray); // Izvade: [1, 2, 3]
console.log(newArrayWithPush); // Izvade: [1, 2, 3, 4]

// Funkcionālais veids, izmantojot slice un savienošanu (tagad retāk sastopams)
const newArrayWithSlice = originalArray.slice(0, originalArray.length).concat(4);
console.log(newArrayWithSlice); // Izvade: [1, 2, 3, 4]

Piemērs: Elementa noņemšana nemainīgi

const originalArray = [1, 2, 3, 4, 5];

// Noņemt elementu ar indeksu 2 (vērtība 3)

// Funkcionālais veids, izmantojot slice un izklājuma sintaksi
const newArrayAfterSplice = [
  ...originalArray.slice(0, 2),
  ...originalArray.slice(3)
];
console.log(originalArray); // Izvade: [1, 2, 3, 4, 5]
console.log(newArrayAfterSplice); // Izvade: [1, 2, 4, 5]

// Izmantojot filter, lai noņemtu konkrētu vērtību
const newValueToRemove = 3;
const arrayWithoutValue = originalArray.filter(item => item !== newValueToRemove);
console.log(arrayWithoutValue); // Izvade: [1, 2, 4, 5]

Labākās prakses un progresīvas tehnikas

Kļūstot ērtāk ar funkcionālajām masīvu metodēm, apsveriet šādas prakses:

Piemērs: Funkcionāla pieeja datu apvienošanai

Iedomājieties, ka jums ir pārdošanas dati no dažādiem reģioniem un vēlaties aprēķināt kopējo pārdošanas apjomu katram reģionam, tad atrast reģionu ar vislielāko pārdošanas apjomu.

const salesData = [
  { region: 'North', amount: 100 },
  { region: 'South', amount: 150 },
  { region: 'North', amount: 120 },
  { region: 'East', amount: 200 },
  { region: 'South', amount: 180 },
  { region: 'North', amount: 90 }
];

// 1. Aprēķiniet kopējo pārdošanas apjomu katram reģionam, izmantojot reduce
const salesByRegion = salesData.reduce((acc, sale) => {
  acc[sale.region] = (acc[sale.region] || 0) + sale.amount;
  return acc;
}, {});

// salesByRegion būs: { North: 310, South: 330, East: 200 }

// 2. Pārveidojiet apkopoto objektu par objektu masīvu turpmākai apstrādei
const salesArray = Object.keys(salesByRegion).map(region => ({
  region: region,
  totalAmount: salesByRegion[region]
}));

// salesArray būs: [
//   { region: 'North', totalAmount: 310 },
//   { region: 'South', totalAmount: 330 },
//   { region: 'East', totalAmount: 200 }
// ]

// 3. Atrodiet reģionu ar vislielāko pārdošanas apjomu, izmantojot reduce
const highestSalesRegion = salesArray.reduce((max, current) => {
  return current.totalAmount > max.totalAmount ? current : max;
}, { region: '', totalAmount: -Infinity }); // Inicializēt ar ļoti mazu skaitli

console.log('Pārdošana pa reģioniem:', salesByRegion);
console.log('Pārdošanas masīvs:', salesArray);
console.log('Reģions ar lielāko pārdošanas apjomu:', highestSalesRegion);

/*
Izvade:
Pārdošana pa reģioniem: { North: 310, South: 330, East: 200 }
Pārdošanas masīvs: [
  { region: 'North', totalAmount: 310 },
  { region: 'South', totalAmount: 330 },
  { region: 'East', totalAmount: 200 }
]
Reģions ar lielāko pārdošanas apjomu: { region: 'South', totalAmount: 330 }
*/

Secinājums

Funkcionālā programmēšana ar JavaScript masīviem nav tikai stilistiska izvēle; tas ir spēcīgs veids, kā rakstīt tīrāku, prognozējamāku un robustāku kodu. Ieviešot tādas metodes kā map, filter un reduce, jūs varat efektīvi transformēt, vaicāt un apkopot datus, vienlaikus ievērojot funkcionālās programmēšanas pamatprincipus, īpaši nemainību un tīras funkcijas.

Turpinot savu ceļojumu JavaScript izstrādē, šo funkcionālo modeļu integrēšana ikdienas darba plūsmā neapšaubāmi novedīs pie vieglāk uzturamām un mērogojamām lietojumprogrammām. Sāciet ar šo masīvu metožu eksperimentēšanu savos projektos, un drīz vien atklāsiet to milzīgo vērtību.