Profesjonalny JavaScript
dla Programistów Javy



Grzegorz Borkowski
JavaScript – podstawy


 Najlepsza wg mnie książka na temat JavaScriptu jako języka programowania:
 JavaScript: The Good Parts by Douglas Crockford (O‟Reilly)
  Polskie wydanie: JavaScript - mocne strony (Helion)


 JavaScript używa składni podobnej do Javy - ale to zmyłka, bo na tym podobieństwa się
 kończą; JavaScript jest kompletnie innym typem języka, bliżej mu do języków funkcjonalnych.


 JavaScript jest używany zazwyczaj w środowisku DOM, a DOM jest niewygodny w użyciu
 JavaScript ma wiele błędów i wad, ale ma też mocne strony




         © Rule Financial 2011                                                                 2
JavaScript – podstawy


 Zmienne - var:
 var x = 5;
 Zmienne mają zasięg funkcji:
 function test() {
     var x = 5;
 }
 alert(x) ; //x undefined


 Jeśli zapomnimy słowa var, zmienna stanie się globalna! Również var poza jakąkolwiek
 funkcją da zmienną globalna:
 x = 5;       // zmienna globalna!
 var y = 6; // zmienna globalna jeśli poza funkcją!



         © Rule Financial 2011                                                           3
Obiekty


 Wszystko jest obiektem, lub typem prostym (primitive type)
 Typy proste (strings, numbers, booleans) są niezmienne
  Obiekty są zmienne


 Obiekty są po prostu mapami (kolekcje klucz-wartość)
  Dostęp do atrybutów obiektu poprzez notację kropkową (dot notation) lub klamrową
   (bracket notation)




         © Rule Financial 2011                                                        4
Obiekty


 Dot notation i bracket notation:
  var tree = {};                 // pusty obiekt
  tree.type = 'oak';
  tree.height = 10.34;   //to samo co: tree[“height”] = 10.34
  var weightPropertyName = 'weight';
  tree[weightPropertyName] = 5;                    //to samo co tree.weight = 5 lub tree['weight'] = 5


 Możemy też zdefiniować to wszystko jedną instrukcją za pomocą takiego literału obiektowego:
  var tree = {
     type : "oak",
     height : 10.34,
     weight : 5
  };
 Literał obiektowy a JSON



         © Rule Financial 2011                                                                           5
Prototyp


 Obiekt „dziedziczy” swój prototyp
 var x = {}; //dziedziczy z Object.prototype
 Object.prototype.msg = 'from prototype!';
 alert("x: " + x.msg); //from prototype!
 var y = {};               //również dziedziczy z Object.prototype
 alert("y: " + y.msg); //from prototype!
 x.msg = 'overriden!';
 alert("x: " + x.msg); //overriden!
 alert("y: " + y.msg); //from prototype!
 delete(x.msg);
 alert("x: " + x.msg); //from prototype!




         © Rule Financial 2011                                       6
Tablice


 Tablica jest specjalnym typem obiektu (czyli mapy), gdzie kluczami są liczby całkowite
 W JavaScripcie nie ma tablic takich jak w Javie, opartych o blok pamięci


 Tablice mają swój własny literał []:

  var books = []; // pusta tablica
  books = ['JavaScript in practice',
           'UML for the beginners',
           {name: 'Java tutorial', format: 'ebook'}];
  var size = books.lenth; // 3
  books[1000] = 'Learn programming in one day';
  size = books.length; // 1001




          © Rule Financial 2011                                                            7
Funkcje


 Funkcje są specjalnymi typami obiektów  są więc mapami  mogą więc zawierać właściwości
 jak każdy inny obiekt, a właściwość może być funkcją!
 Funkcje mogą być wywoływane. W związku z tym mają one dwie specyficzne właściwości:
  Kod funkcji
  Kontekst funkcji (w momencie jej wywołania) określający na co wskazują specjalne zmienne
   „this‟ i „arguments‟, oraz jakie inne zmienne są dostępne




        © Rule Financial 2011                                                                 8
Funkcje


 Funkcje mają swój literał:
  var myFunction = function() {
   alert('function has been called!');
  }
 Funkcje są mapami, więc mogą mieć atrybuty jak każdy obiekt:
  myFunction.isCodeComplete = false;
 Opcjonalnie mogą mieć nazwę (która prawie do niczego nie służy):
  var myFunction = function myFunction() { … }
 Zapis instrukcji funkcji:
  function myFunction() { … }
   Niemal równoważny zapis z funkcją anonimową (preferowany):
  var myFunction = function() { … }



          © Rule Financial 2011                                      9
Referencja do funkcji a wywołanie funkcji


 Funkcja jest dostępna jako zmienna – ta zmienna jest referencją do funkcji
 var myFunction = function() {
    return 'result';
 }
 myFunction powyżej jest zmienną będącą referencją do funkcji
 Można tę referencję przekazać:
 var myFunctionAlias = myFunction;              //myFunctionAlias jest funkcją
 lub wywołać funkcję i przekazać jej wynik:
 var myFunctionResult = myFunction();               //myFunctionResult jest łańcuchem „result”




         © Rule Financial 2011                                                                   10
Wzorzec wywołania metody


 Funkcja zadeklarowana jaka właściwość obiektu jest nazywana metodą (tego obiektu)
 var myObject = {
  name : 'An object',
  action : function(count) {
      alert(this.name ? this.name + count : 'no name!');
  }
 } //obiekt myObject ma metodę “action”


 wzorzec wywołania metody:
 myObject.action(5); //wyświetla “An object5”
 więc „this‟ będzie wskazywać na myObject gdy wywołamy funkcję w ten sposób




         © Rule Financial 2011                                                        11
Wzorzec wywołania funkcji


 Weźmy ten sam obiekt:
 var myObject = {
   name : 'An object',
   action : function(count) {
      alert(this.name ? this.name + count : 'no name!');
   }
 }
I zamiast wywoływać funkcję jako metodę:
 myObject.action(5);
zróbmy tak:
 action(5);      // co wyświetli?
 var x = myObject.action;
 x(5);      // co wyświetli?
Jest to wzorzec wywołania funkcji; this wskazuje na obiekt globalny (window)


         © Rule Financial 2011                                                 12
Wzorzec wywołania funkcji


 Czemu to może być problematyczne? Zobaczmy na przykładzie:
 var messanger = {
   message: 'hey',
   printMessage: function() {
      …
      var printer = function() {
         alert(this.message);
      }
      printer();
   }
 }
 messanger.printMessage(); //wyświetla „undefined‟ - dlaczego? Jak to poprawić?




        © Rule Financial 2011                                                     13
Wzorzec wywołania funkcji


 Czemu to może być problematyczne? Zobaczmy na przykładzie:
 var messanger = {
   message: 'hey',
   printMessage: function() {
      var that = this;
      var printer = function() {
         alert(that.message);
      }
      printer();
   }
 }
 messanger.printMessage(); //wyświetla „hey‟


 Wskazówka: Używaj that jako aliasu dla this




        © Rule Financial 2011                                  14
Wzorzec wywołania konstruktora


 Javascript nie posiada konstruktorów jako osobnych funkcji, jak Java
  Każda funkcja może być konstruktorem jeśli wywołamy ją ze słowem new, i odwrotnie. Jest
   to niebezpieczne, nie ma w języku żadnej kontroli tego.
  Dlatego istnieje konwencja: funkcje przeznaczone do wywołania jako konstruktor powinny
   mieć nazwy zaczynające się wielką literą – wówczas narzędzia są w stanie wykryć błędne
   użycie.


 Niepoprawne użycie może dać nieprzewidziane efekty; na przykład funkcja z poprzedniego
 przykładu użyta jako konstruktor:
 new messanger.printMessage();             //wyświetla „undefined‟!




         © Rule Financial 2011                                                               15
Wzorzec zastosowania funkcji


 Funkcja jest obiektem który może mieć atrybuty, a atrybut może być funkcją. Czyli funkcje
 mogą mogę funkcje (metody).
 Każda funkcja posiada metodę „apply‟ (oraz podobną metodę „call‟).
 Metoda „apply‟ pobiera dwa parametry, pierwszy oznacza jakie „this‟ ma być użyte, drugi
 (opcjonalny) to tablica argumentów. W ten sposób możemy „wypożyczać” funkcje:


 var otherObject = {
    message: 'another object!'‚
 }
 messanger.printMessage.apply(otherObject); //wyświetla „another object!”




         © Rule Financial 2011                                                                16
Dostęp do argumentów funkcji


 Każda funkcja podczas wywołania ma dostęp do specjalnej zmiennej arguments, która jest
 pseudo-tablicą zawierającą argumenty wywołania funkcji. To pozwala tworzyć funkcje
 pobierające zmienną liczbę parametrów, np.:

 var sum = function() {
   var i, sum = 0;
   for (i=0; i < arguments.length; i += 1) {
      sum += arguments[i];
   }
   return sum;
 };

 alert(sum(1,2,3,4)); //wyświetla 10




         © Rule Financial 2011                                                             17
Funkcje – dodatkowe uwagi


 Zasięg zmiennej – brak zasięgu blokowego! Każda zmienna ma zasięg obejmujący całą funkcję
 – bardzo niebezpieczne, bo nieintuicyjne!
 Brak napisywania metod (method overloading) w JS
 Zamiast funkcji z wieloma parametrami, preferuj pojedynczy parametr jako tak zwany object
 specifier:

 var panel = new Panel({
  width : 100,
  height: 200,
  title: ‘A title’,
  background: ‘blue’
 });




         © Rule Financial 2011                                                                18
Domknięcia (closures)


 Każda funkcja wewnętrzna ma dostęp do zmiennych zewnętrznych (oprócz „this‟ i „arguments‟).
 var counter = function() {
   var value = 0;
   return {
      increment: function(inc) {
         value += typeof inc === ‘number’ ? inc : 1;
      },
      getValue: function() {
          return value;
      }
   }
 }(); //uwaga na () !
 Domknięcia można wykorzystać do symulacji zmiennych prywatnych lub dziedziczenia




         © Rule Financial 2011                                                                  19
JavaScript - problemy


 Zmienna globalne – wystarczy zapomnieć słówka var
 Brak zasięgu blokowego
 Podchwytliwe reguły uzupełniania średnika
 Długa lista nieużywanych zastrzeżonych słów
 typeof
 Wiele wartości „pustych”: null, undefined, NaN, empty string, 0, false
 parseInt
 == vs === (!= vs !==)
 Standardowe (wbudowane) funkcje są ograniczone i chaotyczne




           © Rule Financial 2011                                           20

Professional Javascript for Developers

  • 1.
  • 2.
    JavaScript – podstawy Najlepsza wg mnie książka na temat JavaScriptu jako języka programowania: JavaScript: The Good Parts by Douglas Crockford (O‟Reilly)  Polskie wydanie: JavaScript - mocne strony (Helion)  JavaScript używa składni podobnej do Javy - ale to zmyłka, bo na tym podobieństwa się kończą; JavaScript jest kompletnie innym typem języka, bliżej mu do języków funkcjonalnych.  JavaScript jest używany zazwyczaj w środowisku DOM, a DOM jest niewygodny w użyciu  JavaScript ma wiele błędów i wad, ale ma też mocne strony © Rule Financial 2011 2
  • 3.
    JavaScript – podstawy Zmienne - var: var x = 5;  Zmienne mają zasięg funkcji: function test() { var x = 5; } alert(x) ; //x undefined  Jeśli zapomnimy słowa var, zmienna stanie się globalna! Również var poza jakąkolwiek funkcją da zmienną globalna: x = 5; // zmienna globalna! var y = 6; // zmienna globalna jeśli poza funkcją! © Rule Financial 2011 3
  • 4.
    Obiekty  Wszystko jestobiektem, lub typem prostym (primitive type) Typy proste (strings, numbers, booleans) są niezmienne  Obiekty są zmienne  Obiekty są po prostu mapami (kolekcje klucz-wartość)  Dostęp do atrybutów obiektu poprzez notację kropkową (dot notation) lub klamrową (bracket notation) © Rule Financial 2011 4
  • 5.
    Obiekty  Dot notationi bracket notation: var tree = {}; // pusty obiekt tree.type = 'oak'; tree.height = 10.34; //to samo co: tree[“height”] = 10.34 var weightPropertyName = 'weight'; tree[weightPropertyName] = 5; //to samo co tree.weight = 5 lub tree['weight'] = 5  Możemy też zdefiniować to wszystko jedną instrukcją za pomocą takiego literału obiektowego: var tree = { type : "oak", height : 10.34, weight : 5 };  Literał obiektowy a JSON © Rule Financial 2011 5
  • 6.
    Prototyp  Obiekt „dziedziczy”swój prototyp var x = {}; //dziedziczy z Object.prototype Object.prototype.msg = 'from prototype!'; alert("x: " + x.msg); //from prototype! var y = {}; //również dziedziczy z Object.prototype alert("y: " + y.msg); //from prototype! x.msg = 'overriden!'; alert("x: " + x.msg); //overriden! alert("y: " + y.msg); //from prototype! delete(x.msg); alert("x: " + x.msg); //from prototype! © Rule Financial 2011 6
  • 7.
    Tablice  Tablica jestspecjalnym typem obiektu (czyli mapy), gdzie kluczami są liczby całkowite  W JavaScripcie nie ma tablic takich jak w Javie, opartych o blok pamięci  Tablice mają swój własny literał []: var books = []; // pusta tablica books = ['JavaScript in practice', 'UML for the beginners', {name: 'Java tutorial', format: 'ebook'}]; var size = books.lenth; // 3 books[1000] = 'Learn programming in one day'; size = books.length; // 1001 © Rule Financial 2011 7
  • 8.
    Funkcje  Funkcje sąspecjalnymi typami obiektów  są więc mapami  mogą więc zawierać właściwości jak każdy inny obiekt, a właściwość może być funkcją!  Funkcje mogą być wywoływane. W związku z tym mają one dwie specyficzne właściwości:  Kod funkcji  Kontekst funkcji (w momencie jej wywołania) określający na co wskazują specjalne zmienne „this‟ i „arguments‟, oraz jakie inne zmienne są dostępne © Rule Financial 2011 8
  • 9.
    Funkcje  Funkcje mająswój literał: var myFunction = function() { alert('function has been called!'); }  Funkcje są mapami, więc mogą mieć atrybuty jak każdy obiekt: myFunction.isCodeComplete = false;  Opcjonalnie mogą mieć nazwę (która prawie do niczego nie służy): var myFunction = function myFunction() { … }  Zapis instrukcji funkcji: function myFunction() { … }  Niemal równoważny zapis z funkcją anonimową (preferowany): var myFunction = function() { … } © Rule Financial 2011 9
  • 10.
    Referencja do funkcjia wywołanie funkcji  Funkcja jest dostępna jako zmienna – ta zmienna jest referencją do funkcji var myFunction = function() { return 'result'; }  myFunction powyżej jest zmienną będącą referencją do funkcji  Można tę referencję przekazać: var myFunctionAlias = myFunction; //myFunctionAlias jest funkcją  lub wywołać funkcję i przekazać jej wynik: var myFunctionResult = myFunction(); //myFunctionResult jest łańcuchem „result” © Rule Financial 2011 10
  • 11.
    Wzorzec wywołania metody Funkcja zadeklarowana jaka właściwość obiektu jest nazywana metodą (tego obiektu) var myObject = { name : 'An object', action : function(count) { alert(this.name ? this.name + count : 'no name!'); } } //obiekt myObject ma metodę “action”  wzorzec wywołania metody: myObject.action(5); //wyświetla “An object5” więc „this‟ będzie wskazywać na myObject gdy wywołamy funkcję w ten sposób © Rule Financial 2011 11
  • 12.
    Wzorzec wywołania funkcji Weźmy ten sam obiekt: var myObject = { name : 'An object', action : function(count) { alert(this.name ? this.name + count : 'no name!'); } } I zamiast wywoływać funkcję jako metodę: myObject.action(5); zróbmy tak: action(5); // co wyświetli? var x = myObject.action; x(5); // co wyświetli? Jest to wzorzec wywołania funkcji; this wskazuje na obiekt globalny (window) © Rule Financial 2011 12
  • 13.
    Wzorzec wywołania funkcji Czemu to może być problematyczne? Zobaczmy na przykładzie: var messanger = { message: 'hey', printMessage: function() { … var printer = function() { alert(this.message); } printer(); } } messanger.printMessage(); //wyświetla „undefined‟ - dlaczego? Jak to poprawić? © Rule Financial 2011 13
  • 14.
    Wzorzec wywołania funkcji Czemu to może być problematyczne? Zobaczmy na przykładzie: var messanger = { message: 'hey', printMessage: function() { var that = this; var printer = function() { alert(that.message); } printer(); } } messanger.printMessage(); //wyświetla „hey‟  Wskazówka: Używaj that jako aliasu dla this © Rule Financial 2011 14
  • 15.
    Wzorzec wywołania konstruktora Javascript nie posiada konstruktorów jako osobnych funkcji, jak Java  Każda funkcja może być konstruktorem jeśli wywołamy ją ze słowem new, i odwrotnie. Jest to niebezpieczne, nie ma w języku żadnej kontroli tego.  Dlatego istnieje konwencja: funkcje przeznaczone do wywołania jako konstruktor powinny mieć nazwy zaczynające się wielką literą – wówczas narzędzia są w stanie wykryć błędne użycie.  Niepoprawne użycie może dać nieprzewidziane efekty; na przykład funkcja z poprzedniego przykładu użyta jako konstruktor: new messanger.printMessage(); //wyświetla „undefined‟! © Rule Financial 2011 15
  • 16.
    Wzorzec zastosowania funkcji Funkcja jest obiektem który może mieć atrybuty, a atrybut może być funkcją. Czyli funkcje mogą mogę funkcje (metody).  Każda funkcja posiada metodę „apply‟ (oraz podobną metodę „call‟). Metoda „apply‟ pobiera dwa parametry, pierwszy oznacza jakie „this‟ ma być użyte, drugi (opcjonalny) to tablica argumentów. W ten sposób możemy „wypożyczać” funkcje: var otherObject = { message: 'another object!'‚ } messanger.printMessage.apply(otherObject); //wyświetla „another object!” © Rule Financial 2011 16
  • 17.
    Dostęp do argumentówfunkcji  Każda funkcja podczas wywołania ma dostęp do specjalnej zmiennej arguments, która jest pseudo-tablicą zawierającą argumenty wywołania funkcji. To pozwala tworzyć funkcje pobierające zmienną liczbę parametrów, np.: var sum = function() { var i, sum = 0; for (i=0; i < arguments.length; i += 1) { sum += arguments[i]; } return sum; }; alert(sum(1,2,3,4)); //wyświetla 10 © Rule Financial 2011 17
  • 18.
    Funkcje – dodatkoweuwagi  Zasięg zmiennej – brak zasięgu blokowego! Każda zmienna ma zasięg obejmujący całą funkcję – bardzo niebezpieczne, bo nieintuicyjne!  Brak napisywania metod (method overloading) w JS  Zamiast funkcji z wieloma parametrami, preferuj pojedynczy parametr jako tak zwany object specifier: var panel = new Panel({ width : 100, height: 200, title: ‘A title’, background: ‘blue’ }); © Rule Financial 2011 18
  • 19.
    Domknięcia (closures)  Każdafunkcja wewnętrzna ma dostęp do zmiennych zewnętrznych (oprócz „this‟ i „arguments‟). var counter = function() { var value = 0; return { increment: function(inc) { value += typeof inc === ‘number’ ? inc : 1; }, getValue: function() { return value; } } }(); //uwaga na () !  Domknięcia można wykorzystać do symulacji zmiennych prywatnych lub dziedziczenia © Rule Financial 2011 19
  • 20.
    JavaScript - problemy Zmienna globalne – wystarczy zapomnieć słówka var  Brak zasięgu blokowego  Podchwytliwe reguły uzupełniania średnika  Długa lista nieużywanych zastrzeżonych słów  typeof  Wiele wartości „pustych”: null, undefined, NaN, empty string, 0, false  parseInt  == vs === (!= vs !==)  Standardowe (wbudowane) funkcje są ograniczone i chaotyczne © Rule Financial 2011 20