Lietuvių

Atraskite funkcinio programavimo galią su JavaScript masyvais. Išmokite efektyviai transformuoti, filtruoti ir redukuoti duomenis naudojant integruotus metodus.

Funkcinio programavimo su JavaScript masyvais įvaldymas

Nuolat besikeičiančioje interneto kūrimo srityje JavaScript išlieka kertiniu akmeniu. Nors objektinio ir imperatyvaus programavimo paradigmos ilgą laiką dominavo, funkcinis programavimas (FP) įgauna vis didesnį populiarumą. FP pabrėžia nekintamumą, grynąsias funkcijas ir deklaratyvų kodą, o tai lemia patikimesnes, lengviau prižiūrimas ir nuspėjamas programas. Vienas iš galingiausių būdų pritaikyti funkcinį programavimą JavaScript yra pasinaudoti jo natūraliais masyvų metodais.

Šis išsamus gidas paaiškins, kaip galite panaudoti funkcinio programavimo principų galią naudojant JavaScript masyvus. Mes išnagrinėsime pagrindines sąvokas ir parodysime, kaip jas taikyti naudojant metodus, tokius kaip map, filter ir reduce, pakeisdami jūsų požiūrį į duomenų manipuliavimą.

Kas yra funkcinis programavimas?

Prieš gilinantis į JavaScript masyvus, trumpai apibrėžkime funkcinį programavimą. Iš esmės, FP yra programavimo paradigma, kuri skaičiavimą traktuoja kaip matematinių funkcijų vertinimą ir vengia būsenos keitimo bei kintamų duomenų. Pagrindiniai principai apima:

Šių principų taikymas gali padėti sukurti kodą, kurį lengviau suprasti, testuoti ir derinti, ypač sudėtingose programose. JavaScript masyvų metodai puikiai tinka šioms koncepcijoms įgyvendinti.

JavaScript masyvų metodų galia

JavaScript masyvai turi gausų integruotų metodų rinkinį, leidžiantį atlikti sudėtingas duomenų manipuliacijas nenaudojant tradicinių ciklų (pvz., for ar while). Šie metodai dažnai grąžina naujus masyvus, skatindami nekintamumą, ir priima atgalinio iškvietimo (callback) funkcijas, įgalindami funkcinį požiūrį.

Panagrinėkime pagrindinius funkcinius masyvų metodus:

1. Array.prototype.map()

Metodas map() sukuria naują masyvą, užpildytą rezultatais, gautais iškvietus pateiktą funkciją kiekvienam pradinio masyvo elementui. Jis idealiai tinka kiekvieno masyvo elemento transformavimui į kažką naujo.

Sintaksė:

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

Pagrindinės savybės:

Pavyzdys: Kiekvieno skaičiaus padvigubinimas

Įsivaizduokite, kad turite skaičių masyvą ir norite sukurti naują masyvą, kuriame kiekvienas skaičius yra padvigubintas.

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

// Naudojamas map transformacijai
const doubledNumbers = numbers.map(number => number * 2);

console.log(numbers); // Išvestis: [1, 2, 3, 4, 5] (originalus masyvas nepakito)
console.log(doubledNumbers); // Išvestis: [2, 4, 6, 8, 10]

Pavyzdys: Savybių išgavimas iš objektų

Dažnas panaudojimo atvejis – konkrečių savybių išgavimas iš objektų masyvo. Tarkime, turime vartotojų sąrašą ir norime gauti tik jų vardus.

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

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

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

2. Array.prototype.filter()

Metodas filter() sukuria naują masyvą su visais elementais, kurie praeina pateiktos funkcijos įgyvendintą testą. Jis naudojamas elementams pasirinkti pagal tam tikrą sąlygą.

Sintaksė:

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

Pagrindinės savybės:

Pavyzdys: Lyginių skaičių filtravimas

Filtruokime skaičių masyvą, kad paliktume tik lyginius skaičius.

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

// Naudojamas filter lyginiams skaičiams atrinkti
const evenNumbers = numbers.filter(number => number % 2 === 0);

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

Pavyzdys: Aktyvių vartotojų filtravimas

Iš mūsų vartotojų masyvo išfiltruokime vartotojus, kurie yra pažymėti kaip aktyvūs.

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

3. Array.prototype.reduce()

Metodas reduce() vykdo vartotojo pateiktą „reduktoriaus“ (reducer) atgalinio iškvietimo funkciją kiekvienam masyvo elementui iš eilės, perduodamas grąžinamąją reikšmę iš skaičiavimo su ankstesniu elementu. Galutinis reduktoriaus vykdymo per visus masyvo elementus rezultatas yra viena reikšmė.

Tai, be abejonės, universaliausias iš masyvų metodų ir yra daugelio funkcinio programavimo modelių pagrindas, leidžiantis „redukuoti“ masyvą iki vienos reikšmės (pvz., sumos, sandaugos, skaičiaus arba net naujo objekto ar masyvo).

Sintaksė:

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

Pagrindinės savybės:

Pavyzdys: Skaičių sumavimas

Susumuokime visus skaičius mūsų masyve.

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

// Naudojamas reduce skaičiams sumuoti
const sum = numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 0); // 0 yra pradinė reikšmė (initialValue)

console.log(sum); // Išvestis: 15

Paaiškinimas:

Pavyzdys: Objektų grupavimas pagal savybę

Galime naudoti reduce, kad paverstume objektų masyvą į objektą, kuriame reikšmės sugrupuotos pagal tam tikrą savybę. Sugrupuokime mūsų vartotojus pagal jų `isActive` būseną.

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;
}, {}); // Tuščias objektas {} yra pradinė reikšmė (initialValue)

console.log(groupedUsers);
/* Išvestis:
{
  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 }
  ]
}
*/

Pavyzdys: Pasikartojimų skaičiavimas

Suskaičiuokime kiekvieno vaisiaus pasikartojimo dažnį sąraše.

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); // Išvestis: { apple: 3, banana: 2, orange: 1 }

4. Array.prototype.forEach()

Nors forEach() negrąžina naujo masyvo ir dažnai laikomas labiau imperatyviu, nes jo pagrindinis tikslas yra įvykdyti funkciją kiekvienam masyvo elementui, jis vis tiek yra pagrindinis metodas, kuris vaidina vaidmenį funkciniuose modeliuose, ypač kai reikalingi šalutiniai poveikiai arba kai iteruojama be transformuotos išvesties poreikio.

Sintaksė:

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

Pagrindinės savybės:

Pavyzdys: Kiekvieno elemento registravimas

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

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

Pastaba: Transformacijoms ir filtravimui pirmenybė teikiama map ir filter dėl jų nekintamumo ir deklaratyvios prigimties. Naudokite forEach, kai specialiai reikia atlikti veiksmą kiekvienam elementui, nerenkant rezultatų į naują struktūrą.

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

Šie metodai naudingi ieškant konkrečių elementų masyve.

Pavyzdys: Vartotojo paieška

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

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

Šie metodai tikrina, ar visi masyvo elementai atitinka pateiktos funkcijos įgyvendintą testą.

Pavyzdys: Vartotojo būsenos tikrinimas

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); // Išvestis: true (nes Bob yra neaktyvus)
console.log(allAreActive); // Išvestis: false (nes Bob yra neaktyvus)

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

// Alternatyva naudojant every tiesiogiai
const allUsersActiveDirect = users.every(user => user.isActive);
console.log(allUsersActiveDirect); // Išvestis: false

Masyvų metodų grandininis jungimas sudėtingoms operacijoms

Tikroji funkcinio programavimo su JavaScript masyvais galia atsiskleidžia, kai šiuos metodus sujungiame į grandinę. Kadangi dauguma šių metodų grąžina naujus masyvus (išskyrus forEach), galite sklandžiai perduoti vieno metodo išvestį į kito įvestį, sukurdami elegantiškus ir lengvai skaitomus duomenų apdorojimo vamzdynus.

Pavyzdys: Aktyvių vartotojų vardų radimas ir jų ID padvigubinimas

Raskime visus aktyvius vartotojus, ištraukime jų vardus, o tada sukurkime naują masyvą, kuriame prie kiekvieno vardo pridedamas skaičius, nurodantis jo indeksą *išfiltruotame* sąraše, o jų ID yra padvigubinti.

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) // Gauti tik aktyvius vartotojus
  .map((user, index) => ({      // Transformuoti kiekvieną aktyvų vartotoją
    name: `${index + 1}. ${user.name}`,
    doubledId: user.id * 2
  }));

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

Šis grandininis požiūris yra deklaratyvus: mes nurodome žingsnius (filtruoti, tada transformuoti) be aiškaus ciklų valdymo. Jis taip pat yra nekintamas, nes kiekvienas žingsnis sukuria naują masyvą ar objektą, palikdamas originalų users masyvą nepaliestą.

Nekintamumas praktikoje

Funkcinis programavimas labai remiasi nekintamumu. Tai reiškia, kad vietoj esamų duomenų struktūrų keitimo, jūs kuriate naujas su norimais pakeitimais. JavaScript masyvų metodai, tokie kaip map, filter ir slice, iš prigimties tai palaiko, grąžindami naujus masyvus.

Kodėl nekintamumas yra svarbus?

Kai reikia atlikti operaciją, kuri tradiciškai pakeistų masyvą (pvz., pridėti ar pašalinti elementą), galite pasiekti nekintamumą naudodami metodus, tokius kaip slice, „spread“ sintaksę (...), arba derindami kitus funkcinius metodus.

Pavyzdys: Elemento pridėjimas nekintamu būdu

const originalArray = [1, 2, 3];

// Imperatyvus būdas (keičia originalų masyvą)
// originalArray.push(4);

// Funkcinis būdas naudojant „spread“ sintaksę
const newArrayWithPush = [...originalArray, 4];
console.log(originalArray); // Išvestis: [1, 2, 3]
console.log(newArrayWithPush); // Išvestis: [1, 2, 3, 4]

// Funkcinis būdas naudojant slice ir sujungimą (dabar retesnis)
const newArrayWithSlice = originalArray.slice(0, originalArray.length).concat(4);
console.log(newArrayWithSlice); // Išvestis: [1, 2, 3, 4]

Pavyzdys: Elemento pašalinimas nekintamu būdu

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

// Pašalinti elementą su indeksu 2 (reikšmė 3)

// Funkcinis būdas naudojant slice ir „spread“ sintaksę
const newArrayAfterSplice = [
  ...originalArray.slice(0, 2),
  ...originalArray.slice(3)
];
console.log(originalArray); // Išvestis: [1, 2, 3, 4, 5]
console.log(newArrayAfterSplice); // Išvestis: [1, 2, 4, 5]

// Naudojant filter konkrečiai reikšmei pašalinti
const newValueToRemove = 3;
const arrayWithoutValue = originalArray.filter(item => item !== newValueToRemove);
console.log(arrayWithoutValue); // Išvestis: [1, 2, 4, 5]

Gerosios praktikos ir pažangios technikos

Kai labiau įprasite prie funkcinių masyvų metodų, apsvarstykite šias praktikas:

Pavyzdys: Funkcinis požiūris į duomenų agregavimą

Įsivaizduokite, kad turite pardavimų duomenis iš skirtingų regionų ir norite apskaičiuoti bendrus pardavimus kiekvienam regionui, o tada rasti regioną su didžiausiais pardavimais.

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. Apskaičiuoti bendrus pardavimus pagal regioną naudojant reduce
const salesByRegion = salesData.reduce((acc, sale) => {
  acc[sale.region] = (acc[sale.region] || 0) + sale.amount;
  return acc;
}, {});

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

// 2. Konvertuoti agreguotą objektą į objektų masyvą tolesniam apdorojimui
const salesArray = Object.keys(salesByRegion).map(region => ({
  region: region,
  totalAmount: salesByRegion[region]
}));

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

// 3. Rasti regioną su didžiausiais pardavimais naudojant reduce
const highestSalesRegion = salesArray.reduce((max, current) => {
  return current.totalAmount > max.totalAmount ? current : max;
}, { region: '', totalAmount: -Infinity }); // Inicijuoti su labai mažu skaičiumi

console.log('Pardavimai pagal regioną:', salesByRegion);
console.log('Pardavimų masyvas:', salesArray);
console.log('Regionas su didžiausiais pardavimais:', highestSalesRegion);

/*
Išvestis:
Pardavimai pagal regioną: { North: 310, South: 330, East: 200 }
Pardavimų masyvas: [
  { region: 'North', totalAmount: 310 },
  { region: 'South', totalAmount: 330 },
  { region: 'East', totalAmount: 200 }
]
Regionas su didžiausiais pardavimais: { region: 'South', totalAmount: 330 }
*/

Išvada

Funkcinis programavimas su JavaScript masyvais yra ne tik stilistinis pasirinkimas; tai galingas būdas rašyti švaresnį, labiau nuspėjamą ir patikimesnį kodą. Pradėję naudoti tokius metodus kaip map, filter ir reduce, galite efektyviai transformuoti, užklausti ir agreguoti duomenis, laikydamiesi pagrindinių funkcinio programavimo principų, ypač nekintamumo ir grynųjų funkcijų.

Tęsiant kelionę JavaScript kūrimo srityje, šių funkcinių modelių integravimas į kasdienę darbo eigą neabejotinai padės kurti lengviau prižiūrimas ir labiau keičiamo mastelio programas. Pradėkite eksperimentuoti su šiais masyvų metodais savo projektuose ir netrukus atrasite jų didžiulę vertę.