Eesti

Vabastage JavaScripti massiivide funktsionaalse programmeerimise jõud. Õppige oma andmeid tõhusalt teisendama, filtreerima ja vähendama sisseehitatud meetodite abil.

JavaScripti massiivide funktsionaalse programmeerimise meisterdamine

Veebiarenduse pidevalt arenevas maastikus on JavaScript jätkuvalt nurgakivi. Kuigi objektorienteeritud ja käskiv programmeerimisparadigma on pikka aega domineerinud, on funktsionaalne programmeerimine (FP) saavutanud märkimisväärse tõmbejõu. FP rõhutab muutumatust, puhtaid funktsioone ja deklaratiivset koodi, mis viib robustsemate, hooldatavamate ja prognoositavamate rakendusteni. Üks võimsamaid viise funktsionaalse programmeerimise omaksvõtmiseks JavaScriptis on selle natiivsete massiivi meetodite kasutamine.

See põhjalik juhend sukeldub sellesse, kuidas saate JavaScripti massiivide abil rakendada funktsionaalse programmeerimise põhimõtteid. Uurime peamisi kontseptsioone ja näitame, kuidas neid rakendada, kasutades selliseid meetodeid nagu map, filter ja reduce, muutes teie andmete manipuleerimise viisi.

Mis on funktsionaalne programmeerimine?

Enne JavaScripti massiividesse sukeldumist määratleme lühidalt funktsionaalse programmeerimise. Oma olemuselt on FP programmeerimisparadigma, mis käsitleb arvutamist matemaatiliste funktsioonide hindamisena ning väldib oleku ja muudetavate andmete muutmist. Peamised põhimõtted hõlmavad:

Nende põhimõtete omaksvõtmine võib viia koodini, mida on lihtsam mõista, testida ja siluda, eriti keerukates rakendustes. JavaScripti massiivide meetodid sobivad nende kontseptsioonide rakendamiseks suurepäraselt.

JavaScripti massiivide meetodite jõud

JavaScripti massiivid on varustatud rikkaliku sisseehitatud meetodite komplektiga, mis võimaldavad keerukat andmete manipuleerimist ilma traditsiooniliste tsükliteta (nagu for või while). Need meetodid tagastavad sageli uued massiivid, edendades muutumatust, ja aktsepteerivad tagasikutsumisfunktsioone, võimaldades funktsionaalset lähenemist.

Uurime kõige fundamentaalsemaid funktsionaalseid massiivi meetodeid:

1. Array.prototype.map()

map() meetod loob uue massiivi, mis on täidetud kõigile kutsutud massiivi elementidele rakendatud funktsiooni tulemustega. See sobib ideaalselt iga massiivi elemendi teisendamiseks millekski uueks.

Süntaks:

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

Peamised omadused:

Näide: iga numbri kahekordistamine

Kujutage ette, et teil on numbrite massiiv ja soovite luua uue massiivi, kus iga number on kahekordistatud.

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

// Kasutades teisendamiseks map
const doubledNumbers = numbers.map(number => number * 2);

console.log(numbers); // Väljund: [1, 2, 3, 4, 5] (originaalmassiiv jääb muutmata)
console.log(doubledNumbers); // Väljund: [2, 4, 6, 8, 10]

Näide: objektidest atribuutide väljavõtmine

Tavaline kasutusjuht on konkreetsete atribuutide väljavõtmine objektide massiivist. Oletame, et meil on kasutajate loend ja tahame saada ainult nende nimesid.

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

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

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

2. Array.prototype.filter()

filter() meetod loob uue massiivi kõigi elementidega, mis läbivad antud funktsiooni abil antud testi. Seda kasutatakse elementide valimiseks tingimuse alusel.

Süntaks:

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

Peamised omadused:

Näide: paaritute numbrite filtreerimine

Filtreerime numbrite massiivi, et säilitada ainult paaritud numbrid.

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

// Kasutades filtreerimist paaritute numbrite valimiseks
const evenNumbers = numbers.filter(number => number % 2 === 0);

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

Näide: aktiivsete kasutajate filtreerimine

Meie kasutajate massiivist filtreerime kasutajad, kes on märgitud aktiivseteks.

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);
/* Väljund:
[
  { id: 1, name: 'Alice', isActive: true },
  { id: 3, name: 'Charlie', isActive: true }
]
*/

3. Array.prototype.reduce()

reduce() meetod täidab kasutaja poolt pakutud "reduktori" tagasikutsumisfunktsiooni iga massiivi elemendi kohta järjest, edastades eelmisel elemendil arvutamise tulemuse. Reduktori kogu massiivi elementide kaudu käitamise lõpptulemus on üks väärtus.

See on vaieldamatult kõige mitmekülgsem massiivi meetoditest ja paljude funktsionaalse programmeerimise mustrite alustala, mis võimaldab teil massiivi "vähendada" üheks väärtuseks (nt summa, korrutis, loendus või isegi uus objekt või massiiv).

Süntaks:

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

Peamised omadused:

Näide: numbrite summeerimine

Summeerime kõik numbrid meie massiivis.

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

// Kasutades summeerimiseks reduce
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0); // 0 on initialValue

console.log(sum); // Väljund: 15

Selgitus:

Näide: objektide grupeerimine atribuudi järgi

Võime kasutada reduce-i objektide massiivi teisendamiseks objektiks, kus väärtused on grupeeritud konkreetse atribuudi järgi. Grupeerime oma kasutajad nende isActive oleku järgi.

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;
}, {}); // Tühi objekt {} on initialValue

console.log(groupedUsers);
/* Väljund:
{
  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 }
  ]
}
*/

Näide: esinemiste arvestamine

Arvutame iga puuvilja esinemissageduse loendis.

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); // Väljund: { apple: 3, banana: 2, orange: 1 }

4. Array.prototype.forEach()

Kuigi forEach() ei tagasta uut massiivi ja seda peetakse sageli käskivamaks, kuna selle peamine eesmärk on funktsiooni täitmine iga massiivi elemendi jaoks, on see siiski fundamentaalne meetod, mis mängib rolli funktsionaalsetes mustrites, eriti kui kõrvalmõjud on vajalikud või kui itereeritakse ilma teisendatud väljundit vajamata.

Süntaks:

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

Peamised omadused:

Näide: iga elemendi logimine

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

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

Märkus: Teisenduste ja filtreerimise jaoks on map ja filter eelistatud nende muutumatuse ja deklaratiivsuse tõttu. Kasutage forEach-i, kui peate konkreetse toimingu tegemiseks iga üksuse jaoks, ilma et tulemusi uude struktuuri koguksite.

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

Need meetodid on kasulikud konkreetsete elementide leidmiseks massiivist.

Näide: kasutaja leidmine

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); // Väljund: { id: 2, name: 'Bob' }
console.log(bobIndex); // Väljund: 1
console.log(nonExistentUser); // Väljund: undefined
console.log(nonExistentIndex); // Väljund: -1

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

Need meetodid testivad, kas kõik massiivi elemendid läbivad antud funktsiooni abil antud testi.

Näide: kasutaja oleku kontrollimine

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); // Väljund: true (kuna Bob on passiivne)
console.log(allAreActive); // Väljund: false (kuna Bob on passiivne)

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

// Alternatiiv igaühe otse kasutamise kaudu
const allUsersActiveDirect = users.every(user => user.isActive);
console.log(allUsersActiveDirect); // Väljund: false

Massiivide meetodite ühendamine keerukate toimingute jaoks

Funktsionaalse programmeerimise tõeline jõud JavaScripti massiividega avaldub siis, kui ühendate need meetodid. Kuna enamik neist meetoditest tagastab uued massiivid (välja arvatud forEach), saate ühe meetodi väljundi sujuvalt järgmise sisendiks juhtida, luues elegantseid ja loetavaid andmepipeliine.

Näide: aktiivsete kasutajate nimede leidmine ja nende ID-de kahekordistamine

Leiame kõik aktiivsed kasutajad, võtame välja nende nimed ja loome seejärel uue massiivi, kus iga nimi on eesliitega nummerdatud, mis tähistab selle indekseid filtreeritud loendis, ja nende ID-d on kahekordistatud.

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) // Hankige ainult aktiivsed kasutajad
  .map((user, index) => ({      // Teisendage iga aktiivne kasutaja
    name: `${index + 1}. ${user.name}`,
    doubledId: user.id * 2
  }));

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

See ühendatud lähenemine on deklaratiivne: me määrate sammud (esmalt filtreerimine, seejärel map) ilma selge tsüklihalduse ta. See on ka muutumatu, kuna iga samm loob uue massiivi või objekti, jättes originaal users massiivi puutumata.

Muutumatus praktikas

Funktsionaalne programmeerimine tugineb suuresti muutumatusele. See tähendab, et olemasolevate andmestruktuuride muutmise asemel loote soovitud muudatustega uued. JavaScripti massiivide meetodid, nagu map, filter ja slice, toetavad seda sisemiselt, tagastades uued massiivid.

Miks on muutumatus oluline?

Kui peate tegema toimingu, mis traditsiooniliselt muudaks massiivi (nt elemendi lisamine või eemaldamine), saate muutumatust saavutada, kasutades selliseid meetodeid nagu slice, levitamissüntaks (...) või teiste funktsionaalsete meetodite kombineerimisel.

Näide: elemendi muutumatu lisamine

const originalArray = [1, 2, 3];

// Käskiv viis (muudab originalArray)
// originalArray.push(4);

// Funktsionaalne viis levitamissüntaksi abil
const newArrayWithPush = [...originalArray, 4];
console.log(originalArray); // Väljund: [1, 2, 3]
console.log(newArrayWithPush); // Väljund: [1, 2, 3, 4]

// Funktsionaalne viis, kasutades slice ja ühendamist (praegu vähem levinud)
const newArrayWithSlice = originalArray.slice(0, originalArray.length).concat(4);
console.log(newArrayWithSlice); // Väljund: [1, 2, 3, 4]

Näide: elemendi muutumatu eemaldamine

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

// Elemendi eemaldamine indeksil 2 (väärtus 3)

// Funktsionaalne viis, kasutades slice ja levitamissüntaksit
const newArrayAfterSplice = [
  ...originalArray.slice(0, 2),
  ...originalArray.slice(3)
];
console.log(originalArray); // Väljund: [1, 2, 3, 4, 5]
console.log(newArrayAfterSplice); // Väljund: [1, 2, 4, 5]

// Filtri kasutamine konkreetse väärtuse eemaldamiseks
const newValueToRemove = 3;
const arrayWithoutValue = originalArray.filter(item => item !== newValueToRemove);
console.log(arrayWithoutValue); // Väljund: [1, 2, 4, 5]

Parimad praktikad ja täiustatud tehnikad

Kui muutute funktsionaalsete massiivi meetoditega mugavamaks, kaaluge neid tavasid:

Näide: funktsionaalne lähenemine andmete koondamisele

Kujutage ette, et teil on erinevate piirkondade müügiandmed ja soovite arvutada iga piirkonna kogumüügi, seejärel leida piirkonna, kus on suurim müük.

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. Arvutage kogumüük piirkonna kohta, kasutades reduce
const salesByRegion = salesData.reduce((acc, sale) => {
  acc[sale.region] = (acc[sale.region] || 0) + sale.amount;
  return acc;
}, {});

// salesByRegion saab olema: { North: 310, South: 330, East: 200 }

// 2. teisendage koondatud objekt edasiseks töötlemiseks objektide massiiviks
const salesArray = Object.keys(salesByRegion).map(region => ({
  region: region,
  totalAmount: salesByRegion[region]
}));

// salesArray saab olema: [
//   { region: 'North', totalAmount: 310 },
//   { region: 'South', totalAmount: 330 },
//   { region: 'East', totalAmount: 200 }
// ]

// 3. Leidke reduce abil piirkond suurima müügiga
const highestSalesRegion = salesArray.reduce((max, current) => {
  return current.totalAmount > max.totalAmount ? current : max;
}, { region: '', totalAmount: -Infinity }); // Alustage väga väikese numbriga

console.log('Sales by Region:', salesByRegion);
console.log('Sales Array:', salesArray);
console.log('Region with Highest Sales:', highestSalesRegion);

/*
Väljund:
Sales by Region: { North: 310, South: 330, East: 200 }
Sales Array: [
  { region: 'North', totalAmount: 310 },
  { region: 'South', totalAmount: 330 },
  { region: 'East', totalAmount: 200 }
]
Region with Highest Sales: { region: 'South', totalAmount: 330 }
*/

Järeldus

Funktsionaalne programmeerimine JavaScripti massiividega ei ole lihtsalt stiilivalik; see on võimas viis puhtama, prognoositavama ja robustsema koodi kirjutamiseks. Võttes kasutusele sellised meetodid nagu map, filter ja reduce, saate oma andmeid tõhusalt teisendada, päringuid teha ja koondada, järgides samal ajal funktsionaalse programmeerimise põhiprintsiipe, eriti muutumatust ja puhtaid funktsioone.

Jätkates oma JavaScripti arendamise teekonda, integreerides need funktsionaalsed mustrid oma igapäevasesse töövoogu, toob kahtlemata kaasa hooldatavamad ja skaleeritavamad rakendused. Alustage nende massiivi meetoditega oma projektides eksperimenteerimist ja avastate peagi nende tohutu väärtuse.