Jako, że ostatnim wpisem zakończyłem omawianie zagadnień związanych z manipulowaniem strukturą dokumentu oraz obiektami, w dzisiejszym poście przejdę do drugiego z czterech głównych tematów związanych z egzaminem 70-480. Mowa tutaj o “implementacji przepływu programu” (ang. Implement Program Flow) sterowanie prze, który to temat ma stanowić 25% wszystkich pytań na egzaminie. Zapraszam więc na pełne objaśnienie jak wygląda sterowanie przepływem operacji w JavaScript!

W związku z powyższym, wpis dzisiejszy zawierać będzie omówienie sposobów iterowania po kolekcjach i elementach tablic, zajmiemy się także podejmowaniem decyzji (a więc konstrukcje switch, if/else i operatory), a na koniec przyjrzymy się funkcji ‘eval’.

Tyle tytułem wstępu, przejdźmy do rzeczy.

Iterowanie po elementach tablic

Temat iterowania się po tablicach jest dość prosty i podobny do innych języków. Standardowy sposób to użycie pętli ‘for’:

var months = ['January', 'February', 'March'];

// petla
for (var i = 0; i < months.length; i++) {
    alert(months[i]);
}

Inny sposób

Myślę, że powyższy kod nie wymaga wyjaśnień ;) Jednak pętlę ‘for’ można też użyć w trochę inny sposób:

var months = ['January', 'February', 'March'];

// petla
for (var i in months) {
    alert(months[i]);
}

W tym przypadku mamy do czynienia z czymś podobnym do pętli ‘foreach’ w innych językach programowania - z tą różnicą, że do ‘i’, przy każdym przebiegu pętli przypisywany jest index elementu a nie jego konkretna wartość.

Wykorzystanie do tablic asocjacyjnych

Tak zadeklarowana pętla ma zastosowanie w przypadku tablic asocjacyjnych (tak na prawdę język JavaScript ich nie posiada, ale dzięki temu, że wszystko jest obiektem, można taką tablicę łatwo zasymulować). Spójrzmy na kolejny przykład:

var array = [];
array['one'] = 'First';
array['two'] = 'Second';
array['three'] = 'Third';
for (var index in array) {
   alert(array[index]);
}

// to jest bardziej prawidlowy zapis:
var obj = {};
obj.one = 'First';
obj.two = 'Second';
obj.three = 'Third';
for (var ind in obj) {
  alert(obj[ind]);
}

W powyższym przykładzie definiujemy tablicę ‘array’ a następnie przypisujemy trzy wartości do indeksów (które nie są kolejnymi liczbami tylko ciągami znaków - tak jak w tablicy asocjacyjnej). Następnie iterujemy po tej tablicy.

Jednak, tak jak widać powyżej (od linii dziewiątej do końca), to co zostało zrobione wcześniej to tak na prawdę iterowanie po poszczególnych właściwościach obiektu (przy okazji widzimy, że to też jest możliwe za pomocą pętli ‘for’). Mimo, że w pierwszej linii tworzymy tablicę ‘array’, to w dalszej części traktujemy ją jak zwykły obiekt przypisując poszczególne wartości do jej właściwości (nie są one tak na prawdę elementami tablicy) - jak widać zamiast “array[‘one’]” moglibyśmy równie dobrze napisać “array.one”.

Iterowanie za pomocą funkcji forEach obiektu Array

Istnieje jeszcze jeden sposób na iterowanie się po tablicach - jako, że tablica jest jednym z obiektów natywnych (Array; patrz poprzedni post), dostarcza nam zestaw predefiniowanych metod. Jedną z nich jest metoda ‘forEach’. Najlepiej zobaczmy na przykładzie, jak działa:

var alertElement = function (value, index) {
   alert('[' + index + '] = ' + value);
};

var array = [1,'dwa',3,'cztery',5];

array.forEach(alertElement);

Najpierw popatrzmy na koniec, na linię siódmą - na rzecz zdefiniowanej w linii piątej tablicy, wywołujemy funkcję ‘forEach’. Jak widać, metoda ta, jako parametr wejściowy przyjmuje referencję do funkcji, która będzie wykonywać zadanie dla każdego z elementów tablicy. Możemy zauważyć, że w ramach tejże funkcji (zdefiniowanej w liniach od pierwszej do trzeciej), mamy dostęp do aktualnej wartości i indexu danego elementu tablicy.

Wyrażenia warunkowe

Myślę, że tematyka wyrażeń warunkowych jest dobrze znana nawet początkującym programistom, a w JavaScript nie różni się znacząco w tej kwestii od innych języków programowania, dlatego myślę, że wystarczy jak w tym paragrafie zamieszczę tylko mówiące same za siebie przykłady wyrażeń warunkowych.

if/else

Poniżej przykład dla wyrażenia “if/else”:

var x = Math.random() * 100;

if (x < 50) {
  alert(x + ' mniejsze niz 50!');
} else if (x == 50) {
  alert(x + ' rowne 50!');
} else {
  alert(x + ' większe niż 50!');
}

Tak jak napisałem wcześniej, myślę że nie ma tutaj czego komentować. Nadmienić można ewentualnie, że w JavaScript, “else if” widoczna tutaj w linii piątej powstaje poprzez użycie dwóch słów kluczowych (a nie jak to jest w niektórych językach poprzez użycie specjalnego słowa kluczowego “elseif”).

switch/case

Kolejny przykład to konstrukcja “swith/case”:

var x = Math.round(Math.random());

switch(x) {
  case 0:
    alert('Mniej niż 0.5')
    break;
  case 1:
    alert('Wiecej niż 0.5')
    break;
  default:
    alert('Żadne z powyższych');
}

Jak widać, konstrukcja “swich/case” nie różni się niczym od tej znanej z C# czy Javy, dlatego pozostawię ją bez komentarza.

Operatory porównania

Będąc przy wyrażeniach warunkowych, należy też wspomnieć o operatorach porównania - używa się ich przecież podczas definiowania wyrażeń “if/else”. Oto operatory porównania dostępne w JavaScript:

  • == - sprawdzenie czy wyrażenia są sobie równe
  • === - sprawdzenie czy wyrażenia są dokładnie równe (wartość i typ)
  • != - sprawdzenie czy wyrażenia nie są sobie równe
  • !== - sprawdzenie czy wyrażenia są dokładnie różne (wartość i typ)
  • > - sprawdzenie czy wyrażenie po lewej jest większe od tego po prawej
  • < - sprawdzenie czy wyrażenie po lewej jest mniejsze od tego po prawej
  • >= - sprawdzenie czy wyrażenie po lewej jest większe lub równe od tego po prawej
  • <= - sprawdzenie czy wyrażenie po lewej jest mniejsze lub równe od tego po prawej

Myślę, że większość jest znana z innych języków i nie wymaga wyjaśnienia. Warto jedynie, bliżej przyjrzeć się wyrażeniom “===” oraz “!==”, które nie występują np. w C#. Najlepiej zobaczyć to po prostu na przykładzie:

var x = 7;

// ===
alert(x === 7); // true
alert(x === 5); // false
alert(x === '7'); // false

// ale...
alert(x == '7'); // true !!!

// !==
alert(x !== 7); // false
alert(x !== 5); // true
alert(x !== '7'); // true (!)

// ale...
alert(x != '7'); // false !!!

Tak jak wcześniej opisałem, operator “===” służy do dokładnego porównania wartości uwzględniając również typ wartości - jak widać więc w linii szóstej, porównanie zwraca ‘false’, ponieważ ‘x’ jest typu ‘int’, a wartość po prawej jest typu ‘string’. Dla porównania, w linii dziewiątej widzimy użycie w tym samym kontekście operatora “==”. Tym razem typ nie miał znaczenia i porównania zwróciło wartość ‘true’.

Drugi rozpatrywany operator to “!==”. Tym razem zwróćmy uwagę na linię czternastą - tutaj porównanie zwraca wartość ‘true’ ponieważ typy wartości się różnią. Dla porównania, w linii siedemnastej użyto w tym samym kontekście operatora “!=”, i tym razem również typ nie miał znaczenia.

Metoda eval()

Ostatnim poruszanym przeze mnie w dzisiejszym wpisie zagadnieniem jest użycie metody ‘eval()’. Funkcja ta, zdefiniowana jest w obiekcie ‘window’ dlatego dostępna jest globalnie z każdego miejsca. Jako parametr wejściowy może ona przyjmować równania, które są za jej pomocą wyliczane. Może także przyjmować wyrażenia, np. kod JavaScript - w takim przypadku kod taki zostanie wykonany. Spójrzmy na prosty przykład:

eval('x =1 ; y = 2; alert(x + y)');
alert(eval(4 * 5));

W pierwszej linii mamy przykład wykonania przez metodę ‘eval()’ kodu JavaScript, podanego w postaci ciągu znaków - wynikiem wykonania tej linii jest wyświetlenie na ekranie okienka z liczbą 3. W drugiej linii przykład obliczenia równania - w tym przypadku na ekranie pojawi się liczba 20.

Jak łatwo się domyślić, użycie tej funkcji nie jest zalecane, ponieważ zdecydowanie jest błędogenne i utrudnia debugowanie. Ponadto jest mniej wydajne ponieważ kod taki nie może zostać zoptymalizowany przed wykonaniem oraz wymaga od przeglądarki utworzenia całkiem nowego środowiska skryptowego, w którym wyrażenie lub równanie zostanie wykonane (patrz How evil is eval).

Sterowanie przepływem operacji - podsumowanie

To tyle jeśli chodzi o kontrolowanie przepływu wykonania programu. W kolejnym “odcinku” zajmiemy się wywoływaniem i obsługą zdarzeń w języku JavaScript. Zapraszam!