aboutsummaryrefslogtreecommitdiff
path: root/files/pl/web/javascript/guide/control_flow_and_error_handling/index.html
blob: f7121fa2a5d9bac4ab4a7e6d1e30027f6db868eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
---
title: Przepływ danych i obsługa błędów
slug: Web/JavaScript/Guide/Control_flow_and_error_handling
tags:
  - JavaScript
  - Początkujący
  - Przewodnik
translation_of: Web/JavaScript/Guide/Control_flow_and_error_handling
---
<div>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Grammar_and_types", "Web/JavaScript/Guide/Loops_and_iteration")}}</div>

<p class="summary">JavaScript jest językiem zawierającym w sobie szeroki wachlarz instrukcji. Część z nich odnosi się do sterowania przepływem programu <em>(</em><em>ang. control flow)</em> i może być pomyślnie użyta w celu nadania Twojej aplikacji kolejnych poziomów interaktywności. W rozdziale tym omówimy te instrukcje.</p>

<p><a href="/en-US/docs/Web/JavaScript/Reference/Statements">JavaScript reference</a> zawiera wyczerpujący opis instrukcji wymienionych w tym artykule. Średnik (;) jest używany do oddzielenia od siebie kolejnych poleceń w języku JavaScript. Chodź w większości przypadków brak średnika na końcu instrukcji nie powoduje błędu, by kod był jak najbardziej semantyczny, należy go tam umieszczać.</p>

<p>Każde wyrażenie w języku JavaScript jest również instrukcją. <a href="/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators">Expressions and operators</a> zawiera kompletny opis wyrażeń.</p>

<h2 id="Instrukcja_blokowa">Instrukcja blokowa</h2>

<p>Najprostszym rodzajem instrukcji jest instrukcja blokowa, która służy do grupowania wyrażeń. Blok jest ograniczony parą nawiasów klamrowych.</p>

<pre class="syntaxbox">{ wyrazenie_1; wyrazenie_2; . . . wyrazenie_n; }
</pre>

<h3 id="Przykład"><strong>Przykład</strong></h3>

<p>Instrukcje blokowe są bardzo często używane w połączeniu z instrukcjami sterującymi (np. <code>if</code>, <code>for</code>, <code>while</code>).</p>

<pre class="brush: js">while (x &lt; 10) {
  x++;
}
</pre>

<p>W tym przypadku, { x++; } jest instrukcją blokową.</p>

<p><strong>Ważne</strong>: Blok w JavaScript w wersji do ECMAScript6 nie posiada własnego scope (zasięgu zmiennych). Zmienne zadeklarowane wewnątrz takiego bloku bowiem mają scope (zasięg zmiennych) związany z funkcją lub skryptem, w którym blok się bezpośrednio znajduje. Efektem tego jest to, że każda zmienna zadeklarowana w bloku istnieje również i poza nim. W innych słowach - instrukcje blokowe nie definują nowego scope (zasięgu zmiennych). Samodzielne bloki w JavaScript mogą wyprodukować zupełnie inne wyniki od tych, których moglibyśmy się spodziewać w językach takich jak C czy Java. Przykład:</p>

<pre class="brush: js">var x = 1;
{
  var x = 2;
}
console.log(x); // wypisze 2
</pre>

<p>Wypisane zostanie 2 ponieważ wyrażenie var x wewnątrz bloku dzieli scope (zasięg zmiennych) z wyrażeniem var x na zewnątrz bloku. W C lub Javie, równoważny kod wypisałby 1.</p>

<p>Począwszy od specyfikacji ECMAScript 6, za pomocą słowa kluczowego <code>let</code> mamy mozliwość tworzenia zmiennych o zasięgu blokowym.  </p>

<h2 id="Instrukcje_warunkowe">Instrukcje warunkowe</h2>

<p>Instrukcje warunkowe są zbiorem instrukcji, które pozwalają na wykonywanie danej porcji kodu gdy warunki (parametry instrukcji) zwracają wartość true. JavaScript wspiera dwa rodzaje instrukcji warunkowych:<strong> </strong><code>if . . . else</code>  oraz <code>switch</code><strong>.</strong></p>

<h3 id="Instrukcje_if...else">Instrukcje <code>if...else</code></h3>

<p>Instrukcja <code>if</code><strong> </strong>wykonuje blok instrukcji jeżeli jej warunki zwrócą wartość <code>true</code>. Aby obsłużyć sytuacje gdy warunki nie zostały spełnione i zwracają <code>false</code>, można posłużyć się np. instrukcją <code>else</code><strong>:</strong></p>

<pre class="syntaxbox">if (warunki) {
  intrukcja_1;
}
else {
  instrukcja_2;
}</pre>

<p>Warunkami mogą być wszystkie twierdzania które można przekształcić do typu boolean (<code>true</code> lub <code>false</code>). W powyższym przykładzie <code>instrukcja_1</code> wykona się jeśli warunki zwrócą <code>true</code>, w przeciwnym wypadku wykonana zostanie <code>instrukcja_2</code>.<br>
 <br>
 Za pomocą <code>else if</code><strong> </strong>można tworzyć złożone sekwencyjnie testowe oparte na wielu instrukcjach warunkowych. Jeśli <code>warunek_1</code> nie zostanie spełniony, skrypt sprawdza kolejne warianty:</p>

<pre class="syntaxbox">if (warunek_1) { instrukcja_1; }
else if (warunek_2) { instrukcja_2; }
else if (warunek_n) { instrukcja_n; }
else { ostatnia_instrukcja; }
</pre>

<p>Aby wykonać wiele instrukcji można je zgrupować za pomocą deklaracji bloku (<code>{ ... }</code>). Mimo, że nie jest wymagane by pojedyncze instrukcje byly zawierane w bloku, warto stosować to rozwiązanie dla lepszej czytelności kodu:</p>

<pre class="syntaxbox">if (warunek_1) {
  instrukcja_1;
  instrukcja_2;
}
else if (warunek_2) {
  instrukcja_3;
}
else
   instrukcja_4;
   // Pojedyńcze instrukcje nie wymagają zawierania ich w nawiasy.

</pre>

<div>Wskazane jest, by nie używać przypisywania w wyrażeniu warunków:<br>
 </div>

<pre class="example-bad brush: js">if (x = y) {
  /* instrukcje */
}</pre>

<p>Jeśli konieczne jest użycie operatora przypisania w wyrażeniu warunku, najczęściej stosowaną praktyką jest zawieranie przypisania w dodatkowe nawiasy:</p>

<pre class="brush: js">if ((x = y)) {
  /* statements here */
}
</pre>

<h4 id="Wartości_false">Wartości false</h4>

<p>Poniższe wartości użyte w wyrażeniu warunku zostaną przekształcone w wartość <code>false</code>:</p>

<ul>
 <li><code>false</code>, zmienna typu Boolean</li>
 <li><code>undefined</code></li>
 <li><code>null</code></li>
 <li><code>0</code>, zmienna typu Number</li>
 <li><code>NaN</code>, zmienna typu Number</li>
 <li><code>""</code>, zmienna typu String</li>
</ul>

<p>Wszystkie inne wartości, włączając w to wszystkie obiekty, zostają przekształcone do wartości <code>true</code>.</p>

<p>Nie należy mylić pierwotnych wartości <code>true</code> i <code>false</code> z wartościami <code>true</code> i <code>false</code> obiektu {{jsxref("Boolean")}}:</p>

<pre class="brush: js">var b = new Boolean(false);
if (b) // Warunek zwróci wartość true gdyż zmienna b jest obiektem
if (b == true) // Warunek zwróci wartość false
</pre>

<h4 id="Przykład_2"><strong>Przykład</strong></h4>

<p>Następujący przykład przedstawia funkcje <code>checkData</code>, która zwróci <code>true</code> jeżeli liczba znaków w wartości elementu <code>threeChar</code> jest równa <code>3</code>, w przeciwnym wypadku zostanie wyświetlony alert i zwrócona wartość <code>false</code>.</p>

<pre class="brush: js">function checkData() {
  if (document.form1.threeChar.value.length == 3) {
    return true;
  } else {
    alert("Enter exactly three characters. " +
    document.form1.threeChar.value + " is not valid.");
    return false;
  }
}
</pre>

<h3 id="Instrukcja_switch">Instrukcja <code>switch</code></h3>

<p>Instrukcja <code>switch</code> pozwala na wykonanie bloku instrukcji jeśli podana wyrażenie zgadza się z identyfikatorem danego bloku. Gdy użyte zostanie słowo kluczowe <code>break</code>, switch wykonuje tylko instrukcje dopasowanego bloku. Bez niego wykonywane są wszystkie bloki poniżej dopasowania. Taka kaskadowość jest w wielu sytuacjach użyteczna.<br>
 W przypadku gdy wyrażenie nie zostanie dopasowane do żadnego identyfikatora, wykonywany jest kod z bloku o identyfikatorze <code>default</code>. Default nie jest obowiązkowy i może zostać pominięty.</p>

<pre class="syntaxbox">switch (wyrażenie) {
  case identyfikator_1:
    instruckje_1
    [break;]
  case identyfikator_2:
    instrukcje_2
    [break;]
    ...
  default:
    instruckje_def
    [break;]
}

</pre>

<h4 id="Przykład_3"><strong>Przykład</strong></h4>

<p>W następującym przykładzie, jeśli <code>fruittype</code> przekaże wartość "Bananas", program dopasuje ją do bloku z identyfikatorem "Bananas" i wykona instrukcje które zostały w tym bloku zdefiniowane. Po napotkaniu i wykonaniu instrukcji <code>break</code>, program przerywa działanie instrukcji switch. Gdyby w bloku "Bananas" nie występował break, zostałyby wykonane również instrukcje dla bloku "Cherries" i zatrzymały na tam napotkanej instrukcji <code>break</code>.</p>

<pre class="brush: js">switch (fruittype) {
  case "Oranges":
    console.log("Oranges are $0.59 a pound.");
    break;
  case "Apples":
    console.log("Apples are $0.32 a pound.");
    break;
  case "Bananas":
    console.log("Bananas are $0.48 a pound.");
    break;
  case "Cherries":
    console.log("Cherries are $3.00 a pound.");
    break;
  case "Mangoes":
    console.log("Mangoes are $0.56 a pound.");
    break;
  case "Papayas":
    console.log("Mangoes and papayas are $2.79 a pound.");
    break;
  default:
   console.log("Sorry, we are out of " + fruittype + ".");
}
console.log("Is there anything else you'd like?");</pre>

<h2 id="Instrukcje_obsługi_wyjątków">Instrukcje obsługi wyjątków</h2>

<p>Możliwe jest wywoływanie wyjątków za pomocą <code>throw</code> i ich późniejsza obsługa za pomocą instrukcji <code><font face="Consolas, Liberation Mono, Courier, monospace">try...catch.</font></code></p>

<ul>
 <li><a href="#throw_statement"><code>throw</code> statement</a></li>
 <li><a href="#try_catch_statement"><code>try...catch</code> statement</a></li>
</ul>

<h3 id="Typy_wyjątków">Typy wyjątków</h3>

<p>Praktycznie każda wartość czy obiekt może posłużyć do wygenerowania wyjątku w JavaScript. Nie mniej jednak  bardziej efektywne jest skorzystanie z już wbudowanych, specjalnie do tego przygotowanych typów jak np.</p>

<ul>
 <li><a href="/pl/docs/Web/JavaScript/Referencje/Obiekty/Error">Error</a></li>
</ul>

<h3 id="Instrukcja_throw">Instrukcja <code>throw</code></h3>

<p><code>throw</code> tworzy wyjątek. Kiedy wywołujesz wyjątek, musisz podać w danym wyrażeniu wartość, którą ma ten wyjątek zwrócić:</p>

<pre class="syntaxbox">throw wyrażenie;
</pre>

<p>Możesz wywoływać wyjątek z jakąkolwiek wartością. Podany kod rzuca wyjątki z wartościami różnych typów:</p>

<pre class="brush: js">throw "Error2";   // Ciąg znaków
throw 42;         // Typ liczbowy
throw true;       // Wartość Boolean
throw {toString: function() { return "I'm an object!"; } };
</pre>

<div class="note">
<p><strong>Notatka:</strong> Za pomocą instrukcji throw możesz zwrócić rówież obiekt. Możliwe jest osniesienie wartości objektu do właściwości bloku <code>catch</code>. Poniższy przykład tworzy obiekt <code>myUserException</code> typu <code>UserException</code> i używa go w instrukcji throw.</p>
</div>

<pre class="brush: js">// Create an object type UserException
function UserException(message) {
  this.message = message;
  this.name = "UserException";
}

// Make the exception convert to a pretty string when used as a string
// (e.g. by the error console)
UserException.prototype.toString = function() {
  return this.name + ': "' + this.message + '"';
}

// Create an instance of the object type and throw it
throw new UserException("Value too high");</pre>

<h3 id="Instrukcja_try...catch">Instrukcja <code>try...catch</code></h3>

<p><code>try...catch </code>jest instrukcją wykonującą pewien blok kodu i wyłąpującą w nim ewentualne wyjątki i błędy, które mogą zostać odpowiednio obsłużone.</p>

<p>Instrukcja <code>try...catch </code>zawiera blok <code>try</code>, w którym znajduje się jedna bądź więcej instrukcji i zero lub więcej bloków <code>catch</code> określających zachowanie programu w przypadku napotkania w bloku <code>try</code> jakiegoś wyjątku. Blok <code>try</code> testuje nie tylko bezpośrednio wywołane instrukcje, ale cały stos wywołań użytych funkcji.</p>

<pre class="brush: js">function test1() {
   test2();
};

function test2() {
   console.log(name);
};

try{
   test1();
}
catch(e){
   console.error(e); //ReferenceError: name is not defined
}</pre>

<pre class="brush: js">function getMonthName(mo) {
  mo = mo - 1; // Adjust month number for array index (1 = Jan, 12 = Dec)
  var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul",
                "Aug","Sep","Oct","Nov","Dec"];
  if (months[mo]) {
    return months[mo];
  } else {
    throw "InvalidMonthNo"; //throw keyword is used here
  }
}

try { // statements to try
  monthName = getMonthName(myMonth); // function could throw exception
}
catch (e) {
  monthName = "unknown";
  logMyErrors(e); // pass exception object to error handler -&gt; your own function
}
</pre>

<h4 id="Blok_catch">Blok <code><strong>catch</strong></code></h4>

<p>Możesz użyć bloku <code>catch</code> do obsługi wszystkich wyjątków jakie wystąpią w bloku <code>try</code>.</p>

<pre class="syntaxbox">catch (catchID) {
  instrukcje
}
</pre>

<p>Blok <code>catch</code> przyjmuje parametr catchID, który jest po prostu wartością wyrzuconą przez wyjątek.</p>

<h4 id="Blok_finally">Blok <code><strong>finally</strong></code></h4>

<p>Możliwe jest dodanie bloku <code>finally</code>, który wykona się niezależnie od tego czy kod w bloku <code>try</code> rzucił jakimś wyjątkiem czy nie.</p>

<pre class="brush: js">function test1(){
   test2();
};

function test2(){
   console.log(name)
};

try{
   test1();
}
catch(e){
   console.error(e) //ReferenceError: name is not defined
}
finally{
   console.log('Taka zmienna nie została zadeklarowana!')
}</pre>

<h4 id="Nesting_try...catch_Statements" name="Nesting_try...catch_Statements">Zagnieżdzone instrukcje <strong>try...catch</strong></h4>

<p>W swoim programie możesz użyć wielu zagnieżdzonych bloków <code>try...catch. </code>Jeśli wewnętrzny <code>try...catch </code>nie będzie posiadał bloku <code>catch,</code> wyjątek zostanie przekazany do zewnętrznego<code> try...catch.</code></p>

<h3 id="Wykorzystanie_obiektu_Error">Wykorzystanie obiektu Error</h3>

<p>W zależności od rodzaju błędu jaki chcesz wygnerować w swoim programie, możesz skorzystać z pól 'name' i 'message', aby uzyskać bardziej wyrafinowany log. 'name' zabiera nazwe ogólnej klasy błędu (np. 'DOMException'), z kolei 'message' zawiera bardziej szczegółową informacje okolicznościach powstania danego błędu.</p>

<p>Jeśli chcesz wywoływać własne wyjątki, aby skorzystać z zalet tych pól możesz użyć konstruktora Error:</p>

<pre class="brush: js">function doSomethingErrorProne () {
  if (ourCodeMakesAMistake()) {
    throw (new Error('The message'));
  } else {
    doSomethingToGetAJavascriptError();
  }
}
....
try {
  doSomethingErrorProne();
}
catch (e) {
  console.log(e.name); // logs 'Error'
  console.log(e.message); // logs 'The message' or a JavaScript error message)
}</pre>

<h2 id="Obietnice">Obietnice</h2>

<p>Począwszy od specyfikacji ECMAScript 6, JavaScript obsługuje obiekty obietnic pozwalające na kontrole przepływu opóźnionych i asynchronicznych operacji.</p>

<p>Obietnica może znajdować się w jednym z następujących stanów:</p>

<ul>
 <li><em>oczekiwanie</em>: stan początkowy, obietnica nie jest ani spełniona ani odrzucona.</li>
 <li><em>spełnienie</em>: operacja zakończona sukcesem.</li>
 <li><em>odrzucenie</em>: operacja zakończona niepowodzeniem.</li>
 <li><em>rozliczenie</em>: obietnica została spełniona lub odrzucona i nie jest już w stanie oczekiwania.</li>
</ul>

<p><img alt="" src="https://mdn.mozillademos.org/files/8633/promises.png" style="height: 297px; width: 801px;"></p>

<h3 id="Ładowanie_zdjęcia_za_pomocą_XHR">Ładowanie zdjęcia za pomocą XHR</h3>

<p>Prosty przykład użycia <code>Promise and <code><a href="/en-US/docs/Web/API/XMLHttpRequest">XMLHttpRequest</a> </code></code>do załadowania zdjęcia jeśli jest dostępne w MDN GitHub promise-test repozytorium. </p>

<pre class="brush: js">function imgLoad(url) {
  return new Promise(function(resolve, reject) {
    var request = new XMLHttpRequest();
    request.open('GET', url);
    request.responseType = 'blob';
    request.onload = function() {
      if (request.status === 200) {
        resolve(request.response);
      } else {
        reject(Error('Image didn\'t load successfully; error code:'
                     + request.statusText));
      }
    };
    request.onerror = function() {
      reject(Error('There was a network error.'));
    };
    request.send();
  });
}</pre>

<p>Aby dowiedzieć się więcej, sprawdź {{jsxref("Promise")}}.</p>

<div>{{PreviousNext("Web/JavaScript/Guide/Grammar_and_types", "Web/JavaScript/Guide/Loops_and_iteration")}}</div>