wtorek, 22 kwietnia 2014

Ach ten Javascript



Być może rzadko widać w ofertach pracy aby wymagano bezpośrednio znajomości  języka Javascript, tylko zamiast tego wypisane są oczekiwania odnośnie znajomości framework-ów Javascript  typu Angularjs,  Backbone, Ember.js, ale czy to oznacza, że nie należy się go uczyć?  

Posługując się grafem ze strony indeed.com, widać jak zmieniają się tendencje w ofertach pracy dla języka Javascript oraz opartych na nim rozwiązaniach.



Można zauważyć, że sam Javascript jest prawie niewidoczny na tym grafie,  króluje AnugularJs i Node.Js mimo to nie wyobrażam sobie, żeby pisać w jakiejkolwiek z tych bibliotek/framework-ów dobry kod bez porządnej znajomości języka Javascript. Owszem język Javascript ma to do siebie, ze można w nim zacząć pisać bez wnikania w mechanizmy działania samego języka, napisany kod może działać, nie mówię nie, ale kiedy tego kodu przybędzie, i zaczną pojawiać się błędy i zaczniemy debugować, może się okazać, że nie mamy pojęcia dlaczego coś nie działa i najczęściej obwiniamy za ten stan sam język a nie brak własnej wiedzy.

Nie ukrywam były lata kiedy nie lubiłem pisać w javascriptcie, na studiach traktowałem to jako zło konieczne, bo ciągle się frustrowałem że coś nie działa. Później pojawiło się jQuery i bam .. no teraz to ja umiem pisać w javascriptcie sobie myślałem.... (co oczywiście było moim pochlebnym marzeniem), owszem umiałem pisać  ale w jQuery a o javascriptcie ciągle wiedziałem nie wiele i wychodziło to przy prawie każdym błędzie który musiałem poprawiać...

Poniżej podaje dwa proste przykłady które pokazują, że bez znajomości javascriptu można spędzić bardzo dużo czasu analizując dlaczego nasz kod nie działa.

 
1. przykład
for (var i = 0; i < 5; i++)
{
    setTimeout( function(){ console.log(i)},0); 
}; 

2. przykład
var obj = ( function(){ 

    return 
    { 
        name:'Łukasz' 
    }; 

}()); 

console.log(obj.name);

Jak widać kod jest bardzo prosty. 

W pierwszym przypadku można by oczekiwać, że napisany kod zwróci nam na konsoli cyfry 0, 1, 2, 3, 4, zatem wprowadźmy ten kod np. do konsoli w Chromie i sprawdźmy wynik....


Wynik pokazuje zupełnie coś innego, nie tego się spodziewaliśmy (w prezentowanym wyniku ignorujemy liczbę 87, która jest identyfikatorem timera zwróconym przez funkcję setTimeOut, fakt wyświetlenie tej wartości wynika ze sposobu obsługi konsoli w przeglądarce Chrome). W wyniku otrzymaliśmy cyfrę 5 powtórzoną 5 razy o czym świadczy cyfra pięć w kółeczku z lewej strony. Aby zrozumieć dlaczego otrzymaliśmy taki wynik, należy zrozumieć następujące fakty:
  • Dysponujemy tylko jedną zmienną i zadeklarowaną w globalnym zakresie (ang. scope) widoczności zmiennych w języku JavaScript (lub w zakresie najbliższej funkcji, jeżeli ten kod umieścilibyśmy w funkcji), każda iteracja pętli nie tworzy nam nowej kopii zmiennej i zamkniętej w zakresie pętli (co sugeruje użyty kod), ponieważ nie tak działa zakres w Javascript (ale o tym przy innej okazji..)
  • Po zakończeniu pętli zmienna i === 5, ponieważ jest to warunek przerywający pętle i < 5
  • Każda z pięciu stworzonych funkcji obsługujących timer zostanie wywołana po zakończeniu pętli for, ponieważ funkcje obsługujące zdarzenia (ang. event handlers) są kolejkowane i zostaną obsłużone  kiedy aktualnie wykonywany kod Javascript zostanie zakończony
Mam nadzieję, że udało mi się to wyjaśnić ;), zatem jak możemy poprawić ten kod aby używając timera wypisać cyfry 0, 1, 2, 3, 4? Musimy w każdej iteracji pętli stworzyć nowy zakres z kopią wartości zmiennej i, jak to osiągnąć? Używając bardzo popularnej konstrukcji w javascriptcie o ładnym skrócie IIFE (Immediately-Invoked Function Expression), czyli funkcja która jest natychmiast wywoływana.

Tak prezentuje się poprawiony kod ..
  

for (var i = 0; i < 5; i++){ 

  (function( j ) {

    setTimeout( function(){ console.log(j)}, 0); 

   }(i));

};

a tak prezentuje się wynik działania poprawionego kodu


A teraz wracam do drugiego przykładu, który jest naprawdę prosty, tworzę sobie obiekt, który ma właściwość name z przypisaną do niej wartością. Następnie na konsoli chcę wypisać właściwość name dla nowo utworzonego obiektu, zobaczmy to w konsoli....


A co to?

Co się stało? Jak to zwykle bywa diabeł tkwi w szczegółach. Jedną z wbudowanych w język Javascript funkcjonalności jest automatyczne wstawianie średnika na końcu linii. Silnik Javascript chce być bardzo pomocny dla programisty. Jeżeli w kodzie występuje linia kodu bez średnika na końcu, to silnik Javascript analizuje czy wstawienie średnika nie spowoduje błędu składniowego analizując kolejną linię kodu, jeżeli stwierdzi, że błąd nie występuje, to śpieszy z pomocą i sam wstawia za programistę średnik na końcu linii. Czyli patrząc okiem silnika Javascript nasz kod wygląda tak.

var obj = ( function(){ 

    return; 
    { 
        name:'Łukasz' 
    }; 

}()); 


Fragment { name: 'Łukasz' }; nigdy nie zostanie wywołany. Szukanie tego typu błędów może być koszmarem. Rozwiązanie jest bardzo proste wystarczy otwierający nawias klamrowy pisać z prawej strony. Poniżej umieściłem wynik poprawionego kodu.



Javascript jest potężnym językiem, ale bez jego znajomości analiza pojawiających się błędów może być koszmarem, dlatego uważam, że warto poświęcić czas aby poznać ten język i jego mechanizmy, tym bardziej, jeżeli chcemy używać rozwiazań na nim opartych, typu AngularJs, Backobone.js, Sencha Touch i innych.

No moim blogu, w ramach własnego poznawania języka Javascript będę się starał umieszczać posty przybliżające innym ten język programowania.

Brak komentarzy:

Prześlij komentarz