-
Notifications
You must be signed in to change notification settings - Fork 5
/
index.html
652 lines (631 loc) · 31.9 KB
/
index.html
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
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>girls.js - Funkcje</title>
<link rel="stylesheet" href="css/reveal.css">
<link rel="stylesheet" href="css/theme/simple.css">
<!-- Theme used for syntax highlighting of code -->
<link rel="stylesheet" href="lib/css/zenburn.css">
<link rel="icon" href="img/logo.svg">
<link rel="stylesheet" href="css/font-awesome.min.css">
<link rel="stylesheet" href="css/custom.css">
<link href="https://fonts.googleapis.com/css?family=Lato"; rel="stylesheet">
<!-- Printing and PDF exports -->
<script>
let link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = window.location.search.match(/print-pdf/gi) ? 'css/print/pdf.css' : 'css/print/paper.css';
document.getElementsByTagName('head')[0].appendChild(link);
</script>
<!-- facebook meta -->
<meta property="og:description" content="Materiały do krótkich warsztatów z cyklu girls.js: funkcje w JavaScript." />
<meta property="og:image" content="https://girlsjs.github.io/www/assets/logo.png"; />
</head>
<body>
<div class="left-bar">
<div class="left-bar-photo"></div>
</div>
<div class="help">
<a href="help.html">?</a>
</div>
<div class="reveal">
<div class="slides">
<section>
<div class="big-logo">
<img style="height: 400px; border: none; box-shadow: none;" src="img/logo.svg"/>
</div>
<h3 class="fragment grow">Cześć!</h3>
<p>(naciśnij spację, żeby kontynuować)</p>
<i class="fragment fade-down fa fa-angle-right"></i>
</section>
<section>
<h1 style="font-size: 3rem">Funkcje</h1>
<figure>
<img src="img/graph.gif" />
<figcaption style="font-size: 0.5rem">
Grafika zapożyczona z serwisu media.quizizz.com
</figcaption>
</figure>
</section>
<section>
<h3 style="font-size: 3rem">Funkcje</h3>
<p>Dziś poznamy lepiej funkcje. Są one bardzo ważną częścią języka JavaScript (i programowania w ogóle).</p>
</section>
<section>
<h3 style="font-size: 3rem">Do czego przydają się funkcje?</h3>
<p>Jeżeli byłyście na naszym warsztacie, pisałyście tam własne funkcje do obsługi przycisków na stronie.</p>
<p class="fragment">Funkcje przydają się, gdy chcemy ten sam kawałek kodu wykonać kilka razy.</p>
<p class="fragment">Można wykonywać go za każdym razem <strong>na innych danych</strong>.</p>
<p class="fragment">Funkcja może też zwracać wynik swojego działania, na którym reszta kodu będzie działać dalej.</p>
</section>
<section>
<h3 style="font-size: 3rem">Więc czym to się właściwie różni od pętli?</h3>
<p>Te z was, ktore znają pętle, wiedzą że też mogą wykonywać ten sam kod kilka razy...</p>
</section>
<section>
<p>Pętlę wykonujemy kilka razy jeden po drugim, i na tym koniec. Funkcję możemy wywołać w dowolnym momencie, z dowolnego miejsca w kodzie.</p>
<p class="fragment">Pętla musi mieć z góry przygotowane dane i działa na nich w ściśle określonej kolejności (0, 1, 2, ...). Funkcja za każdym razem może dostać nowy zestaw danych, niezależny od tego co było wcześniej.</p>
<p class="fragment">Podział na funkcje sprawia, że kod staje się bardziej przejrzysty, i łatwiej szukać w nim błędów.</p>
</section>
<section>
<h3 style="font-size: 3rem">A w praktyce?</h3>
<figure>
<img src="img/postit.jpg" />
<figcaption style="font-size: 0.5rem">
Grafika zapożyczona z <a href="https://www.orsgroup.com.au/blog/how-to-stress-down-for-stress-down-day/">orsgroup.com</a>;
</figcaption>
</figure>
</section>
<section>
<h3 style="font-size: 3rem">A w praktyce?</h3>
<p>Żeby wypisać karteczki w pętli, musimy z góry pamiętać, co na której będzie, w jakiej idą kolejności, i wypisać je wszystkie jedna po drugiej.</p>
<p class="fragment">Używając funkcji możemy pojedynczo dodawać nowe karteczki, kiedy tylko nam coś wpadnie do głowy - nawet kiedy zajmujemy się właśnie czymś zupełnie innym.</p>
</section>
<section>
<h3 style="font-size: 3rem">Na razie bez komputerów...</h3>
<p class="note task fragment fade-left">
Załóżmy, że chcemy dodać nową karteczkę do tablicy z poprzedniego slajdu. Zastanówmy się razem, jakie czynności będziemy musiały wykonać?
</p>
</section>
<section>
<h3 style="font-size: 3rem">Dodawanie nowej karteczki - na sucho :-)</h3>
<pre><code class="hljs javascript">1. Weź samoprzylepną karteczkę.
2. Weź długopis.
3. Napisz na karteczce tekst.
4. Przyklej karteczkę na tablicy.
5. Odłóż długopis (?)</code></pre>
</section>
<section>
<h3 style="font-size: 3rem">Czegoś tu brakuje?</h3>
<p class="note task fragment fade-left">
Skąd wiemy, jaki tekst napisać na karteczce?
</p>
</section>
<section>
<h3 style="font-size: 3rem">Dodawanie nowej karteczki - na sucho :-)</h3>
<pre><code class="hljs javascript">Funkcja: Dodaj nową karteczkę ( dany_tekst ):
1. Weź samoprzylepną karteczkę.
2. Weź długopis.
3. Napisz na karteczce dany_tekst.
4. Przyklej karteczkę na tablicy.
5. Odłóż długopis (?)</code></pre>
</section>
<section>
<h1 style="font-size: 3rem">Wszystko jasne do tej pory?</h1>
<figure>
<img src="img/llama.gif" />
</figure>
</section>
<section>
<h3>Anatomia funkcji</h3>
<p>Funkcję w JavaScript deklarujemy przy użyciu słowa <code>function</code>:</p>
<pre class="fragment"><code class="hljs javascript">function sum(x, y) {
return x + y;
}</code></pre>
<p class="fragment">Wartości w nawiasie to są <strong>parametry</strong> - dane, na których funkcja operuje.</p>
<p class="fragment">Słowem <code>return</code> oznaczamy wartość zwracaną przez funkcję, na której możemy operować dalej:</p>
<pre class="fragment"><code class="hljs javascript">let result = sum(2, 3) // result = 5</code></pre>
</section>
<section>
<h3>Gotowe? Do dzieła</h3>
<p>Pliki z kodem do pobrania znajdziecie <a href="exercises.zip">tutaj</a>.</p>
</section>
<section>
<h3>Otwórzmy teraz plik exercise.html</h3>
<figure>
<a href="exercise.html" target="_blank"><img src="img/screenshot.png" /></a>
</figure>
</section>
<section>
<h3>Zadanie 1</h3>
<p>W pliku mamy tablicę korkową z dodaną na niej karteczką.</p>
<p class="fragment">Naszym zadaniem będzie napisać funkcję, która doda do tablicy nową karteczkę, z dowolnym, podanym przez nas tekstem.</p>
</section>
<section>
<h3>Zadanie 1 - funkcje pomocnicze</h3>
<p>W tym celu możemy wykorzystać dwie napisane już funkcje pomocnicze:</p>
<ul>
<li class="fragment"><code>getNote()</code> - która tworzy nową karteczkę i zwraca ją jako wynik działania,</li>
<li class="fragment"><code>addNoteToBoard( note )</code> - bierze karteczkę przekazaną jako parametr i dodaje ją do tablicy.</li>
</ul>
</section>
<section>
<h3>Coś jeszcze?</h3>
<p>Zastanawiacie się pewnie, w jaki sposób napiszemy tekst na karteczce?</p>
<p class="fragment">Nasza karteczka, jak każdy element <a href="help.html#/document" target="_blank">dokumentu</a> HTML ma właściwość <code>innerText</code>. Cokolwiek w niej zapiszemy, stanie się treścią karteczki, np:</p>
<pre class="fragment"><code class="hljs javascript">element.innerText = 'Kodowanie jest fajne!'</code></pre>
</section>
<section>
<h3>Do dzieła!</h3>
<p class="note task fade-left">
Napiszmy funkcję <code>createNewNote</code>, która przyjmie jako parametr tekst, pobierze nową karteczkę korzystając z funkcji <code>getNote()</code>, napisze tekst na karteczce - zapisując go w <code>innerText</code>, a następnie doda karteczkę do tablicy przy użyciu funkcji <code>addNoteToBoard( note )</code>.
</p>
</section>
<section>
<h3>Gotowe?</h3>
<p>Powinno nam wyjść coś takiego:</p>
<pre class="fragment"><code class="hljs javascript">function createNewNote( text ) {
let newNote = getNote();
newNote.innerText = text;
addNoteToBoard( newNote );
}</code></pre>
</section>
<section>
<h1 style="font-size: 3rem">Wszystko się zgadza?</h1>
<p>Przetestujmy teraz tę funkcję w konsoli.</p>
<p class="fragment">Jak to zrobimy?</p>
<pre class="fragment"><code class="hljs javascript">createNewNote( "Zaprosić koleżankę na następne warsztaty" );</code></pre>
</section>
<section>
<h3>Bonus: spróbuj kliknąć na długopis i zobacz, co się wtedy stanie. </h3>
<p class="fragment">Jeżeli twoja funkcja nazywa się <code>createNewNote</code> i działa jak trzeba, powinnaś mieć wygodną opcję dodawania nowych karteczek.</p>
</section>
<section>
<h3>A co jeśli nie podamy żadnego tekstu?</h3>
<p>Żeby karteczka nie była pusta, można zaproponować domyślny tekst, który pojawi się tam, kiedy nie przekażemy żadnego parametru.</p>
<p class="fragment">W tym celu możemy użyć <strong>parametrów domyślnych</strong>.</p>
</section>
<section>
<h3>Jak działają parametry domyślne?</h3>
<p>Przy deklarowaniu funkcji i jej parametrów możemy podać domyślną wartość po znaku <code>=</code>. Na przykład:</p>
<pre class="fragment"><code class="hljs javascript">function setColor( color = 'yellow' ) {
// jeżeli podasz kolor w nawiasie, funkcja użyje tego, który podałaś
// jeżeli nie podasz żadnego, automatycznie ustawi się żółty
}</code></pre>
</section>
<section>
<h3>Wykorzystajmy to w praktyce.</h3>
<p class="note task fade-left">
W funkcji <code>createNewNote</code>, którą wcześniej napisałaś, dodaj domyślną treść, która ma się pojawić, kiedy nie podamy żadnego tekstu.
</p>
</section>
<section>
<h3>Proste, prawda?</h3>
<pre class="fragment"><code class="hljs javascript">function createNewNote( text = "Dokupić więcej żółtych karteczek" ) {
let newNote = getNote();
newNote.innerText = text;
addNoteToBoard( newNote );
}</code></pre>
</section>
<section>
<h3>No to lecimy dalej :-)</h3>
<figure class="fragment">
<img src="img/lets-do-this.gif" />
</figure>
</section>
<section>
<h3>Funkcja jako parametr innej funkcji</h3>
<p>W JavaScripcie parametrem funkcji może być praktycznie wszystko - włącznie z inną funkcją.</p>
<p class="fragment">Przydaje się to na przykład, kiedy chcemy powiązać funkcję z jakimś zdarzeniem, na przykład naciśnięciem klawisza.</p>
<p class="fragment">Albo zapamiętać zadanie do zrobienia na potem, zupełnie jak na żółtej karteczce.</p>
</section>
<section>
<h3>Przekazywanie funkcji jako parametr</h3>
<p>Żeby przekazać funkcję jako parametr podajemy w nawiasach jej nazwę:</p>
<pre class="fragment"><code class="hljs javascript">function cleanUpSomething () {
// funkcja ktorą chcemy wykonać za minutę
}
setTimeout( cleanUpSomething, 60000 );
// wykonaj funkcję cleanUpSomething za 60 sekund
</code></pre>
</section>
<section>
<h3>Przekazywanie funkcji jako parametr</h3>
<p>Możemy też zapisać całą funkcję jako parametr innej funkcji:</p>
<pre class="fragment"><code class="hljs javascript">setTimeout( function cleanUpSomething () {
// funkcja ktorą chcemy wykonać za minutę
}, 60000 );
// wykonaj funkcję cleanUpSomething za 60 sekund
</code></pre>
</section>
<section>
<h3>Przekazywanie funkcji jako parametr</h3>
<p>To czego nie możemy, to podać w nawiasach nazwę funkcji wraz z nawiasami:</p>
<pre class="fragment"><code class="hljs javascript">function cleanUpSomething ( data = '' ) {
// funkcja ktorą chcemy wykonać za minutę
}
setTimeout( cleanUpSomething(), 60000 );
setTimeout( cleanUpSomething( someData ), 60000 );
// w obu przypadkach funkcja cleanUpSomething wykona nam się od razu
</code></pre>
<p class="fragment">Jeżeli tak zrobimy, funkcja wykona nam się na miejscu zamiast być przekazana dalej.</p>
</section>
<section>
<h3>Do czego nam to potrzebne?</h3>
<p>Otwórzmy teraz plik z drugim zadaniem, exercise2.html</p>
<figure>
<a href="exercise2.html" target="_blank"><img src="img/screenshot2.png" /></a>
</figure>
</section>
<section>
<h3>Zadanie 2</h3>
<p>Mamy przed sobą częściowo oprogramowany kalkulator. W tym momencie jeszcze żaden guziczek nie działa - żeby go ożywić, musimy napisać kilka nowych funkcji, i podłączyć je pod odpowiednie guziki.</p>
</section>
<section>
<h3>Czyszczenie ekranu</h3>
<p class="fragment">Zacznijmy od w miarę prostego przypadku. Przycisk <strong>C</strong> zazwyczaj służy do wyczyszczenia ekranu - zmiany tego, co na nim jest na zero. Zastanówmy się (na razie po polsku) co powinno się wydarzyć, kiedy ktoś wciśnie ten przycisk.</p>
</section>
<section>
<h2>Gotowe?</h2>
<p>Zobaczmy, co nam wyszło:</p>
<pre class="fragment"><code class="hljs javascript">Kiedy wciśnięto przycisk C:
1. Zapisz 0 jako aktualny numer,
2. Wyświetl aktualny numer na ekranie.
</code></pre>
</section>
<section>
<p>Do wyświetlenia liczby na ekranie możemy użyć właściwości <code>innerText</code>, którą poznałyśmy już wcześniej. Tylko jak podpiąć ją do ekranu kalkulatora?</p>
</section>
<section>
<p>
Dowolny element na stronie możemy "zbadać" narzędziami przeglądarki:
</p>
<figure>
<img src="img/inspect.png" />
</figure>
</section>
<section>
<p>A następnie pobrać jego selektor w drzewie po prawej:</p>
<figure>
<img src="img/inspect2.png" />
</figure>
</section>
<section>
<p>Używając tego selektora możemy teraz dobrać się do elementu, używając <a href="help.html#/querySelector">document.querySelector</a>, np:</p>
<pre class="fragment"><code class="hljs javascript">document.querySelector('#screen').innerText = "Siemanko!";</code></pre>
</section>
<section>
<p>Możemy uzupełnić nasz pseudokod o bardziej szczegółowe instrukcje:</p>
<pre class="fragment"><code class="hljs javascript">Kiedy naciśnięto przycisk C:
1. Zapisz 0 jako aktualny numer,
2. Znajdź element o selektorze '#screen',
3. Podmień jego zawartość na aktualny numer.
</code></pre>
</section>
<section>
<h2>Wszystko jasne?</h2>
<p class="note task fragment fade-left">
W pliku <code>exercise2.html</code> dodaj nową funkcję o nazwie <code>reset</code>. Funkcja ta powinna zrobić dwie rzeczy: zapisać 0 w zmiennej <code>currentNumber</code>, oraz złapać element <code>'#screen'</code> i podmienić jego zawartość, na to co mamy w tej zmiennej. Pamiętaj, żeby użyć tych samych nazw funkcji i zmiennych, inaczej nasz kod nie będzie współpracował z resztą.
</p>
</section>
<section>
<h2>I jak nam poszło?</h2>
<pre class="fragment"><code class="hljs javascript">function reset() {
currentNumber = 0;
document.querySelector('#screen').innerText = currentNumber;
}
</code></pre>
<p class="fragment">Przetestujmy, jak to działa w konsoli. </p>
</section>
<section>
<p>To, czego potrzebujemy teraz to powiązać tę funkcję z akcją, kiedy ktoś naciśnie na przycisk <strong>C</strong></p>
</section>
<section>
<p>Uwaga, będzie dużo nowych rzeczy naraz!</p>
</section>
<section>
<h3>Są tu absolwentki warsztatów Girls.js?</h3>
<p>Poznałyśmy tam metodę <code>addEventListener</code>, która pozwala powiązać funkcję z wydarzeniem na elemencie. </p>
<ul class="note more fragment">
<li><code>element.addEventListener( wydarzenie, akcja-do-wykonania )</code> - wykonuje
podaną akcję, gdy z elementem stanie się coś konkretnego.
</li>
</ul>
</section>
<section>
<h3>addEventListener - przykład</h3>
<pre class="fragment"><code class="hljs javascript">document.querySelector( '#button' ).addEventListener( 'click',
nazwaMojejFunkcji );</code></pre>
<p class="fragment">Czyli jak to wszystko razem będzie po polsku?</p>
</section>
<section>
<p>Dopiszmy brakujące fragmenty pseudokodu:</p>
<pre class="fragment"><code class="hljs javascript">Funkcja reset:
1. Zapisz 0 jako aktualny numer,
2. Znajdź element o selektorze '#screen',
3. Podmień jego zawartość na aktualny numer.
1. Znajdź element o selektorze '#C',
2. Powiąż wydarzenie 'click' na tym elemencie z funkcją reset.
</code></pre>
</section>
<section>
<h3>No to do dzieła!</h3>
<p class="note task fragment fade-left">
Powiąż teraz funkcję <code>reset</code>, którą napisałaś, z przyciskiem <code>C</code>. Do przycisku możesz odnieść się przy użyciu <code>document.querySelector</code>. Jeżeli nie jesteś pewna jaki jest selektor elementu, sprawdź w narzędziach przeglądarki. Użyj <code>addEventListener</code> żeby powiązać kliknięcie na tym przycisku z funkcją <code>reset</code>.
</p>
</section>
<section>
<h3>Gotowe?</h3>
<p class="fragment">
Tak powinna wyglądać całość:
</p>
<pre class="fragment"><code class="hljs javascript">function reset() {
currentNumber = 0;
document.querySelector('#screen').innerText = currentNumber;
}
document.querySelector('#C').addEventListener( 'click', reset );
</code></pre>
<p class="fragment">Sprawdźmy, jak to teraz działa.</p>
</section>
<section>
<h3>Przyciski z liczbami</h3>
<p>Teraz zajmiemy się oprogramowaniem przycisków od 0 do 9.</p>
</section>
<section>
<p>Nie będziemy szczegółowo wszystkiego same programować, bo dzieje się tu sporo:</p>
<ul>
<li class="fragment">Musimy wiedzieć, czy dopisujemy cyfry do kolejnej liczby, czy zaczynamy nową,</li>
<li class="fragment">Uważamy, żeby nie dopisać cyfr do zera z przodu (bo wyszłoby nam 05),</li>
<li class="fragment">Uważamy, żeby nie przekroczyć 11 znaków, ktore mieszczą się na wyświetlaczu,</li>
<li class="fragment">Zapamiętujemy całą liczbę jako tekst, żeby łatwiej nam było wprowadzać ułamki. </li>
</ul>
</section>
<section>
<p>Tym wszystkim zajmuje się gotowa już funkcja <code>numberKeyPressed( number )</code>, zapisana w pliku <code>calc.js</code> (w domu możecie sprawdzić, jak ta funkcja działa).</p>
<p class="fragment">Bierze ona liczbę od 0 do 9 jako parametr, i robi wszystko co potrzeba, żeby w odpowiedni sposob dopisać ją na ekranie.</p>
</section>
<section>
<p>Naszym zadaniem będzie powiązać funkcję <code>numberKeyPressed</code> z naciśnięciem kolejnych guziczków. Przykładowo, po wciśnięciu guziczka 1 chcemy wywołać tę funkcję z parametrem 1. </p>
<p>Tradycyjnie, zapiszmy najpierw po polsku, co chcemy, żeby się stało.</p>
</section>
<section>
<h3>Gotowe?</h3>
<pre class="fragment"><code class="hljs javascript">1. Znajdź przycisk z numerem 1 (selektor '#number1')
2. Powiąż wydarzenie 'click' na tym elemencie z funkcją numberKeyPressed.
3. Przekaż do tej funkcji parametr 1.
</code></pre>
<p class="fragment">Jest tylko jeden haczyk...</p>
</section>
<section>
<p>Nie możemy tak po prostu przekazać jako parametr funkcji <code>numberKeyPressed</code> z własnym parametrem.</p>
<p class="fragment">Jeżeli zapiszemy to jako <code>numberKeyPressed( 1 )</code>, funkcja wykona nam się od razu, zamiast powiązać z przyciskiem.</p>
<p class="fragment">Co z tym zrobimy? Na ratunek przyjdzie nam <strong>funkcja anonimowa</strong>.</p>
</section>
<section>
<h3>Funkcja anonimowa</h3>
<p>To funkcja, która nie ma swojej nazwy. Wygląda na przykład tak:</p>
<pre class="fragment"><code class="hljs javascript">function (x, y) {
return x + y;
}</code></pre>
</section>
<section>
<h3>Po co więc nam funkcje anonimowe?</h3>
<p class="fragment">Możemy je przypisać do zmiennej:</p>
<pre class="fragment"><code class="hljs javascript">let sum = function (x, y) {
return x + y;
}
</code></pre>
<p class="fragment">Ale to wiele nie różni się od funkcji nazwanej:</p>
<pre class="fragment"><code class="hljs javascript">sum( 2, 3 ) // zwróci 5
</code></pre>
</section>
<section>
<h3>Funkcja anonimowa</h3>
<p>Prawdziwy użytek można zrobić z funkcji anonimowych przy przekazywaniu jej jako parametr do innej funkcji, albo przy tworzeniu ich dynamicznie (czytaj: na bieżąco).</p>
</section>
<section>
<h3>Pamiętacie nasz przykład z odkładaniem zadania na potem?</h3>
<pre class="fragment"><code class="hljs javascript">function cleanUpSomething ( data = '' ) {
// funkcja ktorą chcemy wykonać za minutę
}
setTimeout( cleanUpSomething( someData ), 60000 );
// funkcja cleanUpSomething wykona nam się od razu
setTimeout( function () {
cleanUpSomething( someData );
}, 60000 );
// funkcja cleanUpSomething wykona się za minutę,
// i będzie miała dostęp do zmiennej someData
</code></pre>
</section>
<section>
<h3>Wszystko w miarę jasne?</h3>
<figure>
<img src="img/mindblown.gif" />
</figure>
</section>
<section>
<h3>To spróbujmy to wykorzystać w praktyce :-)</h3>
<p class="note task fragment fade-left">
Napisz kod, który powiąże przycisk 1 z wywołaniem funkcji <code>numberKeyPressed</code> z odpowiednim parametrem. Potrzebna ci będzie funkcja anonimowa, żeby móc jej ten parametr przekazać. Tradycyjnie przyda nam się <code>document.querySelector</code> do złapania elementu, i <code>addEventListener</code> żeby powiązać kliknięcie na tym przycisku z naszą funkcją.
</p>
</section>
<section>
<h3>Co nam wyszło?</h3>
<pre class="fragment"><code class="hljs javascript">document.querySelector('#number1').addEventListener( 'click',
function () {
numberKeyPressed( 1 );
});</code></pre>
<p class="fragment">Działa?</p>
</section>
<section>
<h3>To zróbmy teraz to samo dla pozostałych 9 przycisków</h3>
<p>Najlepiej do tego celu będzie użyć pętli.</p>
</section>
<section>
<h3>Szybka ściągawka jak wygląda pętla</h3>
<pre class="fragment"><code class="hljs javascript">for (warunek początkowy; warunek trwania pętli; instrukcja przejścia) {
// wykonaj ten kod tak długo jak warunek trwania pętli jest prawdziwy
}</code></pre>
</section>
<section>
<p>Czyli przy 10 elementach od 0 do 9 będziemy miały:</p>
<pre class="fragment"><code class="hljs javascript">for (let i=0; i<10; i++) {
// wykonaj ten kod tak długo jak warunek trwania pętli jest prawdziwy
}</code></pre>
</section>
<section>
<h3>Składamy wszystko razem do kupy...</h3>
<p class="note task fragment fade-left">
Przerób kod z poprzedniego etapu, tak żeby przypisywał wywołanie funkcji <code>numberKeyPressed</code> z odpowiednim parametrem do każdego z przycisków od 0 do 9. Wykorzystaj w tym celu pętlę, i pamiętaj o użyciu odpowiednich selektorów.
</p>
</section>
<section>
<h3>Sprawdzamy czy działa:</h3>
<pre class="fragment"><code class="hljs javascript">for( let i = 0; i < 10; i++ ) {
document.querySelector('#number' + i).addEventListener( 'click',
function () {
numberKeyPressed( i );
});
} </code></pre>
<p class="fragment">Jak wyszły testy?</p>
</section>
<section>
<h3>To teraz przed nami najtrudniejsze zadanie</h3>
<p>Zostały nam do oprogramowania jeszcze guziczki <code>+</code>, <code>-</code>, <code>x</code> i <code>/</code>. Zastanówmy się przez chwilę, jaką funkcję pełnią w kalkulatorze (możemy otworzyć standardową aplikację kalkulatora do pomocy).</p>
</section>
<section>
<h3>Zapamiętanie funkcji na potem</h3>
<p>W momencie, gdy naciśniemy przycisk <code>+</code>, nie wykonujemy jeszcze operacji dodawania. Kalkulator zapamiętuje wtedy liczbę, jaką do tej pory wpisałyśmy, zapamiętuje, że następną operacją będzie dodawanie, i czeka na drugą liczbę, ktorą należy do niej dodać.</p>
</section>
<section>
<h3>To jeszcze nie wszystko!</h3>
<p>Jeżeli miałyśmy już wcześniej zapamiętaną jakąś operację, to wykona się ona również w momencie naciśnięcia znaku <code>+</code>. Niekoniecznie musi być to dodawanie - może to być zupełnie inna, zapamiętana wcześniej operacja.</p>
</section>
<section>
<h3>Zapamiętanie funkcji na potem</h3>
<p>Szczegóły tego, jak zapamiętujemy funkcję i kolejne liczby sobie dzisiaj darujemy - kto chce, może poczytać sobie plik <code>calc.js</code> w domu.</p>
<p class="fragment">Dzisiaj skorzystamy z gotowej funkcji <code>scheduleNextOperation( operation )</code>, ktora przyjmuje jako parametr funkcję operującą na dwóch liczbach, i robi wszystko co trzeba, żeby potem to dodawanie mogło się wykonać.</p>
</section>
<section>
<h3>Funkcja sumy</h3>
<p class="note task">Na początek napiszemy samą funkcję <code>sum( x, y )</code>, która przyjmuje 2 liczby i zwraca ich sumę jako wynik.</p>
</section>
<section>
<h3>Proste, prawda?</h3>
<pre class="fragment"><code class="hljs javascript">function sum ( x, y ) {
return x + y;
} </code></pre>
<p class="fragment">Możemy sprawdzić, czy wszystko dobrze działa w konsoli.</p>
</section>
<section>
<p>Teraz pozostaje nam oprogramować guziczek <code>+</code> - jeżeli ktoś go naciśnie, chcemy wywołać funkcję <code>scheduleNextOperation</code> i przekazać do niej funkcję, którą właśnie napisałyśmy.</p>
<p class="fragment">Żeby móc przekazać parametr do funkcji, która obsługuje zdarzenie, musimy posłużyć się funkcją anonimową.</p>
</section>
<section>
<h3>No to do dzieła!</h3>
<p class="note task fragment fade-left">
Znajdź selektor przycisku <code>+</code>, i powiąż wydarzenie <code>click</code> na tym elemencie z wywołaniem funkcji <code>scheduleNextOperation</code> z funkcją <code>sum</code> jako parametrem. Użyj w tym celu metody <code>addEventListener</code> i funkcji anonimowej.
</p>
</section>
<section>
<h3>Mamy pewnie coś takiego:</h3>
<pre class="fragment"><code class="hljs javascript">function sum( x, y ) {
return x + y;
}
document.querySelector("#plus").addEventListener( 'click' , function() {
scheduleNextOperation ( sum );
});</code></pre>
<p class="fragment">Skoro mamy już oprogramowane guziczki z liczbami i znak plus, możemy przetestować jak to wszystko działa :-)</p>
</section>
<section>
<p>Wszystko działa dobrze? To została nam jeszcze jedna rzecz - zrobić to samo dla przycisków <code>-</code>, <code>x</code> i <code>/</code>.</p>
<p class="fragment">Na tej samej zasadzie napiszmy funkcję, która wykona nam działanie matematyczne i zapamiętajmy ją na potem po naciśnięciu odpowiedniego przycisku.</p>
</section>
<section>
<h3>Teraz to już będzie proste</h3>
<p class="note task fragment fade-left">
Dopisz brakujące funkcje odejmowania, mnożenia i dzielenia, i powiąż każdą z odpowiednim przyciskiem. Uwaga, znak mnożenia w JavaScript to wcale nie jest <code>x</code>!
</p>
</section>
<section>
<h3>Sprawdzamy</h3>
<pre class="fragment"><code class="hljs javascript">function substract( x, y ) {
return x - y;
}
document.querySelector("#minus").addEventListener( 'click' , function() {
scheduleNextOperation ( substract );
});
function multiply( x, y ) {
return x * y;
}
document.querySelector("#multiply").addEventListener( 'click' , function() {
scheduleNextOperation ( multiply );
});
function divide( x, y ) {
return x / y;
}
document.querySelector("#divide").addEventListener( 'click' , function() {
scheduleNextOperation ( divide );
});</code></pre>
</section>
<section>
<h3>Najwyższa pora potestować nasz kalkulator :-)</h3>
</section>
<section data-transition="zoom" data-transition-speed="slow">
<p>To już wszystko, co przygotowaliśmy na dzisiaj. Dzięki za wspólnie spędzony czas i do zobaczenia!</p>
<img src="img/logo.svg" style="border: none; box-shadow: none;"/>
</section>
</div>
<div class="small-duck"></div>
<div class="footer">
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/3.0/pl/">
<img
alt="Licencja Creative Commons" style="border-width:0;vertical-align:bottom"
src="./img/cc.png" />
</a>
<span>
Ta prezentacja jest dostępna na
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/3.0/pl/">;
licencji Creative Commons Uznanie autorstwa-Użycie niekomercyjne-Na tych
samych warunkach 3.0 Polska
</a>.
</span>
</div>
</div>
<script src="lib/js/head.min.js"></script>
<script src="js/reveal.js"></script>
<script>
// More info https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
history: true,
controls: false,
progress: false,
center: true,
transition: 'convex',
slideNumber: 'true',
// More info https://github.com/hakimel/reveal.js#dependencies
dependencies: [
{
src: 'plugin/highlight/highlight.js', async: true, callback: function () {
hljs.initHighlightingOnLoad();
}
}
]
});
function changeTopBar(slideNumber) {
if (slideNumber === 0) {
document.querySelector('.left-bar').classList.add('big')
} else {
document.querySelector('.left-bar').classList.remove('big')
}
}
Reveal.addEventListener('slidechanged', function( event ) {
changeTopBar(event.indexh)
});
setTimeout(changeTopBar(Reveal.getIndices()['h']), 100)
</script>
</body>
</html>