11 najważniejszych (i więcej!) funkcji JavaScript, które musisz znać

Koduj mądrze! Bądź szybszym, bardziej produktywnym i szczęśliwszym programistą JavaScript, opanowując te najważniejsze i powtarzające się funkcje tego języka.

Niezależnie od tego, czy jest to backend, czy frontend (a nawet statki kosmiczne), JavaScript jest wszędzie. Jest to również dość elastyczny język (co oznacza, że ​​ma hardkorowe wzorce programowania funkcyjnego, jak również stare, dobre klasy), a jego podobieństwo do innych języków „podobnych do C” ułatwia programistom przejście z innych języków.

Jeśli chcesz ulepsz swoją grę JS, sugeruję poznanie, przećwiczenie i ostatecznie opanowanie następujących podstawowych funkcji dostępnych w tym języku. Nie wszystkie z nich są ściśle „niezbędne” do rozwiązywania problemów, ale w niektórych przypadkach mogą zrobić dla ciebie dużo ciężkiej pracy, podczas gdy w innych mogą zmniejszyć ilość kodu, który musisz napisać.

mapa()

Byłoby herezją napisać artykuł o ważnych funkcjach JavaScript i nie wspomnieć o map()! 😆😆 Wraz z filter() i reduce(), map() tworzy swego rodzaju świętą trójcę. Są to funkcje, których będziesz często używać w swojej karierze, więc są więcej niż warte obejrzenia. Zajmijmy się nimi po kolei, zaczynając od map().

map() należy do tych funkcji, które sprawiają najwięcej problemów osobom uczącym się JavaScript. Czemu? Nie dlatego, że jest w tym coś z natury złożonego, ale dlatego, że sposób działania tej funkcji jest pomysłem zaczerpniętym z tak zwanego programowania funkcjonalnego. A ponieważ nie jesteśmy narażeni na programowanie funkcyjne — nasze szkoły i branża są pełne języków obiektowych — działanie wydaje się dziwne, a nawet błędne dla naszych tendencyjnych mózgów.

JavaScript jest o wiele bardziej funkcjonalny niż zorientowany obiektowo, chociaż jego nowoczesne wersje starają się ukryć ten fakt. Ale to cała puszka robaków, którą może kiedyś otworzę. 🤣 Ok, więc map() . . .

map() to bardzo prosta funkcja; przyłącza się do tablicy i pomaga nam przekształcić każdy element w coś innego, w wyniku czego powstaje nowa tablica. Inna funkcja, która zgodnie z konwencją jest anonimowa, określa, jak dokładnie przekonwertować element.

To wszystko! Przyzwyczajenie się do składni może zająć trochę czasu, ale zasadniczo to właśnie robimy w funkcji map(). Dlaczego możemy chcieć użyć map()? Zależy co chcemy osiągnąć. Załóżmy na przykład, że zarejestrowaliśmy temperaturę dla każdego dnia ostatniego tygodnia i zapisaliśmy ją jako prostą tablicę. Jednak teraz powiedziano nam, że instrumenty nie były zbyt dokładne i zgłosiły temperaturę o 1,5 stopnia niższą niż powinny.

Możemy wykonać tę poprawkę za pomocą funkcji map() w następujący sposób:

const weeklyReadings = [20, 22, 20.5, 19, 21, 21.5, 23];

const correctedWeeklyReadings = weeklyReadings.map(reading => reading + 1.5);

console.log(correctedWeeklyReadings); // gives [ 21.5, 23.5, 22, 20.5, 22.5, 23, 24.5 ]

Inny, bardzo praktyczny przykład pochodzi ze świata React, gdzie tworzenie list elementów DOM z tablic jest powszechnym wzorcem; więc coś takiego jest powszechne:

export default ({ products }) => {
    return products.map(product => {
        return (
            <div className="product" key={product.id}>
                <div className="p-name">{product.name}</div>
                <div className="p-desc">{product.description}</div>
            </div>
        );
    });
};

Tutaj mamy funkcjonalny komponent React, który otrzymuje listę produktów jako swoje rekwizyty. Z tej listy (tablicy) tworzy następnie listę „elementów div” HTML, zasadniczo konwertując każdy obiekt produktu na HTML. Oryginalny przedmiot produktów pozostaje nietknięty.

Możesz argumentować, że map() to nic innego jak uwielbiona pętla for i miałbyś całkowitą rację. Ale zauważ, że gdy tylko przedstawisz ten argument, przemawia twój zorientowany obiektowo umysł, podczas gdy te funkcje i ich uzasadnienie pochodzą z programowania funkcjonalnego, gdzie jednolitość, zwięzłość i elegancja są bardzo cenione. 🙂

filtr()

filter() to bardzo przydatna funkcja, którą będziesz często stosować w wielu sytuacjach. Jak sama nazwa wskazuje, ta funkcja filtruje tablicę na podstawie podanych reguł/logiki i zwraca nową tablicę zawierającą elementy, które spełniają te reguły.

Wykorzystajmy ponownie nasz przykład dotyczący pogody. Załóżmy, że mamy tablicę zawierającą maksymalne temperatury dla każdego dnia ostatniego tygodnia; teraz chcemy się dowiedzieć, ile z tych dni było chłodniejszych. Tak, „zimniej” to pojęcie subiektywne, więc powiedzmy, że szukamy dni, w których temperatura była niższa niż 20. Możemy to zrobić za pomocą funkcji filter() w następujący sposób:

const weeklyReadings = [20, 22, 20.5, 19, 21, 21.5, 23];

const colderDays = weeklyReadings.filter(dayTemperature => {
    return dayTemperature < 20;
});

console.log("Total colder days in week were: " + colderDays.length); // 1

Zwróć uwagę, że anonimowa funkcja, którą przekazujemy do filter() musi zwracać wartość logiczną: prawda lub fałsz. W ten sposób filter() będzie wiedział, czy uwzględnić ten element w filtrowanej tablicy. Możesz napisać dowolną ilość złożonej logiki wewnątrz tej anonimowej funkcji; możesz wykonywać wywołania interfejsu API i odczytywać dane wprowadzane przez użytkownika i tak dalej, o ile upewnisz się, że ostatecznie zwracasz wartość logiczną.

Uwaga: jest to uwaga dodatkowa, którą czuję się zobowiązany przedstawić na podstawie mojego doświadczenia jako programisty JavaScript. Niezależnie od tego, czy jest to spowodowane niechlujstwem, czy złymi podstawami, wielu programistów tworzy subtelne błędy w swoich programach podczas używania funkcji filter(). Przepiszmy poprzedni kod, aby zawierał błąd:

const weeklyReadings = [20, 22, 20.5, 19, 21, 21.5, 23];

const colderDays = weeklyReadings.filter(dayTemperature => {
    return dayTemperature < 20;
});

if(colderDays) {
    console.log("Yes, there were colder days last week");
} else {
    console.log("No, there were no colder days");
}

Zauważ coś? Świetna robota, jeśli to zrobiłeś! Warunek if pod koniec sprawdza colderDays, który w rzeczywistości jest tablicą! Zdziwisz się, ile razy ludzie popełniają ten błąd, ścigając się, by dotrzymać terminów lub kodować w złym humorze (z jakiegokolwiek powodu). Problem z tym warunkiem polega na tym, że JavaScript jest pod wieloma względami dziwnym i niespójnym językiem, a „prawdziwość” rzeczy jest jednym z nich. Podczas gdy [] == prawda zwraca fałsz, co sprawia, że ​​myślisz, że powyższy kod nie jest uszkodzony, w rzeczywistości wewnątrz warunku if [] ocenia jako prawdziwe! Innymi słowy, napisany przez nas kod nigdy nie powie, że w zeszłym tygodniu nie było zimniejszych dni.

Poprawka jest bardzo prosta, jak podano w kodzie przed powyższym kodem. Sprawdzamy colderDays.length, który gwarantuje nam liczbę całkowitą (zero lub więcej), dzięki czemu działa konsekwentnie w porównaniach logicznych. Zauważ, że filter() zawsze, zawsze, zawsze zwraca tablicę, pustą lub niepustą, więc możemy na tym polegać i pewnie pisać nasze logiczne porównania.

To był dłuższy objazd, niż planowałem, ale błędy takie jak ten są warte podkreślenia w dziesięciu tysiącach słów, w razie potrzeby dużymi literami. Mam nadzieję, że nie zostaniesz przez to ugryziony i oszczędzisz sobie setek godzin debugowania! 🙂

redukować()

Spośród wszystkich funkcji opisanych w tym artykule, a także w standardowej bibliotece JavaScript, reduce() jest jednym z liderów w walce o koronę „zagmatwanych i dziwnych”. Chociaż ta funkcja jest bardzo ważna i w wielu sytuacjach skutkuje eleganckim kodem, większość programistów JavaScript unika jej i zamiast tego woli pisać bardziej rozwlekły kod.

Powodem jest to, że — i będę tu szczery! — funkcja reduce() jest trudna do zrozumienia, zarówno w sensie koncepcji, jak i wykonania. Kiedy czytasz jego opis, przeczytałeś go kilka razy i nadal wątpisz w siebie, czy nie przeczytałeś go źle; a kiedy widzisz to w akcji i próbujesz zwizualizować, jak to działa, twój mózg skręca się w tysiąc węzłów! 🤭

Nie bój się. Funkcja reduce() nie jest tak skomplikowana i zastraszająca jak, powiedzmy, Drzewa B+ i ich algorytmy. Po prostu tego rodzaju logika jest rzadko spotykana podczas codziennej pracy przeciętnego programisty.

Tak więc, wystraszywszy cię na świcie, a następnie natychmiast mówiąc ci, żebyś się nie martwił, chciałbym w końcu pokazać ci, czym jest ta funkcja i dlaczego dokładnie możemy jej potrzebować.

Jak sama nazwa wskazuje, reduce() służy do, cóż, redukcji czegoś. Rzeczą, którą redukuje, jest tablica, a rzeczą, do której redukuje daną tablicę, jest pojedyncza wartość (liczba, łańcuch, funkcja, obiekt, cokolwiek). Oto prostszy sposób ujmowania tego — reduce() przekształca tablicę w pojedynczą wartość. Zauważ, że wartość zwracana przez reduce() nie jest tablicą, jak ma to miejsce w przypadku map() i filter(). Zrozumienie tego to już połowa sukcesu. 🙂

Teraz jest trochę oczywiste, że jeśli zamierzamy przekształcić (zredukować) tablicę, musimy dostarczyć niezbędną logikę; a bazując na twoim doświadczeniu jako programisty JS, już prawie odgadłeś, że robimy to za pomocą funkcji. Tę funkcję nazywamy funkcją zmniejszającą, która stanowi pierwszy argument funkcji reduce(). Drugim argumentem jest wartość początkowa, taka jak liczba, ciąg znaków itp. (Za chwilę wyjaśnię, czym do cholery jest ta „wartość początkowa”).

Opierając się na naszym dotychczasowym zrozumieniu, możemy powiedzieć, że wywołanie funkcji reduce() wygląda następująco: array.reduce(reducerFunction, startValue). Zajmijmy się teraz sednem całości: funkcją reduktora. Jak już ustalono, funkcja reduce mówi funkcji reduce(), jak przekonwertować tablicę na pojedynczą wartość. Przyjmuje dwa argumenty: zmienną, która działa jak akumulator (bez obaw, wyjaśnię to również) oraz zmienną do przechowywania bieżącej wartości.

Wiem wiem . . . to było dużo terminologii dla jednej funkcji, która nie jest nawet obowiązkowa w JavaScript. 😝😝 I dlatego ludzie uciekają od reduce(). Ale jeśli nauczysz się tego krok po kroku, nie tylko to zrozumiesz, ale także docenisz, gdy staniesz się lepszym programistą.

Ok, więc wracamy do aktualnego tematu. „Wartość początkowa” przekazywana do funkcji reduce() to . . . Cóż, wartość początkowa do obliczenia, którego chcesz użyć. Na przykład, jeśli zamierzasz wykonać mnożenie w funkcji redukującej, początkowa wartość 1 ma sens; dla dodawania możesz zacząć od 0 i tak dalej.

Teraz spójrzmy na sygnaturę funkcji reduktora. Funkcja reduktora przekazywana do funkcji reduce() ma postać: reducerFunction(acumulator, currentValue). „Akumulator” to tylko fantazyjna nazwa zmiennej, która zbiera i przechowuje wynik obliczeń; to dokładnie tak, jakby użyć zmiennej o nazwie total do zsumowania wszystkich elementów w tablicy za pomocą czegoś takiego jak total += arr[i]. Dokładnie w ten sposób stosowana jest funkcja redukująca w funkcji reduce(): akumulator jest początkowo ustawiany na podaną przez ciebie wartość początkową, a następnie kolejno odwiedzane są elementy tablicy, wykonywane są obliczenia, a wynik jest zapisywany w akumulator i tak dalej. . .

Czym więc jest ta „wartość bieżąca” w funkcji reduktora? To ten sam pomysł, który wyobraziłbyś sobie, gdybym poprosił cię o przechodzenie przez tablicę: wziąłbyś zmienną, aby zaczynała się od indeksu zero i przesuwał ją krok po kroku do przodu. Kiedy to robisz, jeśli poproszę cię o nagłe zatrzymanie się, znajdziesz się na jednym z elementów tablicy, prawda? Oto, co rozumiemy przez bieżącą wartość: jest to wartość zmiennej używanej do reprezentowania elementu tablicy, który jest obecnie rozważany (pomyśl o zapętleniu tablicy, jeśli to pomaga).

Po tym wszystkim nadszedł czas, aby zobaczyć prosty przykład i zobaczyć, jak cały ten żargon łączy się w rzeczywiste wywołanie funkcji reduce(). Załóżmy, że mamy tablicę zawierającą pierwsze n liczb naturalnych (1, 2, 3… n) i jesteśmy zainteresowani znalezieniem silni liczby n. Wiemy, że aby znaleźć n! musimy po prostu wszystko pomnożyć, co prowadzi nas do tej implementacji:

const numbers = [1, 2, 3, 4, 5];
const factorial = numbers.reduce((acc, item) => acc * item, 1);
console.log(factorial); // 120

Wiele się dzieje w tych zaledwie trzech liniach kodu, więc rozpakujmy to po kolei w kontekście (bardzo długiej) dyskusji, którą odbyliśmy do tej pory. Jak widać, liczby to tablica zawierająca wszystkie liczby, które chcemy pomnożyć. Następnie spójrz na wywołanie numbers.reduce(), które mówi, że początkową wartością dla acc powinno być 1 (ponieważ nie wpływa to ani nie niszczy mnożenia). Następnie sprawdź treść funkcji redukującej, `(acc, item) => acc * item, która po prostu mówi, że wartością zwracaną dla każdej iteracji tablicy powinna być ta pozycja pomnożona przez to, co już jest w akumulatorze. Iteracja i faktyczne przechowywanie mnożenia jawnie w akumulatorze jest tym, co dzieje się za kulisami i jest jednym z największych powodów, dla których reduce() jest taką przeszkodą dla programistów JavaScript.

Po co używać funkcji reduce()?

To naprawdę świetne pytanie i szczerze mówiąc, nie mam jednoznacznej odpowiedzi. Cokolwiek reduce() robi, można to zrobić za pomocą pętli, forEach() itp. Jednak te techniki skutkują znacznie większą ilością kodu, co utrudnia czytanie, zwłaszcza jeśli się spieszysz. Następnie pojawia się obawa o niezmienność: dzięki funkcji reduce() i podobnym funkcjom możesz być pewien, że oryginalne dane nie zostały zmutowane; to samo w sobie eliminuje całe klasy błędów, zwłaszcza w aplikacjach rozproszonych.

Wreszcie funkcja reduce() jest znacznie bardziej elastyczna w tym sensie, że akumulatorem może być obiekt, tablica, a nawet funkcja, jeśli zajdzie taka potrzeba; to samo dotyczy wartości początkowej i innych części wywołania funkcji — prawie wszystko może wejść i prawie wszystko może wyjść, więc istnieje wyjątkowa elastyczność w projektowaniu kodu wielokrotnego użytku.

Jeśli nadal nie jesteś przekonany, to też jest w porządku; sama społeczność JavaScript jest mocno podzielona co do „zwartości”, „elegancji” i „mocy” funkcji reduce(), więc nie ma nic złego w jej nieużywaniu. 🙂 Ale upewnij się, że patrzysz na niektóre zgrabne przykłady zanim zdecydujesz się na bin reduce().

niektóre()

Załóżmy, że masz tablicę obiektów, z których każdy reprezentuje osobę. Chcesz wiedzieć, czy w tablicy są osoby w wieku powyżej 35 lat. Zauważ, że nie ma potrzeby liczenia, ile jest takich osób, nie mówiąc już o pobieraniu ich listy. To, co tutaj mówimy, jest odpowiednikiem „jednego lub więcej” lub „co najmniej jednego”.

Jak Ty to robisz?

Tak, możesz utworzyć zmienną flagową i zapętlić tablicę, aby rozwiązać ten problem w następujący sposób:

const persons = [
    {
        name: 'Person 1',
        age: 32
    },
    
    {
        name: 'Person 2',
        age: 40
    },
];

let foundOver35 = false;

for (let i = 0; i < persons.length; i ++) {
    if(persons[i].age > 35) {
        foundOver35 = true;
        break;
    }
}

if(foundOver35) {
    console.log("Yup, there are a few people here!")
}

Problem? Moim zdaniem kod jest zbyt podobny do C lub podobny do Javy. „Głębokie” to kolejne słowo, które przychodzi na myśl. Doświadczony JS może myśleć o „brzydkim”, „okropnym” itp. 😝 I słusznie, kłóciłbym się. Jednym ze sposobów ulepszenia tego fragmentu kodu jest użycie czegoś takiego jak map(), ale nawet wtedy rozwiązanie jest nieco niezgrabne.

Okazuje się, że mamy dość zgrabną funkcję o nazwie some() już dostępną w języku rdzenia. Ta funkcja działa na tablicach i akceptuje niestandardową funkcję „filtrowania”, która zwraca wartość logiczną true lub false. Zasadniczo robi to, co próbowaliśmy robić przez ostatnie kilka minut, tylko bardzo zwięźle i elegancko. Oto jak możemy go użyć:

const persons = [
    {
        name: 'Person 1',
        age: 32
    },
    
    {
        name: 'Person 2',
        age: 40
    },
];

if(persons.some(person => {
    return person.age > 35
})) {
    console.log("Found some people!")
}

To samo wejście, ten sam wynik co poprzednio; ale zauważ ogromną redukcję kodu! Zauważ również, jak drastycznie zmniejsza się obciążenie poznawcze, ponieważ nie musimy już analizować kodu linia po linii, jakbyśmy sami byli tłumaczem! Kod jest teraz prawie czytany jak język naturalny.

każdy()

Podobnie jak some(), mamy inną przydatną funkcję, zwaną every(). Jak już możesz się domyślić, to również zwraca wartość logiczną w zależności od tego, czy wszystkie elementy w tablicy przejdą dany test. Oczywiście test do zaliczenia jest przez większość czasu dostarczany jako funkcja anonimowa. Oszczędzę ci bólu związanego z tym, jak może wyglądać naiwna wersja kodu, więc oto jak używa się funkcji every():

const entries = [
    {
        id: 1
    },
    
    {
        id: 2
    },
    
    {
        id: 3  
    },
];

if(entries.every(entry => {
    return Number.isInteger(entry.id) && entry.id > 0;
})) {
    console.log("All the entries have a valid id")
}

Jak widać, kod sprawdza wszystkie obiekty w tablicy pod kątem prawidłowej właściwości id. Definicja „poprawny” zależy od kontekstu problemu, ale jak widać, dla tego kodu wziąłem pod uwagę nieujemne liczby całkowite. Po raz kolejny widzimy, jak prosty i elegancki jest odczytywanie kodu, co jest jedynym celem tej (i podobnych) funkcji.

zawiera()

Jak sprawdzić, czy istnieją podciągi i elementy tablicy? Cóż, jeśli jesteś podobny do mnie, szybko sięgasz po indexOf(), a następnie przeglądasz dokumenty, aby poznać możliwe wartości zwracane. Jest to spora niedogodność, a zwracane wartości są trudne do zapamiętania (szybko — co oznacza proces zwracający 2 do systemu operacyjnego?).

Istnieje jednak fajna alternatywa, z której możemy skorzystać: obejmuje(). Użycie jest tak proste, jak sama nazwa, a wynikowy kod jest niezwykle ciepły. Należy pamiętać, że dopasowywanie odbywa się za pomocą funkcji include() jest rozróżniana wielkość liter, ale myślę, że i tak wszyscy intuicyjnie tego oczekujemy. A teraz czas na trochę kodu!

const numbers = [1, 2, 3, 4, 5];
console.log(numbers.includes(4));
const name = "Ankush";
console.log(name.includes('ank')); // false, because first letter is in small caps
console.log(name.includes('Ank')); // true, as expected

Nie oczekuj jednak zbyt wiele od tej skromnej metody:

const user = {a: 10, b: 20};
console.log(user.includes('a')); // blows up, as objects don't have a "includes" method

Nie może zaglądać do obiektów, ponieważ po prostu nie jest zdefiniowany dla obiektów. Ale hej, wiemy, że działa to na tablicach, więc może uda nam się tutaj trochę poszaleć. . . 🤔.

const persons = [{name: 'Phil'}, {name: 'Jane'}];
persons.includes({name: 'Phil'});

Co się dzieje po uruchomieniu tego kodu? Nie eksploduje, ale wynik też jest rozczarowujący: false. 😫😫 W rzeczywistości ma to związek z obiektami, wskaźnikami i tym, jak JavaScript widzi i zarządza pamięcią, która jest własnym światem. Jeśli chcesz nurkować głębiej, nie krępuj się zanurzyć (może zacznij tutaj), ale na tym poprzestanę.

Możemy sprawić, by powyższy kod zachowywał się, jeśli przepiszemy go w następujący sposób, ale w tym momencie moim zdaniem staje się to mniej więcej żartem:

const phil = {name: 'Phil'};
const persons = [phil, {name: 'Jane'}];
persons.includes(phil); // true

Mimo to pokazuje, że potrafimy sprawić, by include() działało na obiektach, więc myślę, że nie jest to całkowita katastrofa. 😄

plasterek()

Załóżmy, że mamy ciąg znaków i proszę o zwrócenie jego części, która zaczyna się na „r” i kończy na „z” (rzeczywiste znaki nie są ważne). Jak byś do tego podszedł? Być może utworzysz nowy ciąg i użyjesz go do przechowywania wszystkich niezbędnych znaków i zwrócenia ich. Lub, jeśli jesteś jak większość programistów, dałbyś mi w zamian dwa indeksy tablicy: jeden wskazujący początek podłańcucha, drugi oznaczający koniec.

Oba te podejścia są dobre, ale istnieje koncepcja zwana krojeniem, która oferuje zgrabne rozwiązanie w takich sytuacjach. Na szczęście nie ma zawiłej teorii do naśladowania; krojenie oznacza dokładnie to, na co brzmi — tworzenie mniejszego ciągu/tablicy z podanego, podobnie jak tworzymy plasterki owoców. Zobaczmy, co mam na myśli, posługując się prostym przykładem:

const headline = "And in tonight's special, the guest we've all been waiting for!";
const startIndex = headline.indexOf('guest');
const endIndex = headline.indexOf('waiting');
const newHeadline = headline.slice(startIndex, endIndex);
console.log(newHeadline); // guest we've all been

Kiedy używamy slice(), udostępniamy JavaScriptowi dwa indeksy — jeden, w którym chcemy rozpocząć cięcie, a drugi, w którym chcemy go zatrzymać. Problem z slice() polega na tym, że indeks końcowy nie jest uwzględniany w wyniku końcowym, dlatego widzimy, że w nowym nagłówku w powyższym kodzie brakuje słowa „oczekiwanie”.

Pojęcia takie jak krojenie są bardziej widoczne w innych językach, zwłaszcza w Pythonie. Jeśli zapytasz tych programistów, powiedzą, że nie wyobrażają sobie życia bez tej funkcjonalności, i słusznie, gdy język zapewnia bardzo zgrabną składnię do krojenia.

Krojenie jest schludne i niezwykle wygodne i nie ma powodu, aby z niego nie korzystać. Nie jest to również cukier składniowy obarczony karą za wydajność, ponieważ tworzy płytkie kopie oryginalnej tablicy/łańcucha. Programistom JavaScript gorąco polecam zapoznanie się z funkcją slice() i dodanie jej do swojego arsenału!

splatać()

Metoda splice() brzmi jak kuzynka slice() i pod pewnymi względami możemy twierdzić, że tak jest. Obie tworzą nowe tablice/ciągi z oryginalnych, z jedną małą, ale ważną różnicą — splice() usuwa, zmienia lub dodaje elementy, ale modyfikuje oryginalną tablicę. To „zniszczenie” oryginalnej tablicy może spowodować ogromne problemy, jeśli nie będziesz ostrożny lub nie zrozumiesz głębokich kopii i odniesień. Zastanawiam się, co powstrzymywało twórców przed zastosowaniem tego samego podejścia, co w przypadku slice() i pozostawieniem oryginalnej tablicy nietkniętej, ale myślę, że możemy być bardziej wyrozumiali dla języka powstał w ciągu zaledwie dziesięciu dni.

Niezależnie od moich skarg, spójrzmy, jak działa splice(). Pokażę przykład, w którym usuwamy kilka elementów z tablicy, ponieważ jest to najczęstsze zastosowanie tej metody. Powstrzymam się również od podawania przykładów dodawania i wstawiania, ponieważ można je łatwo wyszukać i są one również proste.

const items = ['eggs', 'milk', 'cheese', 'bread', 'butter'];
items.splice(2, 1);
console.log(items); // [ 'eggs', 'milk', 'bread', 'butter' ]

Powyższe wywołanie metody splice() mówi: rozpocznij od indeksu 2 (tj. trzeciego miejsca) tablicy i usuń jeden element. W podanej tablicy „ser” jest trzecim elementem, więc zostaje usunięty z tablicy, a tablica elementów zostaje skrócona, zgodnie z oczekiwaniami. Nawiasem mówiąc, usunięte elementy są zwracane przez splice() w formie lub tablicy, więc gdybyśmy chcieli, moglibyśmy przechwycić „cheese” w zmiennej.

Z mojego doświadczenia wynika, że ​​indexOf() i splice() mają świetną synergię — znajdujemy indeks elementu, a następnie usuwamy go z podanej tablicy. Należy jednak pamiętać, że nie zawsze jest to najskuteczniejsza metoda, a często użycie kluczy obiektowych (odpowiednik mapy skrótów) jest znacznie szybsze.

Zmiana()

shift() jest swego rodzaju wygodną metodą i służy do usuwania pierwszego elementu tablicy. Zauważ, że to samo można zrobić za pomocą splice(), ale shift() jest nieco łatwiejszy do zapamiętania i intuicyjny, gdy wszystko, co musisz zrobić, to odciąć pierwszy element.

const items = ['eggs', 'milk', 'cheese', 'bread', 'butter'];
items.shift()
console.log(items); // [ 'milk', 'cheese', 'bread', 'butter' ]

cofnij przesunięcie ()

Tak jak shift() usuwa pierwszy element z tablicy, unshift() dodaje nowy element na początku tablicy. Jego użycie jest równie proste i kompaktowe:

const items = ['eggs', 'milk'];
items.unshift('bread')
console.log(items); // [ 'bread', 'eggs', 'milk' ]

To powiedziawszy, nie mogę się powstrzymać i ostrzegam nowych w grze: w przeciwieństwie do popularnych metod push() i pop(), shift() i unshift() są wyjątkowo nieefektywne (ze względu na sposób działania algorytmów leżących u ich podstaw). Tak więc, jeśli operujesz na dużych tablicach (powiedzmy ponad 2000 elementów), zbyt wiele wywołań funkcji może spowodować zatrzymanie aplikacji.

wypełnić()

Czasami trzeba zmienić kilka elementów na jedną wartość lub nawet „zresetować” całą tablicę, że tak powiem. W takich sytuacjach funkcja fill() uchroni Cię przed pętlami i błędami „off-by-one”. Można go użyć do zastąpienia części lub całej tablicy podaną wartością. Zobaczmy kilka przykładów:

const heights = [1, 2, 4, 5, 6, 7, 1, 1];
heights.fill(0);
console.log(heights); // [0, 0, 0, 0, 0, 0, 0, 0]

const heights2 = [1, 2, 4, 5, 6, 7, 1, 1];
heights2.fill(0, 4);
console.log(heights2); // [1, 2, 4, 5, 0, 0, 0, 0]

Inne funkcje, o których warto wspomnieć

Chociaż powyższa lista jest tym, z czym większość programistów JavaScript spotyka się i używa w swojej karierze, to w żadnym wypadku nie jest kompletna. Istnieje tak wiele mniejszych, ale przydatnych funkcji (metod) w JavaScript, że nie będzie możliwe opisanie ich wszystkich w jednym artykule. To powiedziawszy, kilka, które przychodzą na myśl, to:

  • odwrócić()
  • sortować()
  • wpisy()
  • wypełnić()
  • odnaleźć()
  • mieszkanie()

Zachęcam do przynajmniej ich przejrzenia, aby mieć pojęcie, że takie udogodnienia istnieją.

Wniosek

JavaScript to duży język, pomimo niewielkiej liczby podstawowych pojęć do nauczenia. Wiele dostępnych nam funkcji (metod) stanowi większość tego dużego rozmiaru. Jednak ponieważ JavaScript jest językiem drugorzędnym dla większości programistów, nie nurkujemy wystarczająco głęboko, tracąc wiele pięknych i przydatnych funkcji, które oferuje. Właściwie to samo dotyczy koncepcji programowania funkcyjnego, ale to temat na inny dzień! 😅

Kiedy tylko możesz, poświęć trochę czasu na poznanie podstawowego języka (i jeśli to możliwe, słynnych bibliotek narzędziowych, takich jak Lodasz). Nawet kilka minut poświęconych na ten wysiłek zaowocuje ogromnym wzrostem produktywności oraz znacznie czystszym i bardziej zwartym kodem.