Rozdział 2. Podstawy języka JavaScript

> Dodaj do ulubionych

Wprowadzenie

Podstaw─Ö biblioteki jQuery stanowi JavaScript, kt├│ry sam w sobie jest niezwykle bogatym i ekspresyjnym j─Özykiem. W poni┼╝szej sekcji poznamy podstawowe poj─Öcia j─Özyka JavaScript, a tak┼╝e przyjrzymy si─Ö czekaj─ůcym na nowicjuszy pu┼éapkom. Om├│wione zagadnienia skierowane s─ů przede wszystkim do pocz─ůtkuj─ůcych, jednak zapoznanie si─Ö z charakterystycznymi cechami JavaScriptu mo┼╝e przynie┼Ť─ç korzy┼Ťci r├│wnie┼╝ programistom maj─ůcym do┼Ťwiadczenie w innych j─Özykach programowania.

Je┼Ťli chcesz dowiedzie─ç si─Ö wi─Öcej na temat j─Özyka JavaScript, gor─ůco polecam ksi─ů┼╝k─Ö Douglasa Crockforda JavaScript: The Good Parts oraz nasz kurs programowania w j─Özyku JavaScript autorstwa Marijna Haverbeke

Podstawy składni JavaScriptu

Omówienie instrukcji, nazewnictwa zmiennych, białych znaków oraz innych podstawowych elementów składni języka JavaScript.

Przykład 2.1. Prosta deklaracja zmiennej

var foo = 'witaj, ┼Ťwiecie';

Przyk┼éad 2.2. Poza cudzys┼éowem bia┼ée znaki nie pe┼éni─ů ┼╝adnej funkcji

var foo = 'witaj, ┼Ťwiecie';

Przyk┼éad 2.3. Nawiasy oznaczaj─ů pierwsze┼ästwo wykonywania dzia┼éania

2 * 3 + 5;    // zwraca 11; pierwsze wykonywane jest mno┼╝enie
2 * (3 + 5);  // zwraca 16; pierwsze wykonywane jest dodawanie

Przyk┼éad 2.4. Tabulatory zwi─Ökszaj─ů czytelno┼Ť─ç kodu, lecz nie maj─ů ┼╝adnego specjalnego znaczenia

var foo = function() {
    console.log('witaj');
};

Operatory JavaScript

Podstawowe operatory

U┼╝ywaj─ůc podstawowych operator├│w mo┼╝emy manipulowa─ç warto┼Ťciami.

Przyk┼éad 2.5. ┼ü─ůczenie (konkatenacja)

var foo = 'witaj,';
var bar = '┼Ťwiecie';

console.log(foo + ' ' + bar); // witaj, ┼Ťwiecie

Przykład 2.6. Mnożenie i dzielenie

2 * 3;
2 / 3;

Przykład 2.7. Inkrementacja i dekrementacja

var i = 1;

var j = ++i;  // preinkrementacja:  j r├│wna si─Ö 2; i r├│wna si─Ö 2
var k = i++;  // postinkrementacja: k r├│wna si─Ö 2; i r├│wna si─Ö 3

Operacje na liczbach i ci─ůgach znak├│w

Czasem liczby i ci─ůgi w j─Özyku JavaScript mog─ů zachowywa─ç si─Ö nie do ko┼äca zgodnie z naszymi przewidywaniami.

Przyk┼éad 2.8. Dodawanie vs. ┼é─ůczenie

var foo = 1;
var bar = '2';
console.log(foo + bar);  // 12, ups

Przyk┼éad 2.9. Jak sprawi─ç, by ci─ůg sta┼é si─Ö liczb─ů

var foo = 1;
var bar = '2';
 // wymuszamy, aby ci─ůg sta┼é si─Ö liczb─ů
console.log(foo + Number(bar));

Wywo┼éanie konstruktora Number jako funkcji (tak jak w przyk┼éadzie powy┼╝ej) sprawi, ┼╝e jego argument b─Ödzie traktowany jako liczba. Ten sam rezultat osi─ůgniemy u┼╝ywaj─ůc jednoargumentowego operatora plus:

Przyk┼éad 2.10. Jak sprawi─ç, by ci─ůg sta┼é si─Ö liczb─ů (przy u┼╝yciu jednoargumentowego operatora plus)

console.log(foo + +bar);

Operatory logiczne

Operatory logiczne umo┼╝liwiaj─ů oszacowanie argument├│w poprzez operacje I oraz LUB.

Przykład 2.11. Operatory logiczne I oraz LUB

var foo = 1;
var bar = 0;
var baz = 2;

foo || bar;   // zwraca 1, czyli prawd─Ö
bar || foo;   // zwraca 1, czyli prawd─Ö

foo && bar;   // zwraca 0, czyli fałsz
foo && baz;   // zwraca 2, czyli prawd─Ö
baz && foo;   // zwraca 1, czyli prawd─Ö

By─ç mo┼╝e przyk┼éad nie ilustruje dzia┼éania operator├│w zbyt jasno, zatem kr├│tkie wyja┼Ťnienie: operator || zwraca warto┼Ť─ç pierwszego argumentu, kt├│ry jest prawdziwy, za┼Ť w przypadku, gdy obydwa argumenty s─ů fa┼észywe, zwracany jest ostatni argument. Operator && zwraca warto┼Ť─ç pierwszego fa┼észywego argumentu, lub warto┼Ť─ç ostatniego, je┼Ťli obydwa argumenty s─ů prawdziwe.

Nie zapomnij zajrze─ç do sekcji „Rzeczy prawdziwe, rzeczy fa┼észywe”, aby dowiedzie─ç si─Ö wi─Öcej na temat tego, kt├│re warto┼Ťci s─ů prawdziwe (true), a kt├│re fa┼észywe (false).

Operatory por├│wnywania

Dzi─Öki operatorom por├│wnywania mo┼╝emy sprawdzi─ç, czy dane warto┼Ťci s─ů sobie r├│wne b─ůd┼║ ze sob─ů identyczne.

Przykład 2.12. Operatory porównywania

var foo = 1;
var bar = 0;
var baz = '1';
var bim = 2;

foo == bar;   // zwraca fałsz
foo != bar;   // zwraca prawd─Ö
foo == baz;   // zwraca prawd─Ö; uwaga!

foo === baz;             // zwraca fałsz
foo !== baz;             // zwraca prawd─Ö
foo === parseInt(baz);   // zwraca prawd─Ö

foo > bim;    // zwraca fałsz
bim > baz;    // zwraca prawd─Ö
foo <= baz;   // zwraca prawd─Ö

Kod warunkowy

Czasami chcemy, aby blok kodu zosta┼é wykonany tylko w okre┼Ťlonej sytuacji. Umo┼╝liwia nam to kontrola przep┼éywu sterowania za pomoc─ů instrukcji if-else.

Przykład 2.13. Sterowanie wykonaniem programu

var foo = true;
var bar = false;

if (bar) {
    // ten kod nigdy nie zostanie wykonany
    console.log('witaj!');
}

if (bar) {
    // kod nie zostanie wykonany
} else {
    if (foo) {
        // kod zostanie wykonany
    } else {
        // kod zostanie wykonany je┼Ťli zar├│wno foo i bar b─Öd─ů fa┼észywe
    }
}

Rzeczy prawdziwe, rzeczy fałszywe

Aby umiej─Ötnie sterowa─ç dzia┼éaniem programu, nale┼╝y wiedzie─ç, kt├│re warto┼Ťci s─ů prawdziwe, a kt├│re fa┼észywe. Zdarza si─Ö, ┼╝e warto┼Ťci, kt├│re pozornie wydaj─ů si─Ö fa┼észywe b─ůd┼║ prawdziwe zwracaj─ů przeciwn─ů warto┼Ť─ç.

Przyk┼éad 2.14. Warto┼Ťci, kt├│re zwracaj─ů prawd─Ö

'0';
'dowolny ci─ůg';
[];  // pusta tablica
{};  // pusty obiekt
1;   // dowolna liczba r├│┼╝na od zera

Przyk┼éad 2.15. Warto┼Ťci, kt├│re zwracaj─ů fa┼ész

0;
'';  // pusty ci─ůg
NaN; // zmienna, kt├│ra nie jest typu liczbowego
null;
undefined;  // uwaga ÔÇô undefined mo┼╝e mie─ç zmienion─ů definicj─Ö!

Przypisanie warunkowe zmiennych za pomoc─ů operatora tr├│jargumentowego

Czasami chcemy przypisa─ç zmiennej dan─ů warto┼Ť─ç w zale┼╝no┼Ťci od tego, czy zosta┼é spe┼éniony okre┼Ťlony warunek. Mo┼╝emy w├│wczas u┼╝y─ç instrukcji warunkowej if-else, lecz w wielu przypadkach znacznie wygodniejszym rozwi─ůzaniem jest operator tr├│jargumentowy. [Definicja: operator tr├│jargumentowy sprawdza, czy zosta┼é spe┼éniony okre┼Ťlony warunek; je┼Ťli tak, zwracana jest odpowiednia warto┼Ť─ç, je┼Ťli nie — inna.]

Przykład 2.16. Operator trójargumentowy

// je┼Ťli bar jest prawdziwe, niech foo r├│wna si─Ö 1
// w przeciwnym wypadku niech foo b─Ödzie r├│wne 0
var foo = bar ? 1 : 0;

Operatora tr├│jargumentowego mo┼╝na u┼╝ywa─ç bez przypisania zmiennej warto┼Ť─ç zwrotnej, jednak lepiej tego nie robi─ç.

Instrukcja switch

Czasami zamiast kilku blok├│w if/else-if/else wygodniej jest u┼╝y─ç instrukcji switch. [Definicja: instrukcja switch sprawdza warto┼Ť─ç danego wyra┼╝enia b─ůd┼║ zmiennej i wykonuje poszczeg├│lne bloki kodu zale┼╝nie od tej warto┼Ťci.]

Przykład 2.17. Instrukcja switch

switch (foo) {

    case 'bar':
        alert('warto┼Ť─ç bar ÔÇô ojej!');
    break;

    case 'baz':
        alert('buu baz :(');
    break;

    default:
        alert('wszystko pozostałe może być');
    break;
}

Instrukcja switch nie jest ju┼╝ zbyt ch─Ötnie wykorzystywana przez programist├│w JavaScript, poniewa┼╝ cz─Östo do osi─ůgni─Öcia tych samych rezultat├│w mo┼╝na wykorzysta─ç obiekty. S─ů one wygodniejsze do ponownego u┼╝ycia czy test├│w. Na przyk┼éad:

var coMamZrobic = {
    'bar' : function() {
        alert('warto┼Ť─ç bar ÔÇô ojej!');
    },

    'baz' : function() {
        alert('buu baz :(');
    },

    'default' : function() {
        alert('wszystko pozostałe może być');
    }
};

if (coMamZrobic[foo]) {
    coMamZrobic[foo]();
} else {
    coMamZrobic['default']();
}

Obiektom przyjrzymy si─Ö bli┼╝ej w dalszej cz─Ö┼Ťci rozdzia┼éu.

P─Ötle j─Özyka JavaScript

Dzi─Öki p─Ötlom mo┼╝emy wykona─ç blok kodu okre┼Ťlon─ů liczb─Ö razy.

Przykład 2.18. Pętle

// rejestruje 'pr├│ba 0', 'pr├│ba 1', ..., 'pr├│ba 4'
for (var i=0; i<5; i++) {
    console.log('pr├│ba ' + i);
}
Zwr├│─ç uwag─Ö, ┼╝e cho─ç w p─Ötlach u┼╝ywamy s┼éowa kluczowego var przed nazw─ů zmiennej i, to jednak „zakres” zmiennej nie ogranicza si─Ö tylko do bloku p─Ötli. Poj─Öcie zakresu zmiennych zostanie dok┼éadniej om├│wione w dalszej cz─Ö┼Ťci rozdzia┼éu.

P─Ötla for

P─Ötla for sk┼éada si─Ö z czterech instrukcji. Jej struktura wygl─ůda nast─Öpuj─ůco:

for ([inicjacja]; [warunek]; [iteracja])
 [trescPetli]

Instrukcja inicjuj─ůca wykonywana jest tylko raz, przed rozpocz─Öciem p─Ötli. W├│wczas mo┼╝emy przygotowa─ç lub zadeklarowa─ç jakie┼Ť zmienne.

Instrukcja warunkowa wykonywana jest przed ka┼╝d─ů iteracj─ů, a od jej warto┼Ťci zwrotnej zale┼╝y dalsze wykonywanie p─Ötli. W przypadku warto┼Ťci fa┼észywej p─Ötla si─Ö zatrzymuje.

Instrukcja iteracja wykonywana jest na ko┼äcu ka┼╝dej iteracji — wtedy te┼╝ mo┼╝na zmieni─ç stan istotnych zmiennych. Zazwyczaj zwi─Öksza b─ůd┼║ zmniejsza si─Ö w├│wczas licznik, co przybli┼╝a p─Ötl─Ö do ko┼äca.

TrescFunkcji wykonywana jest w czasie ka┼╝dej iteracji i mo┼╝e zawiera─ç dowolny kod. Zazwyczaj tre┼Ť─ç funkcji sk┼éada si─Ö z wielu instrukcji, kt├│re musz─ů zosta─ç wykonane i s─ů otoczone klamrami ({...}).

Oto typowa p─Ötla for:

Przykład 2.19. Typowa pętla for

for (var i = 0, limit = 100; i < limit; i++) {
    // Ten blok kodu zostanie wykonany 100 razy
    console.log(Iteracja nr ' + i);
    // Uwaga: jako ostatni wy┼Ťwietli si─Ö komunikat "Iteracja nr 99"
}

P─Ötla while

P─Ötla while swoj─ů budow─ů przypomina instrukcj─Ö warunkow─ů if, przy czym tre┼Ť─ç tej p─Ötli jest wykonywana a┼╝ do momentu, w kt├│rym dany warunek nie jest ju┼╝ d┼éu┼╝ej spe┼éniany.

while ([warunek]) [trescPetli]

Oto typowa p─Ötla while:

Przykład 2.20. Typowa pętla while

var i = 0;
while (i < 100) {

    // Ten blok kodu zostanie wykonany 100 razy
    console.log('Iteracja nr ' + i);

    i++; // inkrementacja i

}

Z pewno┼Ťci─ů zauwa┼╝ysz, ┼╝e w tre┼Ťci p─Ötli musimy dokona─ç inkrementacji licznika. Licznik mo┼╝na po┼é─ůczy─ç z warunkiem, tak jak zaprezentowano poni┼╝ej:

Przykład 2.21. Pętla while, w której licznik jest inkrementowany po sprawdzeniu na nim warunku

var i = -1;
while (++i < 100) {
    // Ten blok kodu zostanie wykonany 100 razy
    console.log('Iteracja nr ' + i);
}

Zwr├│─ç uwag─Ö, ┼╝e zaczynamy z poziomu -1 i korzystamy z przedrostkowego operatora inkrementacji (++i), czyli preinkrementacji.

P─Ötla do-while

Jest to praktycznie taka sama p─Ötla co while — r├│┼╝nica polega na tym, ┼╝e tre┼Ť─ç p─Ötli do-while jest wykonywana co najmniej jeden raz, przed sprawdzeniem warunku.

do [trescPetli] while ([warunek])

Oto p─Ötla do-while:

Przykład 2.22. Pętla do-while

do {

    // Nawet w przypadku niespełnienia warunku
    // tre┼Ť─ç p─Ötli zostanie wykonana raz.

    alert('Hej!');

} while (false);

P─Ötle tego typu wykorzystywane s─ů do┼Ť─ç rzadko, poniewa┼╝ tylko w nielicznych wypadkach chcemy, aby p─Ötla zosta┼éa wykonana bez sprawdzenia jakiegokolwiek warunku. Mimo wszystko o istnieniu p─Ötli do-while warto wiedzie─ç.

Instrukcje break i continue

Zazwyczaj zatrzymanie p─Ötli nast─Öpuje po niespe┼énieniu okre┼Ťlonego warunku, lecz mo┼╝na do tego r├│wnie┼╝ doprowadzi─ç umieszczaj─ůc w tre┼Ťci funkcji instrukcj─Ö break.

Przykład 2.23. Zatrzymywanie pętli

for (var i = 0; i < 10; i++) {
    if (co┼Ť) {
        break;
    }
}

Mo┼╝emy r├│wnie┼╝ chcie─ç kontynuowa─ç p─Ötl─Ö bez wykonywania jej dalszej tre┼Ťci — s┼éu┼╝y do tego instrukcja continue.

Przykład 2.24. Przeskakujemy do następnej iteracji pętli

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

    if (co┼Ť) {
        continue;
    }

    // Poni┼╝sza instrukcja zostanie wykonana tylko w├│wczas,
    // je┼Ťli warunek co┼Ť nie zostanie spe┼éniony
    console.log('Koniec');

}

Słowa zarezerwowane

W j─Özyku JavaScript istnieje pewna liczba „s┼é├│w zarezerwowanych” — s─ů to s┼éowa o specjalnym znaczeniu. S┼é├│w tych nale┼╝y u┼╝ywa─ç w kodzie tylko zgodnie z ich okre┼Ťlonym znaczeniem.

  • abstract
  • boolean
  • break
  • byte
  • case
  • catch
  • char
  • class
  • const
  • continue
  • debugger
  • default
  • delete
  • do
  • double
  • else
  • enum
  • export
  • extends
  • final
  • finally
  • float
  • for
  • function
  • goto
  • if
  • implements
  • import
  • in
  • instanceof
  • int
  • interface
  • long
  • native
  • new
  • package
  • private
  • protected
  • public
  • return
  • short
  • static
  • super
  • switch
  • synchronized
  • this
  • throw
  • throws
  • transient
  • try
  • typeof
  • var
  • void
  • volatile
  • while
  • with

Tablice JavaScript

Tablice to indeksowane od zera listy warto┼Ťci. Dzi─Öki tablicom mo┼╝na w wygodny spos├│b przechowywa─ç zbi├│r zwi─ůzanych ze sob─ů element├│w tego samego typu (na przyk┼éad ci─ůg├│w), cho─ç w rzeczywisto┼Ťci w tablicy mog─ů znajdowa─ç si─Ö r├│┼╝ne typy element├│w, w tym inne tablice.

Przykład 2.25. Prosta tablica

var mojaTablica = [ 'witaj', '┼Ťwiecie' ];

Przykład 2.26. Dostęp do tablicy poprzez indeks

var mojaTablica = [ 'witaj', '┼Ťwiecie', 'foo', 'bar' ];
console.log(mojaTablica[3]);   // rejestruje 'bar'

Przykład 2.27. Sprawdzamy rozmiar tablicy

var mojaTablica = [ 'witaj', '┼Ťwiecie' ];
console.log(mojaTablica.length);   // rejestruje 2

Przyk┼éad 2.28. Zmiana warto┼Ťci elementu

var mojaTablica = [ 'witaj', '┼Ťwiecie' ];
mojaTablica[1] = 'zmieniony';
Cho─ç istnieje mo┼╝liwo┼Ť─ç zmiany warto┼Ťci tablicy tak jak zaprezentowano to w przyk┼éadzie 2.28, lepiej tego unika─ç.

Przykład 2.29. Dodawanie elementów do tablicy

var mojaTablica = [ 'witaj', '┼Ťwiecie' ];
mojaTablica.push('nowy element');
Przykład 2.30: Korzystanie z tablic
var mojaTablica = [ 'w', 'i', 't', 'a', 'j' ];
var mojCiag = mojaTablica.join('');   // 'witaj'
var mojPodzial = mojCiag.split('');  // [ 'w', 'i', 't', 'a', 'j' ]

Obiekty JavaScript

Obiekty zawieraj─ů jedn─ů lub wi─Öcej par klucz-warto┼Ť─ç. Kluczem mo┼╝e by─ç dowolny ci─ůg, za┼Ť warto┼Ť─ç mo┼╝e stanowi─ç dowolny typ warto┼Ťci: liczba, ci─ůg, tablica, funkcja, a nawet inny obiekt.

Definicja: Kiedy jedna z warto┼Ťci jest funkcj─ů, nazywa si─Ö j─ů metod─ů danego obiektu. W pozosta┼éych przypadkach warto┼Ťci nazywane s─ů w┼éasno┼Ťciami lub atrybutami.

Jak si─Ö okazuje, praktycznie wszystko w j─Özyku JavaScript jest obiektem — tablice, liczby, funkcje, a nawet ci─ůgi. Ka┼╝de z nich ma swoje w┼éasno┼Ťci i metody.

Przyk┼éad 2.31. Tworzymy „litera┼é obiektowy”

var mojObiekt = {
    przywitajSie : function() {
        console.log('witaj');
    },

    mojeImie : 'Joanna'
};

mojObiekt.przywitajSie();            // rejestruje 'witaj'
console.log(mojObiekt.mojeImie);   // rejestruje 'Joanna'

Funkcje JavaScript

Funkcje s┼éu┼╝─ů do przechowywania blok├│w kodu, kt├│ry ma by─ç wykorzystany wielokrotnie. Mog─ů one przyjmowa─ç od zera do kilku argument├│w, a tak┼╝e zwraca─ç warto┼Ť─ç.

Funkcje mo┼╝na tworzy─ç na r├│┼╝ne sposoby:

Przykład 2.32. Definicja funkcji

function foo() { /* zr├│b co┼Ť */ }

Przykład 2.33. Nazwane wyrażenie funkcyjne

var foo = function() { /* zr├│b co┼Ť */ }
Osobi┼Ťcie wol─Ö, z pewnych przyczyn technicznych, tworzy─ç funkcje poprzez wyra┼╝enia funkcyjne. Generalnie mo┼╝na si─Ö jednak spotka─ç z obiema metodami.

Korzystanie z funkcji

Przykład 2.34. Prosta funkcja

var przywitaj = function(osoba, powitanie) {
    var tekst = powitanie + ', ' + osoba;
    console.log(tekst);
};
przywitaj('Rebecca', 'Witaj');
Przyk┼éad 2.35: Funkcja zwracaj─ůca warto┼Ť─ç
var przywitaj = function(osoba, powitanie) {
    var tekst = powitanie + ', ' + osoba;
    return tekst;
};

console.log(przywitaj('Rebecca','witaj'));

Przyk┼éad 2.36. Funkcja zwracaj─ůca inn─ů funkcj─Ö

var przywitaj = function(osoba, powitanie) {
    var tekst = powitanie + ', ' + osoba;
    return function() { console.log(tekst); };
};


var pozdrowienie = przywitaj('Rebecca', 'Witaj');
pozdrowienie();

Samowykonuj─ůce si─Ö funkcje anonimowe

W j─Özyku JavaScript bardzo cz─Östo wykorzystuj─Ö si─Ö samowykonuj─ůce si─Ö funkcje anonimowe. Funkcja tworzona jest w├│wczas poprzez wyra┼╝enie funkcyjne, a nast─Öpnie zostaje natychmiastowo wykonana. Rozwi─ůzanie to jest niezwykle przydatne je┼Ťli nie chcesz za┼Ťmieca─ç globalnej przestrzeni nazw swoim kodem — zmienne zadeklarowane wewn─ůtrz funkcji nie s─ů widoczne poza ni─ů.

Przyk┼éad 2.37. Samowykonuj─ůca si─Ö funkcja anonimowa

(function(){
    var foo = 'Witaj, ┼Ťwiecie';
})();


console.log(foo);   // niezdefiniowane!

Funkcja jako argument

W j─Özyku JavaScript, funkcje mo┼╝na okre┼Ťli─ç mianem „obywateli pierwszej kategorii” — mog─ů by─ç one przypisywane do zmiennych lub przekazywane jako argumenty innych funkcji. Przekazywanie funkcji jako argumentu to bardzo cz─Östa praktyka w jQuery.

Przykład 2.38. Przekazywanie funkcji anonimowej jako argumentu

var mojaFn = function(fn) {
    var rezultat = fn();
    console.log(rezultat);
};

mojaFn(function() { return 'witaj, ┼Ťwiecie'; });   // rejestruje witaj, ┼Ťwiecie

Przykład 2.39. Przekazywanie nazwanej funkcji jako argumentu

var mojaFn = function(fn) {
    var rezultat = fn();
    console.log(rezultat);
};

var mojaDrugaFn = function() {
    return 'witaj, ┼Ťwiecie';
};

mojaFn(mojaDrugaFn);   // rejestruje witaj, ┼Ťwiecie

Sprawdzanie typu zmiennej

J─Özyk JavaScript pozwala na sprawdzenie „typu” danej zmiennej. Rezultaty mog─ů by─ç jednak dezorientuj─ůce — przyk┼éadowo typ tablicy to obiekt (object).

Do sprawdzania typu warto┼Ťci cz─Östo u┼╝ywany jest operator typeof.

Przykład 2.40. Sprawdzanie typów różnych zmiennych

var mojaFunkcja = function() {
    console.log('witaj');
};

var mojObiekt = {
    foo : 'bar'
};

var mojaTablica = [ 'a', 'b', 'c' ];

var mojCiag = 'witaj';

var mojaLiczba = 3;

typeof mojaFunkcja;   // zwraca function
typeof m├│jObiekt;     // zwraca object
typeof mojaTablica;      // zwraca object ÔÇô uwaga!
typeof m├│jCi─ůg;     // zwraca string
typeof mojaLiczba;     // zwraca number

typeof null;         // zwraca object ÔÇô uwaga!

if (mojaTablica.push && mojaTablica.slice && mojaTablica.join) {
    // prawdopodobnie jaka┼Ť tablica
    // (jest to tak zwane ÔÇ×kacze typowanieÔÇŁ)
}

if (Object.prototype.toString.call(mojaTablica) === '[object Array]') {
    // To na pewno tablica!
    // Powszechnie uwa┼╝a si─Ö to za najlepszy spos├│b
    // do okre┼Ťlenia, czy dana warto┼Ť─ç jest tablic─ů
}

Biblioteka jQuery zawiera metody pomocnicze, kt├│re pozwalaj─ů ustali─ç typ dowolnej warto┼Ťci. Metody te zostan─ů om├│wione w dalszej cz─Ö┼Ťci kursu.

Słowo kluczowe this

W JavaScripcie, podobnie jak w wi─Ökszo┼Ťci j─Özyk├│w programowania obiektowego, this jest specjalnym s┼éowem kluczowym wykorzystywanym w metodach w celu odwo┼éania si─Ö do obiektu, na kt├│rym dana metoda jest wywo┼éywana. Warto┼Ť─ç this okre┼Ťlana jest w kilku prostych krokach:

  1. Je┼Ťli funkcja zostaje wywo┼éana metod─ů Funkcja.call lub Funkcja.apply, this przyjmie warto┼Ť─ç pierwszego argumentu przekazanego do metody call/apply. Je┼Ťli pierwszy argument przekazany do metody call/apply ma warto┼Ť─ç null lub undefined, this b─Ödzie odnosi─ç si─Ö do obiektu globalnego (w przegl─ůdarkach internetowych jest to obiekt window).
  2. Je┼Ťli wywo┼éywana funkcja zosta┼éa utworzona przy pomocy metody Funkcja.bind, this przyjmie warto┼Ť─ç pierwszego argumentu, kt├│ry zosta┼é przekazany do metody bind w czasie tworzenia funkcji.
  3. Je┼Ťli funkcja jest wywo┼éywana jako metoda obiektu, this odwo┼éuje si─Ö do tego obiektu.
  4. W pozosta┼éych przypadkach wywo┼éywana jest samodzielna funkcja, niepowi─ůzana z ┼╝adnym obiektem — w├│wczas this odwo┼éuje si─Ö do obiektu globalnego.

Przykład 2.41. Funkcja wywołana przy użyciu metody Funkcja.call

var mojObiekt = {
    przywitajSie : function() {
        console.log('Cze┼Ť─ç! Mam na imi─Ö ' + this.mojeImie);
    },

    mojeImie : 'Rebecca'
};

var drugiObiekt = {
    mojeImie : 'Colin'
};

mojObiekt.przywitajSie();                  // rejestruje Cze┼Ť─ç! Mam na imi─Ö Rebecca
mojObiekt.przywitajSie.call(drugiObiekt); // rejestruje Cze┼Ť─ç! Mam na imi─Ö Colin
Przykład 2.42: Funkcja utworzona przy pomocy metody Function.bind
var mojeImie = 'obiekt globalny',

    przywitajSie = function () {
        console.log('Cze┼Ť─ç! Mam na imi─Ö ' + this.mojeImie);
    },

    mojObiekt = {
        mojeImie : 'Rebecca'
    };

var mojObiektCzesc = przywitajSie.bind(mojObiekt);

przywitajSie();       // rejestruje Cze┼Ť─ç! Mam na imi─Ö obiekt globalny
m├│jObiektCze┼Ť─ç();  // rejestruje Cze┼Ť─ç! Mam na imi─Ö Rebecca
Przyk┼éad 2.43: Funkcja wi─ůzana z obiektem w czasie dzia┼éania programu
var mojeImie = 'obiekt globalny',

    przywitajSie = function () {
        console.log('Czesc! Mam na imie ' + this.mojeImie);
    },

    mojObiekt = {
        mojeImie : 'Rebecca'
    },

    drugiObiekt = {
        mojeImie : 'Colin'
    };

mojObiekt.przywitajSie = przywitajSie;
drugiObiekt.przywitajSie = przywitajSie;

przywitajSie();               // rejestruje Cze┼Ť─ç! Mam na imi─Ö obiekt globalny
m├│jObiekt.przywitajSie();      // rejestruje Cze┼Ť─ç! Mam na imi─Ö Rebecca
drugiObiekt.przywitajSie();  // rejestruje Cze┼Ť─ç! Mam na imi─Ö Colin

Zakres dost─Öpno┼Ťci zmiennych JavaScript

„Zakres” odnosi si─Ö do zmiennych dost─Öpnych w danym bloku kodu, w okre┼Ťlonym czasie. Niezrozumienie poj─Öcia zakresu cz─Östo sprawia, ┼╝e m─Öczymy si─Ö z uci─ů┼╝liwymi usterkami.

Zmienna zadeklarowana wewn─ůtrz funkcji poprzez s┼éowo kluczowe var dost─Öpna jest tylko w obr─Öbie tej funkcji — nie mo┼╝na wi─Öc skorzysta─ç z takiej zmiennej poza t─ů funkcj─ů. Dost─Öp do tej zmiennej b─Öd─ů mie─ç natomiast funkcje zdefiniowane wewn─ůtrz tej funkcji.

Ponadto zmienne zadeklarowane wewn─ůtrz funkcji bez s┼éowa kluczowego var nie s─ů dla danej funkcji zmiennymi lokalnymi — JavaScript przegl─ůdnie ca┼éy ┼éa┼äcuch zakresu a┼╝ do zakresu okna by ustali─ç, gdzie zmienna ta zosta┼éa zdefiniowana. Je┼Ťli nie znajdzie tej definicji, zmienna ta zostanie potraktowana jako globalna, co mo┼╝e mie─ç zupe┼énie nieprzewidywalne konsekwencje.

Przyk┼éad 2.44. Funkcje maj─ů dost─Öp do zmiennych zdefiniowanych w obr─Öbie tego samego zakresu

var foo = 'witaj';

var przywitajSie = function() {
    console.log(foo);
};

przywitajSie();         // rejestruje witaj
console.log(foo);   // r├│wnie┼╝ rejestruje witaj

Przyk┼éad 2.45. Kod znajduj─ůcy si─Ö poza zakresem, w kt├│rym zosta┼éa zdefiniowana zmienna, nie ma dost─Öpu do tej zmiennej

var przywitajSie = function() {
    var foo = 'witaj';
    console.log(foo);
};

przywitajSie();         // rejestruje witaj
console.log(foo);   // nic nie rejestruje

Przyk┼éad 2.46. Zmienne o takiej samej nazwie mog─ů znajdowa─ç si─Ö w r├│┼╝nych zakresach i przybiera─ç r├│┼╝ne warto┼Ťci

var foo = '┼Ťwiecie';

var przywitajSie = function() {
    var foo = 'witaj';
    console.log(foo);
};

przywitajSie();         // rejestruje witaj
console.log(foo);   // rejestruje ┼Ťwiecie

Przyk┼éad 2.47. Po zdefiniowaniu funkcja mo┼╝e „zobaczy─ç” zmiany w warto┼Ťciach zmiennych

var mojaFunkcja = function() {
    var foo = 'witaj';

    var mojaFn = function() {
        console.log(foo);
    };

    foo = '┼Ťwiecie';

    return mojaFn;
};

var f = mojaFunkcja();
f();  // rejestruje '┼Ťwiecie' ÔÇô ups

Przyk┼éad 2.48. Zakresy mog─ů nas cz─Östo przyprawi─ç o b├│l g┼éowy

// samowykonuj─ůca si─Ö funkcja anonimowa
(function() {
    var baz = 1;
    var bim = function() { alert(baz); };
    bar = function() { alert(baz); };
})();

console.log(baz);  // baz nie jest zdefiniowany poza zakresem funkcji

bar();  // bar jest zdefiniowany poza zakresem funkcji anonimowej
        // ponieważ nie został zadeklarowany przy pomocy słowa kluczowego var; ponadto
        // ponieważ został zdefiniowany w tym samym zakresie co baz,
        // bar ma dost─Öp do baz ÔÇô za┼Ť inny kod
        // poza zakresem funkcji tego dost─Öpu nie ma

bim();  // bim nie jest zdefiniowany poza zakresem funkcji anonimowej,
        // w rezultacie wyst─ůpi b┼é─ůd

Zamkni─Öcia (closures)

Zamkni─Öcia stanowi─ů rozszerzenie poj─Öcia zakresu — funkcje maj─ů dost─Öp do zmiennych, kt├│re by┼éy dost─Öpne w zakresie, w kt├│rym utworzono te funkcje. Je┼Ťli definicja ta wydaje ci si─Ö niejasna, nie przejmuj si─Ö: zamkni─Öcia najlepiej zrozumie─ç na przyk┼éadach.

Przyk┼éad 2.47 demonstrowa┼é w jaki spos├│b funkcje maj─ů dost─Öp do zmienionych warto┼Ťci zmiennych. Podobnie rzecz ma si─Ö w przypadku funkcji zdefiniowanych wewn─ůtrz p─Ötli — po zdefiniowaniu funkcja „widzi” zmian─Ö warto┼Ťci zmiennej i w rezultacie wszystkie klikni─Öcia wywo┼éuj─ů okno alertu z komunikatem 5.

Przyk┼éad 2.49. Jak zamkn─ů─ç warto┼Ť─ç i

/* kod nie zachowa si─Ö tak, jakby┼Ťmy chcieli; */
/* każde kliknięcie wywoła okno alertu z komunikatem 5 */
for (var i=0; i<5; i++) {
    $('<p>kliknij mnie</p>').appendTo('body').click(function() {
        alert(i);
    });
}

Przyk┼éad 2.50. „Zamykamy” warto┼Ť─ç i poprzez zamkni─Öcie

/* rozwi─ůzanie: zamykamy warto┼Ť─ç i wewn─ůtrz funkcji utw├│rzFunkcje, aby warto┼Ť─ç tej zmiennej nie uleg┼éa zmianie */
var utworzFunkcje = function(i) {
    return function() { alert(i); };
};

for (var i=0; i<5; i++) {
    $('<p>kliknij mnie</p>').appendTo('body').click(utworzFunkcj─Ö(i));
}

Zamkni─Öcia mog─ů s┼éu┼╝y─ç r├│wnie┼╝ do rozwi─ůzywania problem├│w ze s┼éowem kluczowym this, kt├│re dla ka┼╝dego zakresu jest unikalne:

Przyk┼éad 2.51. Jak uzyska─ç jednoczesny dost─Öp do wewn─Ötrznego i zewn─Ötrznego obiektu u┼╝ywaj─ůc domkni─Öcia

var zewnetrznyObj = {
    mojaNazwa : 'zewn─Ötrzny',
    zewnetrznaFunkcja : function () {

        // odniesienie do obiektu zewnetrznyObj jest zamkni─Öte w funkcji wewnetrznaFunkcja
        var self = this;

        var wewnetrznyObj = {
            mojaNazwa : 'wewn─Ötrzny',
            wewnetrznaFunkcja : function () {
                console.log(self.mojaNazwa this.mojaNazwa); // rejestruje 'zewn─Ötrzny wewn─Ötrzny'
            }
        };

        wewnetrznyObj.wewnetrznaFunkcja();

        console.log(this.mojaNazwa); // rejestruje 'zewn─Ötrzny'
    }
};

zewn─ÖtrznyObj.zewnetrznaFunkcja();

Autor: Rebecca Murphey

Źródło: http://github.com/rmurphey/jqfundamentals

Tłumaczenie: Łukasz Piwko

Tre┼Ť─ç tej strony jest dost─Öpna na zasadach licencji CC BY-SA 3.0 US

1 komentarz do “Rozdzia┼é 2. Podstawy j─Özyka JavaScript”

  1. dzięki za artykuł, z tym ze przez błędy w prostych przykładach trochę to słabo wszystko wypada.
    Bo wydaje si─Ö ze rozumiem to co wyja┼Ťniasz a w przyk┼éadzie wygl─ůda to inaczej ni┼╝ powinno w stosunku do tego co sam t┼éumaczysz.

    Jako poczatkujacy javascriptowiec moge powiedziec ze w co 2 przykladzie sa bledy. Prosze popraw to. Bo wprowadzaja w blad osobe uczaca sie

Mo┼╝liwo┼Ť─ç komentowania zosta┼éa wy┼é─ůczona.