Tablice

Wyobraź sobie, że musisz przechować 10 różnych wartości. Tworzysz więc 10 zmiennych.
I wszystko jest w porządku do czasu, gdy dostajesz zadanie, by każdą taką zmienną zwiększyć np. o 2. Zaczynają się schody.
A schody te zwiększają się gdy dochodzisz do momentu kiedy nie możesz z góry określić ile masz tych zmiennych, lub gdy tych zmiennych robi się nie 10, a na przykład 2000 razy tyle.

Tutaj przychodzą z pomocą tablice, które są uporządkowanymi zbiorami zawierającymi jakieś dane. Dość klasycznym porównaniem jest szafa z bibliotecznymi kartami książek. Półka - tablica - przechowuje karty książek - u nas zmienne.

Tworzenie nowej tablicy

Aby stworzyć nową tablicę korzystamy z kwadratowych nawiasów:


const tab = []; //pusta tablica

const tab2 = [1, 2, 3, 4]; //tablica z 4 liczbami

const tab3 = ["Marcin", "Ania", "Agnieszka"]; //tablica z 3 elementami

const a = "ALA";
const b = 234;
const c = "PIES";

const tab = [a, b, c, "KOT", {...}]; //tablica z 5 elementami. Mogą to być oddzielne zmienne, ale też wartości wpisane w tablicy

Drugim sposobem tworzenia tablic - o wiele rzadziej używanym jest użycie konstruktora:


const tab = new Array(10);
console.log(tab); //[blank x 10]

const tab = new Array(10, "Ala", "Bala", "Cala"); //gdy podamy więcej wartości staną się one elementami tablicy
console.log(tab); //[10, "Ala", "Bala", "Cala"]

Metoda ta nie jest polecana na co dzień ze względu na niepotrzebne wydłużenie zapisu, ale przydaje się w kilku sytuacjach.

tablica

Jak widzisz powyżej, tablica przetrzymuje kolejne elementy. Nie ma znaczenia jakie są to elementy.
Znaczenie ma to, że są one ponumerowane za pomocą tak zwanych indeksów, które numerowane są od 0.
Pierwsza wartość w tablicy ma indeks 0, druga 1, trzecia 2 i tak dalej, aż do ostatniego indeksu który wynosi długość tablicy - 1 czyli tab.length-1.

Po stworzeniu tablicy aby pobrać dane elementy z tablicy wystarczy się do nich odwołać przez nazwę tablicy i indeks, który podajemy w kwadratowych nawiasach:


const tab = ["Ala", "ma", "rudego", "kota"];

console.log( tab[0] ); //Ala
console.log( tab[1] ); //ma
console.log( tab[2] ); //rudego
console.log( tab[3] ); //kota

Pamiętaj, że jeżeli pobieramy dany element z tablicy, to to co właśnie pobraliśmy nie jest jakąś magiczną nieosiągalną rzeczą, a zwykłą wartością, do której odwołalibyśmy się normalnie przez nazwę.
Dlatego właśnie po pobraniu elementu z tablicy traktujemy go tak samo jak klasyczną zmienną (bo w zasadzie to to samo, tylko włożone do tablicy):


const myVar = "Marcin";
console.log(myVar + "!"); //Marcin!

const tab = ["Marcin", "Ania"]
console.log(tab[0] + "!"); //Marcin!

const name = tab[1];
console.log(name.toUpperCase() + " jest lepsza"); //ANIA jest lepsza

Właściwość length

Każda tablica udostępnia nam właściwość length, która określa jej długość (czyli ilość jej elementów).
Dzięki temu możemy poznać nie tylko długość tablicy, ale i indeks ostatniego elementu oraz w łatwy sposób przeprowadzać pętlę po wszystkich elementach naszej tablicy.


//indeks:       0         1         2
const tab = ["Marcin", "Ania", "Agnieszka"];

console.log( tab.length ); //3
console.log( tab[ tab.length-1 ] ); //Agnieszka

Dodawanie elementów do tablicy

Aby dodać do tablicy element na jej końcu, możemy użyć metody push(element1, element2, ...):


const tab = ["Marcin", "Ania", "Agnieszka"];
tab.push("Piotrek");
console.log(tab); //[Marcin, Ania, Agnieszka, Piotrek]

tab.push("Y", "Z");
console.log(tab); //[Marcin, Ania, Agnieszka, Piotrek, Y, Z]

Drugą metodą jest po prostu ustawianie elementu na danym indeksie:


const tab = ["Marcin", "Ania", "Agnieszka"];

tab[3] = "Piotrek";
//lub
tab[tab.length] = "Piotrek";

console.log(tab); //[Marcin, Ania, Agnieszka, Piotrek]

Jest to mniej bezpieczna metoda, bo możemy nieumyślnie ustawić element w złym miejscu, co może spowodować, że w tabeli pojawią się puste miejsca:


const tab = ["Marcin", "Ania"];

tab[6] = "Piotrek";
console.log(tab); //[Marcin, Ania, empty x 4, Piotrek]

lub przez przypadek nadpiszemy już istniejącą wartość:


const tab = ["Marcin", "Ania", "Agnieszka"];

tab[2] = "Piotrek";
console.log(tab); //Marcin, Ania, Piotrek

Poza powyższymi podstawami, tablice udostępniają nam dużą liczbę metod, które możemy na nich używać.
Poniżej poznamy te najczęściej używane.

Czy tablica jest tablicą?

Żeby sprawdzić czy dana zmienna jest tablicą, powinniśmy skorzystać z metody Array.isArray(). Wynika to z faktu, że tablice w Javascript także są obiektami i typeof zwraca nam "object":


const tab = ["ala", "bala"]
const ob = { name : "Piotr" }

console.log(Array.isArray(tab)); //true
console.log(Array.isArray(ob)); //false

console.log(typeof tab); //"object";
console.log(typeof ob); //"object";

Metody push() i pop()

Metoda Array.push(el1, el2*...) wstawia nowy element (lub kilka) do tablicy na jej końcu i zwraca długość nowej tablicy. Elementów wstawianych można podać kilka lub jeden.


const tab = ["Marcin", "Ania", "Agnieszka"];
tab.push("Grzegorz");
tab.push("Piotr", "Karol");

console.log(tab) //["Marcin", "Ania", "Agnieszka", "Grzegorz", "Piotr", "Karol"]

Metoda pop() w przeciwieństwie do push() zabiera ostatni element z tablicy i go zwraca:


const tab = ["Marcin", "Ania", "Agnieszka"];
const last =  tab.pop();

console.log(last); //Agnieszka
console.log(tab); //[Marcin, Ania]

Metody unshift() i shift()

Metoda unshift(el1, el2*...) wstawia nowy element do tablicy na jej początku, po czym zwraca nową długość tablicy. Elementów wstawianych można podać kilka, albo jeden.


const tab = ["Marcin", "Ania", "Agnieszka"];
tab.unshift("Bartek");
tab.unshift("Piotrek", "Paweł");

console.log(tab); //[Piotrek, Paweł, Bartek, Marcin, Ania, Agnieszka]

Metoda shift() natomiast usuwa pierwszy element z tablicy i zwraca jego wartość:


const tab = ["Marcin", "Ania", "Agnieszka"];
const elDeleted = tab.shift();

console.log(tab); //[Ania, Agnieszka]
console.log(elDeleted); //Marcin

Metoda join()

Metoda join(separator) służy do łączenia kolejnych elementów tablicy w jeden wspólny tekst.
Opcjonalnym parametrem tej metody jest separator - tekst, który będzie oddzielał kolejne elementy w utworzonym tekście. Jeżeli go nie podamy będzie użyty domyślny znak przecinka:


const ourTable = ["Marcin", "Ania", "Agnieszka"];

console.log(ourTable.join()); //wypisze się "Marcin,Ania,Agnieszka"

console.log(ourTable.join(" - ")); //wypisze się "Marcin - Ania - Agnieszka"

console.log(ourTable.join("  ")); //wypisze się "Marcin  Ania  Agnieszka"

//Zliczam liczbę liter w tablicy
const cars = ["Mercedes", "Audi", "BMW"];
console.log(cars.join("").length); //15

Zamiana tekstu na tablicę

Skoro zamieniliśmy tablicę na tekst, to spróbujmy zrobić to w drugą stronę. Aby to zrobić, wystarczy użyć składni spread:


const txt = "kartofel";
const tab = [...txt];
console.log(tab); //["k", "a", "r", "t", "o", "f", "e", "l"]

Jeżeli chcielibyśmy tekst podzielić na podstawie znaku podziału, użyjemy tutaj metody split() dostępnej dla stringów:


const txt = "Ala ma kota";
const tab = txt.split(" ");
console.log(tab); //["Ala", "ma", "kota"];

Metoda reverse()

Dzięki metodzie reverse() możemy odwrócić elementy naszej tablicy:


const tab = [1, 2, 3, 4];

console.log("Przed: " + tab); //Przed: [1, 2, 3, 4]
tab.reverse()
console.log("Po: " + tab); //Po: [4, 3, 2, 1]

const word = "kajak";
const tab = [...word];
console.log(tab.reverse().join("") === tab.join("")); //true czyli palindrom

Metody indexOf(), lastIndexOf() i includes()

Wyszukać element w tablicy możemy na kilka sposobów.

Pierwszy z nich polega (podobnie jak w przypadku przeszukiwania stringów) na skorzystaniu z metody indexOf(str).

Metoda ta działa podobnie jak w przypadku stringów. Zwraca indeks na którym znalazła szukany tekst/obiekt, lub -1, jeżeli nic nie znalazła:


const tab = ["Marcin", "Ania", "Agnieszka", "Monika"];

if (tab.indexOf("Ania") !== -1) {
    console.log("Ania występuje w tablicy pod indexem", tab.indexOf("Ania"));
}

Bardzo podobną metodą jest lastIndexOf(), która działa jak indexOf(), ale zwraca ostatnią pozycję szukanego tekstu:


const tab = ["Agnieszka", "Marcin", "Ania", "Agnieszka", "Monika"];
const index = tab.lastIndexOf("Agnieszka");

if (index !== -1) {
    console.log("Ostatnie wystąpienie w tablicy to", index);
}

Podobnie do stringów dla tablic także istnieje funkcja includes(), która zwraca prawdę lub fałsz w zależności czy szukana wartość znajduje się w tablicy:


const tab = ["Marcin", "Ania", "Agnieszka", "Monika"];

if (tab.includes("Ania")) {
    console.log("Ania występuje w tablicy pod indeksem", tab.indexOf("Ania"));
}

if (!tab.includes("Pies")) {
    console.log("Pies nie występuje w tej tablicy");
}

Wszystkich trzech metod możemy użyć także do wyszukiwania obiektów w tablicy, co staje się przydatne, gdy chcemy znaleźć numer np. klikniętego przycisku w stronicowaniu - np. slidera.


const ob = { name : "Jan" }
const things = ["ala", "bala", "cala", ob, "data"];

console.log(things.indexOf(ob)); //3
console.log(things.includes(ob)); //true

//nie musisz rozumieć poniższego kodu - to tylko ukazanie realnego przykładu
const paginationButtons = [...document.querySelectorAll(".pagination-btn")];

paginationButtons.forEach(btn => {
    btn.addEventListener("click", e => {
        const index = buttons.indexOf(btn);
        showSlide(index);
    });
});

Metoda sort()

Metoda Array.sort(fn) służy do sortowania tablic.
Metoda ta przekształca równocześnie tablicę, na której została wykonana.

Powiedzmy, że mamy tablicę z niepoukładanymi wartościami, i chcemy ją posortować:


const tab = ["Marcin", "Ania", "Piotrek", "Grześ"];
tab.sort();

console.log( tab ); //wypisze się "Ania, Grześ, Marcin, Piotrek"

Standardowo JavaScript segreguje tablice leksykograficznie (słownikowo) traktując liczby jak litery.
Powoduje to w wielu przypadkach nieoczekiwane rezultaty:


const tab = [1, 2, 21, 2.1, 32, 3.1];
tab.sort();

console.log(tab); //[ 1, 2, 2.1, 21, 3.1, 32 ]

Ale nie tylko przy liczbach metoda ta się wykrzaczy. Spójrz na poniższy przykład:


const tab = ["Bartek", "ania", "Celina", "agnieszka"];
tab.sort();

console.log(tab); //["Bartek", "Celina", "agnieszka", "ania"]

Powyższy "błąd" wynika z faktu, że duże litery występują przed małymi.

Aby móc posegregować naszą tablicę według własnych kryteriów (przy okazji naprawiając powyższe niedoskonałości), musimy do funkcji sort przekazać własną funkcję sortującą.


function mySort(a, b) {
    ...
}

tab.sort(mySort);

Do funkcji tej przekazane zostaną 2 parametry - dwa kolejne porównywane ze sobą elementy.

Pisząc taką funkcję musimy pamiętać o 3 warunkach:

  • Jeżeli funkcja(a, b) zwróci wartość mniejszą od 0, to wartość a będzie miała mniejszy indeks od b
  • Jeżeli funkcja(a, b) zwróci 0, to indeksy wartości a i b pozostaną bez zmian
  • Jeżeli funkcja(a, b) zwróci wartość większą od 0, to wartość a będzie miała większy indeks od b

Tak więc ogólna postać funkcji sortującej wygląda tak:


function compare(a, b) {
    if (a  b) {
        return 1
    }
    return 0
}

tab.sort(compare);

co też obrazuje poniższy film:

Przy czym puryści Javascript mogli by się przyczepić, że przecież zastosowany w Javascript algorytm sortujący jest bardziej skomplikowany.

Przykładowo aby posegregować wartości liczbowe musimy utworzyć funkcję:


function compareNr(a, b) {
    return a - b
}

const tab = [100, 320, 10, 25, 310, 1200, 400];

const tab3 = tab.sort(compareNr);
console.log( tab3 ); //[10, 25, 100, 310, 320, 400, 1200]

Oczywiście możemy sami wymyślać nasze własne kryteria segregacji (na przykład by cyfry były "mniejsze" od liter, lub też duże litery były "mniejsze" od małych liter...).


const tab = [
    { name: "Marcin" , height : 183 },
    { name: "Ania" , height : 173 },
    { name: "Agnieszka" , height : 170 },
]

//dla sort spokojnie możemy używać funkcji anonimowej
tab.sort(function(a, b) {
    return a.height - b.height;
});

console.log(tab);

W powyższych przykładach sortowaliśmy po liczbach. Jeżeli podczas takiego sortowania chcielibyśmy porównać 2 stringi, odejmowanie raczej tutaj nie zadziała. O wiele lepszym rozwiązaniem będzie użycie metody localeCompare():


const tab = [
    { name: "Marcin" , height : 183 },
    { name: "Ania" , height : 173 },
    { name: "Agnieszka" , height : 170 },
]

tab.sort(function(a, b) {
    //tekstów nie możemy odejmować. Możemy je porównywać poprzez > 

Dzięki temu, że możemy przekazać własną funkcję, sortować możemy każdy rodzaj tablicy:


const mails = [
    "marcin@wp.pl",
    "marcin@gmail.pl",
    "marcin@onet.pl",
    "marcin@interia.pl"
]

//sortuje po domenach
//z użyciem funkcji strzałkowej
mails.sort((a, b) => {
    const aDomain =  a.substr(a.indexOf("@"));
    const bDomain =  b.substr(b.indexOf("@"));
    return aDomain.localeCompare(bDomain);
})

console.log(mails);

const users = [
    {
        name : "Marcin",
        car : {
            name : "Toyota",
            age : 10
        }
    },
    {
        name : "Marcin",
        car : {
            name : "Fiat",
            age : 15
        }
    },
    {
        name : "Monika",
        car : {
            name : "BMW",
            age : 5
        }
    },
]

//sortuje po wieku samochodu
users.sort((a, b) => {
    return a.car.age - b.car.age
});

console.log(users);

Łączenie tablic

Do połączenia (scalenia) tablic nie możemy użyć zwykłego dodawania (tak samo nie możemy odejmować tablicy od tablicy):


const tab1 = ["Ala", "Basia"];
const tab2 = ["Piotr", "Marcin"];
console.log(tab1 + tab2); //Ala,BasiaPiotr,Marcin

Wynikiem jest string. Zadziałała tutaj automatyczna konwersja typów z wykorzystaniem metody toString(). Tak czy siak wynik jest błędny.

Aby połączyć ze sobą kilka tablic wykorzystamy metodę concat(), która jako parametr przyjmuje jedną lub kilka tablic:


const anim1 = ["Pies", "Kot"];
const anim2 = ["Słoń", "Wieloryb"];
const anim3 = ["Chomik ninja", "Świnka morderca"];

const table = anim1.concat(anim2);
console.log(table); //wypisze ["Pies", "Kot", "Słoń", "Wieloryb"]

const tableBig = anim1.concat(anim2, anim3);
console.log(tableBig); //wypisze ["Pies", "Kot", "Słoń", "Wieloryb", "Chomik ninja", "Świnka morderca"];

W dzisiejszych czasach o wiele przyjemniejszą metodą jest użycie użytego już przez nas spread syntax:


const anim1 = ["Pies", "Kot"];
const anim2 = ["Słoń", "Wieloryb"];
const table = [...anim1, ...anim2];
console.log(table)

Metoda slice()

Metoda Array.slice(od, do*) tak samo jak przy stringach, zwraca kawałek tablicy na której została wywołana. Pierwszy parametr od wskazuje na indeks, od którego ma "wyciąć" elementy, a do analogicznie wskazuje indeks do jakiego będziemy ciąć. Jeżeli go nie podamy, zostanie wycięty kawałek od danego indeksu do końca tablicy.


const tab = ["Marcin", "Ania", "Agnieszka", "Monika", "Magda"];

const tab2 = tab.slice(0, 1);
console.log(tab2); //["Marcin"]
console.log(tab); //["Marcin", "Ania", "Agnieszka", "Monika", "Magda"]

const tab3 = tab.slice(2);
console.log(tab3); //["Agnieszka", "Monika", "Magda"]

const tab4 = tab.slice(0, 5);
console.log(tab4); //["Marcin", "Ania", "Agnieszka", "Monika", "Magda"]

const tab5 = tab.slice(-2); //od końca
console.log(tab5); //["Monika", "Magda"]

const tab6 = tab.slice(2, -1);
console.log(tab6); //["Agnieszka", "Monika"]

Metoda splice()

Metoda splice(index, ileUsunąć, noweElementy*...) służy zarówno do usuwania jak i wstawiania nowych elementów do tablicy.
Parametr index określa miejsce w tablicy od którego zacznie się usuwanie elementów.
Parametr ileUsunąć mówi ile elementów powinno być usuniętych z tablicy. Jeżeli podamy 0, wtedy nic nie zostanie z tablicy usunięte.
Opcjonalne parametry elementyWstawiane to elementy, które będą wstawiane tuż przed usuwanymi elementami, lub tuż przed danym elementem, jeżeli nic nie usuwamy.


const tab = ["Marcin", "Ania", "Agnieszka", "Monika"];

tab.splice(2, 1); //usuwam 1 element na indeksie 2
console.log(tab); //["Marcin", "Ania", "Monika"]

const tab = ["Marcin", "Ania", "Agnieszka", "Monika"];

tab.splice(1, 0, "A", "B") //nic nie usuwam i wstawiam nowe elementy przed indeks 1
console.log(tab); //["Marcin", "A", "B", "Ania", "Agnieszka", "Monika"]

const tab = ["pies", "kot", "chomik", "aligator", "świnka", "kanarek"];

const index = tab.indexOf("aligator"); //szukamy miejsce niepasującego zwierzaka
if (index >= 0) {
    tab.splice(index, 1);
    console.log(tab); //["pies", "kot", "chomik", "świnka", "kanarek"];
}

Metoda fill()

Funkcja fill() służy do wypełniania tablicy. Pierwszy jej parametr to wartość, którą zostanie wypełniona tablica. Dwa pozostałe opcjonalne parametry wskazują na indeks początku i końca wypełniania. Jeżeli nie podamy indeksu kończącego, tablica zostanie wypełniona od indeksu początkowego do swojego końca.


const tab = new Array(20);
console.log(tab); //[empty x 20]
tab.fill("kot");
console.log(tab); //["kot", "kot", "kot", ...]
console.log("co" + tab.join("")) //"cokotkotkotkot..."


const tab2 = [];
tab2.length = 15;
console.log(tab2); //[empty x 15]
tab2.fill("kot", 2, 5);
console.log(tab2); //[empty × 2, "kot", "kot", "kot", empty × 10]


const tab3 = [1, 2, 3, 4, 5];
tab3.fill("pies", 2);
console.log(tab3); //[1, 2, "pies", "pies", "pies"]

Przemieszczanie się po tablicy

Jedną z najwspanialszych rzeczy, jakie dają nam tablice to możliwość wykonywania masowych operacji na wszystkich elementach w tablicy.

Aby zrobić pętlę po tablicy możemy skorzystać z kilku zapisów. Jednym z nich jest użycie klasycznych pętli for/while:


const tab = ["Marcin", "Ania", "Agnieszka"];

for (let i=0; i<tab.length; i++) {
    console.log("licznik pętli: " + i); //0, 1...
    console.log(tab[i]); //"Marcin", "Ania"...
}

Widzisz jak się odwołuję do danego elementu tablicy? Skoro licznik i zwiększa się od 0 do tab.length-1, to mogę za jego pomocą pobierać kolejne elementy tablicy czyli tab[0], tab[1]... i tak do tab[tab.length-1]


const tab = ["Marcin", "Ania", "Agnieszka"];

for (let i=0; i<tab.length; i++) {
    const el = tab[i];
    console.log(el.toUpperCase()); //"MARCIN", "ANIA"...
}

Oczywiście pętlę while też możemy zastosować, przy czym wykorzystanie jej dla iterowania po tablicy jest mało spotykane.

Iterowanie po tablicach to tak częsta rzecz, że w Javascript mamy na to kilka możliwości.

W dzisiejszych czasach możemy też zastosować o wiele przyjemniejszą pętlę for of, która automatycznie wyłapie nam odpowiedni element z tablicy (nie musimy odwoływać się poprzez tab[i]):


const tab = ["Marcin", "Ania", "Agnieszka"];

for (const el of tab) { //el to nazwa zmiennej wymyślona przez nas
    console.log(el); //"Marcin", "Ania"...
}

for (const xxx of tab) { //xxx to nazwa zmiennej wymyślona przez nas
    console.log(xxx.toUpperCase()); //"MARCIN"...
}

for (let lorem of tab) { //niektórzy używają tutaj let zamiast const
    console.log(lorem);
}

Pętla ta jest na tyle wygodna, że w kolejnych rozdziałach (szczególnie DOM) dość często będę z niej korzystał.

Innym sposobem wykonywania zbiorczych operacji na tablicach jest zastosowanie metod iteracyjnych takich jak forEach(). Omówimy je w kolejnym rozdziale.

Tablice wielowymiarowe

Skoro tablice mogą w sobie trzymać dowolne wartości, mogą także przetrzymywać obiekty, lub... kolejne tablice. Taki twór zwie się tablicami wielowymiarowymi.


const tab = [
    ["a1", "a2", "a3", "a4", "a5", "a6"],
    ["b1", "b2", "b3", "b4", "b5", "b6"],
    ["c1", "c2", "c3", "c4", "c5", "c6"],
]

console.log(tab[0]); //["a1", "a2", "a3", "a4", "a5", "a6"]
console.log(tab[0].length); //6
console.log(tab[0][1]); //"a2"
console.log(tab[2][3]); //"c4"

Do czego takie wielowymiarowe tablice mogą się przydać? Przykładowo do przetrzymywania danych:


const tab = [
    ["Marcin", 183, "red", "kot"],
    ["Ania", 173, "blue", "pies"],
    ["Agnieszka", 170, "yellow", "świnka"]
]

console.log(`
    imię:       ${tab[0][0]}
    wzrost:     ${tab[0][1]}
    kolor:      ${tab[0][2]}
    zwierzak:   ${tab[0][3]}
`);

Powyższy przykład nie jest idealny. Trzymanie w taki sposób danych tego typu to proszenie się o problemy. Po pierwsze musimy pamiętać kolejność indeksów dla każdej danej. Druga sprawa to potencjalna możliwość zmiany kolejności indeksów. Problemy te rozwiązują obiekty, o których sobie jeszcze porozmawiamy.

Nie oznacza to jednak, że takie wielowymiarowe tablice nie mają zastosowania. Mają - i to całkiem duże.

Wystarczy chociażby spojrzeć praktycznie na dowolną grę. Większość map poziomów w takich grach zbudowana jest na bazie właśnie tablic wielowymiarowych, gdzie każdy indeks wewnętrznych tablic zawiera informację na temat użytej w danym miejscu grafiki czy wystąpienia ściany.

level mario

Tutaj mała ciekawostka. Wielu artystów nie tworzy takich tablic za pomocą kodu, a raczej korzysta ze specjalnych edytorów, które służą do układania grafiki na planszy. Są to np. https://www.mapeditor.org/, lub tiled, ale też wiele z popularnych narzędzi w świecie gamedevu ma swoje wbudowane edytory.

Spróbujmy wyświetlić jedną z takich przykładowych tablic na ekranie konsoli debugera:


const level = [
    [1, 1, 0, 0, 2, 2, 0, 0, 1, 1],
    [1, 0, 0, 0, 2, 2, 0, 0, 0, 1],
    [1, 0, 1, 1, 2, 2, 1, 1, 0, 1],
    [1, 0, 2, 2, 2, 2, 2, 2, 0, 1],
    [2, 2, 2, 2, 1, 1, 2, 2, 2, 2],
    [2, 2, 2, 2, 1, 1, 2, 2, 2, 2],
    [1, 0, 2, 2, 2, 2, 2, 2, 0, 1],
    [1, 0, 1, 1, 2, 2, 1, 1, 0, 1],
    [1, 0, 0, 0, 2, 2, 0, 0, 0, 1],
    [1, 1, 0, 0, 2, 2, 0, 0, 1, 1]
];


let str = "";

for (const subTab of level) {
    //pod subTab mamy każdą kolejną podtablicę

    for (const el of subTab) {
        switch (el) {
            case 0 : str += "🟩"; break;
            case 1 : str += "🟫"; break;
            case 2 : str += "⬛"; break;
        }
    }

    str += "\n";
}

console.log(str);

W naszym przypadku w tablicy są tylko wartości 0/1/2. W praktyce musiały by się tam znaleźć indeksy każdej grafiki użytej do zrobienia danej planszy, a i przydało by się tutaj dodać kilka funkcji rysujących realną planszę.

I tu się pojawia smutek autora. Chciałbym wam teraz pokazać jakiś bardziej realny przykład, ale wymagało by to sięgnięcia po bardziej zaawansowaną wiedzę, którą poznamy w późniejszych rozdziałach. Przyjdzie pora i na to.

Metoda flat()

Jeżeli chcemy spłaszczyć wielowymiarową tablicę, zastosujemy funkcję flat(). Jedyny jej parametr służy do określenia ile poziomów mamy spłaszczyć:


const tab = [
    1,
    [2,3],
    [4,5,[6,7]],
    [[[8,9], [10,11]]]
]

console.log(tab.flat(1));
tablice flat 1 poziom

const tab = [
    1,
    [2,3],
    [4,5,[6,7]],
    [[[8,9], [10,11]]]
]

console.log(tab.flat(2));
tablice flat 2 poziom

Jeżeli chcemy mieć pewność, że uzyskamy płaską 1 wymiarową tablicę, jako liczbę poziomów podajmy Infinity:


const tab = [
    1,
    [2,3],
    [4,5,[6,7]],
    [[[8,9], [10,11]]]
]

console.log(tab.flat(Infinity)); //[1,2,3,4,5,6,7,8,9,10,11]

Array.from()

Metoda Array.from(ob, map*, this*) służy do tworzenia tablic z obiektów tablico podobnych. Obiekty takie są podobne do tablic, ale równocześnie nimi nie są. Przykładem takiego obiektu są kolekcje elementów pobranych ze strony, argumenty funkcji (arguments), czy np. classList dla elementów na stronie. Będziemy się o nich uczyć w kolejnych rozdziałach.


const ob = {
    0 : "ala",
    1 : "bela",
    length: 2
}

console.log(Array.from(ob)); //["ala", "bela"]

//pobieram kolekcję buttonów ze strony
const buttons = document.querySelectorAll("button");
console.log(buttons); //NodeList [button, button...]

const tab = Array.from(buttons);
console.log(tab); //Array [button, button...]

Drugi opcjonalny parametr tej funkcji może zawierać funkcję map() dla tablic:


const ob = {
    0 : "ala",
    1 : "bela",
    length: 2
}

const tab = Array.from(ob, function(el) {
    return el.toUpperCase()
});
console.log(tab); //["ALA", "BELA"]

Trzeci - równie opcjonalny parametr wskazuje na this. Działa on podobnie do stosowanego w przypadku metod dla tablic. W praktyce w większości przypadków używany jest tylko pierwszy parametr czyli obiekt, który poddajemy konwersji (tak jak w pierwszym przykładzie).

W dzisiejszych czasach w wielu przypadkach zamiast powyższej metody możemy skorzystać ze spread syntax:


const buttons = document.querySelectorAll("button");
console.log(buttons); //NodeList [button, button...]

const buttonsTabA = [...buttons]; //array
const buttonsTabB = Array.from(buttons); //array

Różnica między spread syntax a Array.from() jest taka, że tą drugą możemy zastosować dla obiektów tablico podobnych, które nie mają zaimplementowanej własnej funkcji iterującej:


const ob = { 0: "a", 1: "b", length: 2 };

console.log(Array.from(ob)); //["a", "b"]

console.log([...ob]); //ob[Symbol.iterator] is not a function

Spokojnie. Nie musisz się teraz skupiać na bardzo dokładnym poznaniu każdego aspektu działania tej metody. Wszystko przyjdzie z czasem.

Wszelkie prawa zastrzeżone. Jeżeli chcesz używać jakiejś części tego kursu, skontaktuj się z autorem.
Aha - i ta strona korzysta z ciasteczek.