-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathAppA_Primer.html
More file actions
1139 lines (1101 loc) · 54.1 KB
/
AppA_Primer.html
File metadata and controls
1139 lines (1101 loc) · 54.1 KB
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
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="en">
<head>
<title>JavaScript: AppA Primer</title>
<meta name="title" content="Variations on a Theme: JavaScript: AppA Primer">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta charset="UTF-8">
<meta name="description" content="An object-oriented Introduction">
<meta name="keywords" content="JavaScript,object orientation,introduction">
<meta name="author" content="Ralph P. Lano">
<meta name="robots" content="index,follow">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="book.css">
</head>
<body>
<center>
<div id="wrap">
<ul class="sidenav">
<p><a href="../index.html">Variations on a Theme</a><a href="index.html">JavaScript</a></p>
<li><a href="Ch1_Karel.html">Karel</a></li>
<li><a href="Ch2_Graphics.html">Graphics</a></li>
<li><a href="Ch3_Console.html">Console</a></li>
<li><a href="Ch4_Agrar.html">Agrar</a></li>
<li><a href="Ch5_MindReader.html">MindReader</a></li>
<li><a href="Ch6_Swing.html">Swing</a></li>
<li><a href="Ch7_Asteroids.html">Asteroids</a></li>
<li><a href="Ch8_Stocks.html">Stocks</a></li>
<li><a href="index.html"> </a></li>
<li><a href="AppA_Primer.html">Primer</a></li>
<li><a href="AppB_Libraries.html">Libraries</a></li>
<li><a href="AppC_Ideas.html">Ideas</a></li>
</ul>
<div class="content">
<h1>
JavaScript Primer</h1>
<p>
This is a very brief and superficial introduction to JavaScript. The books in the references are much better and you should get all of them. Here we only do client-side, browser-based JavaScript. Also, we use ES6. Although the class syntax is considered to be only syntactic sugar, we actually like sugar quite a lot.</p>
<p>
JavaScript was invented by Brendan Eich in 1995. Its syntax is somewhat inspired by Java, but it has very little to do with Java. To understand some of the differences, the following comparison might be helpful:</p>
<table align="center" border="0" cellpadding="1" cellspacing="1" width="200">
<tbody>
<tr>
<td>
<b>Java</b></td>
<td>
<b>JavaScript</b></td>
</tr>
<tr>
<td>
Strongly-typed</td>
<td>
Loosely-typed</td>
</tr>
<tr>
<td>
Static</td>
<td>
Dynamic</td>
</tr>
<tr>
<td>
Classical</td>
<td>
Prototypal</td>
</tr>
<tr>
<td>
Classes</td>
<td>
Functions</td>
</tr>
<tr>
<td>
Constructors</td>
<td>
Functions</td>
</tr>
<tr>
<td>
Methods</td>
<td>
Functions</td>
</tr>
</tbody>
</table>
<p>
The key differences being that Java has a statically typed system, whereas JavaScript has a dynamic type system. And in JavaScript basically almost everythings seems to be a function.</p>
<p>
With the advent of ES6 JavaScript has many new features. Most people say it is just syntactic sugar, but in my opinion it is much more than that. We will introduce a few of them here, such as classes, inheritance, closure, generators, and promises.</p>
<p>
.</p>
<h2>
Introduction</h2>
<p>
The simplest way to run JavaScript is in the browser. Use your favorite text editor, such as Notepad, Mousepad, TextEdit, or vi, and type the following into a file you can call "index.html":</p>
<pre style="margin-left: 40px;">
<html>
<head>
<span style="color:#0000ff;"> <script type="text/javascript">
alert("Hello world!");
</script></span>
</head>
</html></pre>
<p>
Now simply open it with your browser and a pop-up box saying "Hello world!" should show up. You could place the script tag also inside the body, but usually it is placed inside the head tag.</p>
<p>
Next, let us consider <em>functions</em>, the bread and butter of JavaScript.</p>
<pre style="margin-left: 40px;">
<html>
<head>
<script type="text/javascript"><span style="color:#0000ff;">
<span style="color:#0000ff;"><span style="color:#0000ff;"> <span style="color:#0000ff;"> </span></span>function run() {
<span style="color:#0000ff;"> <span style="color:#0000ff;"> </span></span> <span style="color:#0000ff;">document.write</span>("Hello world!");
<span style="color:#0000ff;"> <span style="color:#0000ff;"> </span></span>}</span>
</span> </script>
</head>
<body <span style="color:#0000ff;">onload="run()</span>;">
</body>
</html></pre>
<p>
Here we actually use three features of JavaScript: <em>functions</em>, <em>events</em> and the <em>DOM</em>. Functions are declared inside script tags, they start with the keyword "function", often have a name and have a function body, containing JavaScript code:</p>
<pre style="margin-left: 40px;">
function run() {
document.write("Hello world!");
}</pre>
<p>
The word "document" refers to an HTML document and is part of the browsers DOM. DOM stands for Document Object Model and it is a JavaScript wrapper around all the different HTML elements in the browser. Most important are the <em>window</em> and the <em>document</em> objects.</p>
<p>
JavaScript has many events, in our example we use the <em>onload</em> event:</p>
<pre style="margin-left: 40px;">
<body <span style="color:#0000ff;">onload="run();</span>">
</body>
</pre>
<p>
It is triggered when the browser has finished loading the whole HTML page. The above tells the browser to execute the JavaScript function <em>run()</em> after the HTML page has loaded completely. Interestingly, for very large pages, JavaScript may actually start running before the whole page is loaded, this can cause problems when JavaScript tries to access parts that haven't even loaded. Hence it is advisable to only start executing JavaScript code after the whole page has loaded.</p>
<p>
Finally, let us talk about JavaScript files. Instead of mixing HTML with JavaScript code, we can also place them in separate files. In this case the "index.html" file would look like this:</p>
<pre style="margin-left: 40px;">
<html>
<head>
<script type="text/javascript" src="<span style="color:#0000ff;">script.js</span>"></script>
</head>
<body <span style="color:#0000ff;">onload="run()</span>;">
</body>
</html></pre>
<p>
and we put the JavaScript code inside a file called "script.js":</p>
<pre style="margin-left: 40px;">
function run() {
document.write("Hello world!");
}</pre>
<p>
This is clearly the preferred way of writing JavaScript code. First, it separates look (HTML) from function (JavaScript). Especially, when both get large, this is very helpful. And second, it allows for reuse, meaning, we can include the same JavaScript file in many different HTML pages.</p>
<p>
.</p>
<h2>
Popup Boxes</h2>
<p>
For simple interaction with the user, JavaScript has three kind of popup boxes: <em>alert</em>, <em>confirm</em>, and <em>prompt</em>. The alert, we have seen already:</p>
<pre style="margin-left: 40px;">
function showAlert() {
alert("I am an alert box!");
}
</pre>
<p>
The confirm box is often used if we want the user to verify or accept something. When a confirm box pops up, the user will have to click either "OK" or "Cancel" to proceed. If the user clicks "OK", the box returns true, if the user clicks "Cancel", the box returns false.</p>
<pre style="margin-left: 40px;">
function showConfirm() {
let b=confirm("Press a button");
if ( b === true ) {
document.write("You pressed OK!");
} else {
document.write("You pressed Cancel!");
}
}
</pre>
<p>
The prompt box is often used if you want the user to enter some value. When a prompt box pops up, the user will have to click either "OK" or "Cancel" to proceed after entering an input value. If the user clicks "OK" the box returns the input value. If the user clicks "Cancel" the box returns <em>null</em>.</p>
<pre style="margin-left: 40px;">
function showPrompt() {
let name = prompt("Please enter your name", "Harry Potter");
if ( name !== null ) {
document.write("Hello " + name + "!");
}
}
</pre>
<p>
.</p>
<h2>
Variables</h2>
<p>
Let us consider some simple variable declarations:</p>
<pre style="margin-left: 40px;">
x;
var y;
let z;
const c;
</pre>
<p>
The first one declares the variable x. This maybe surprising, especially if you come from other programming languages, but JavaScript is a weakly typed language, meaning you do not have to declare variables at all. Also, you do not specify a data type. The JavaScript interpreter tries to do its best to figure this out by itself. </p>
<p>
This seems very convenient, but may lead to problems. The most common has to do with typos: you slightly misspell a variable name. In normal languages, the compiler would give an error message that the variable was not declared. Not so in JavaScript: the interpreter thinks you want a new variable, and declares it for you automatically. However, you can tell the interpreter not to do that with "use strict", which you should.</p>
<p>
Therefore, preferrably we use the other declarations with the keywords <em>var</em>, <em>let</em>, and <em>const</em>. The last one is always preferred, if a variable does not change, declare it a constant. The difference between the other two is subtle. Consider the following examples [2]:</p>
<pre style="margin-left: 40px;">
function varTest() {
var x = 1;
{
var x = 2; // same variable!
console.log(x); // 2
}
console.log(x); // 2
}
function letTest() {
let x = 1;
{
let x = 2; // different variable
console.log(x); // 2
}
console.log(x); // 1
}</pre>
<p>
A variable declared with <em>let</em> is restricted to the scope in which it is defined, that is inside the curly braces.</p>
<p>
In general, it is better to use <em>let</em>, unless one explicitely wants to create a <em>global</em> variable. Because <em>let</em>, unlike <em>var</em>, does not allow you to create a global variable:</p>
<pre style="margin-left: 40px;">
var x = "global";
let y = "global";
console.log(this.x); // "global"
console.log(this.y); // undefined</pre>
<p>
If you declare a variable within a function, the variable can only be accessed within that function. When you exit the function, the variable is destroyed. These variables are called local variables. You can have local variables with the same name in different functions, because each is recognized only by the function in which it is declared.</p>
<p>
.</p>
<h2>
Data Types</h2>
<p>
In JavaScript you do not have much control over your data types. However, they do exist internally. The simplest one being</p>
<ul>
<li>
number,</li>
<li>
string,</li>
<li>
boolean,</li>
<li>
and undefined.</li>
</ul>
<p>
You may notice, there is no difference between integers and floating point numbers. JavaScript infers the actual data type from the declaration:</p>
<pre style="margin-left: 40px;">
let x = 42;
let y = 42.0;
let z = "42";
</pre>
<p>
So <em>x</em> is actually treated as an integer, <em>y</em> as a floating point number, and <em>z</em> as a string. But as soon as it is needed, JavaScript will perform automatic type conversion. However, only in one direction, that is from integer to floating point, integer to string and floating point to string, but not the other way round.</p>
<p>
For this the conversion functions are helpful:</p>
<pre style="margin-left: 40px;">
let x = parseInt("42");
let y = parseFloat("42.0");
let z = Math.trunc(42.0);</pre>
<p>
The last one converts a floating point number to an integer. Always use <em>trunc()</em>, because <em>floor()</em> works differently on negative numbers.</p>
<h3>
Arrays and Objects</h3>
<p>
In JavaScript we also have complex data types, arrays and objects. Arrays are declared with square brackets:</p>
<pre style="margin-left: 40px;">
let arr1 = [];
let arr2 = [1, 2, 3, 4];</pre>
<p>
The first is an empty array and the second is an array with four elements. Arrays in JavaScript can grow and shrink.</p>
<p>
Similarily, objects are defined using curly braces, with a list of key-value pairs:</p>
<pre style="margin-left: 40px;">
let cat = { name: "Garfield", age: 42 };</pre>
<p>
In this context also the JavaScript Object Notation (JSON) is interesting, since it is a simple way to represent these arrays and objects. For instance the above cat would become:</p>
<pre style="margin-left: 40px;">
"cat": { "name": "Garfield", "age": 42 }</pre>
<h3>
Functions</h3>
<p>
Finally, unless you are used to C's function pointers, the following may seem a little strange:</p>
<pre style="margin-left: 40px;">
let f = function() { alert("hi"); };
f();
</pre>
<p>
Here we seem to define a variable called <em>f</em>, which actually is a function, not a variable. The second line shows how <em>f</em> is being used.</p>
<h3>
typeof</h3>
<p>
You can ask the JavaScript interpreter what the type of a given variable is with the <em>typeof</em> operator. For instance, the following code</p>
<pre style="margin-left: 40px;">
let x = 42;
console.log( typeof(x) );</pre>
<p>
would output "number" to the console. You may want to try the following examples to see how the typeof operator works.</p>
<pre style="margin-left: 40px;">
function run() {
let u1;
console.log(typeof (u1)); // undefined
let u2 = undefined;
console.log(typeof (u2)); // undefined
let x = 42;
console.log(typeof (x)); // number
let y = 42.0;
console.log(typeof (y)); // number
let z = "42";
console.log(typeof (z)); // string
let b = true;
console.log(typeof (b)); // boolean
let n = null;
console.log(typeof (n)); // object
let arr = [];
console.log(typeof (arr)); // object
let obj = { name: "Garfield", age: 42 };
console.log(typeof (obj)); // object
let f = function () { };
console.log(typeof (f)); // function
}</pre>
<p>
Interesting maybe that <em>null</em>, <em>arrays</em> and <em>objects</em> are all considered objects.</p>
<p>
.</p>
<h2>
Operators</h2>
<p>
JavaScript has the standard arithmetic and assignment operators: =, +, -, *, /, %, ++ and --. The + operator can also be used to concatenate strings. When adding a number and a string, the result will be a string. </p>
<p>
Comparison and logical operators are used to test for true or false. We have the standard comparison operators</p>
<pre style="margin-left: 40px;">
== equal
!= not equal
> larger than
< less than
>= larger than or equal
<= less than or equal</pre>
<p>
In addition, JavaScript has two more comparison operators: the exactly equals === and the not exactly equals !==. They compare not only value but also type. The following example shows the difference:</p>
<pre style="margin-left: 40px;">
let x = 42;
let y = "42";
if (x == y) {
console.log("x and y are equal");
}
if (x === y) {
console.log("x and y are exactly equal");
}</pre>
<p>
In general, always use the exactly equals operators. </p>
<p>
As for the logical operators again those work exactly as in Java or C++. </p>
<p>
As for the bitwise operators, strange things might happen here, and they are slow. So no point in using them.</p>
<p>
.</p>
<h2>
Conditional Statements</h2>
<p>
As for conditions, JavaScript has the standard if-else statement:</p>
<pre style="margin-left: 40px;">
let dt = new Date()
let time = dt.getHours()
if (time < 10) {
alert("Good morning");
} else if (time > 10 && time < 16) {
alert("Good day");
} else {
alert("Good evening");
}
</pre>
<p>
In addition, there is also the standard <em>switch</em> statement which works as expected.</p>
<p>
.</p>
<h2>
Loops</h2>
<p>
JavaScript has the standard for-loop:</p>
<pre style="margin-left: 40px;">
for (<span style="color:#0000ff;">let</span> i = 0; i < 10; i++) {
console.log(i);
}</pre>
<p>
Important here is the <em>let</em>, because if you forget it, JavaScript won't complain, but it will create a global variable <em>i</em> for you, which is most likely not what you intended. There is also the while-loop and the do-loop.</p>
<p>
However, we have two more loops in JavaScript: the <em>for...in</em> loop and the <em>for...of</em> loop. </p>
<h3>
for...in Loop</h3>
<p>
The for...in loop is used in connection with objects, when you want to iterate through all the properties of an object.</p>
<pre style="margin-left: 40px;">
let cat = { name: "Garfield", age: 42 };
for (const property in cat) {
console.log(property + ": " + cat[property]);
}</pre>
<h3>
for...of Loop</h3>
<p>
The for...of loop is used when you want to iterate over an iterable object. Iterable objects are Arrays, Strings, TypedArrays, Maps, and Sets, for instance.</p>
<pre style="margin-left: 40px;">
let arr = [1, 2, 3, 4];
for (const element of arr) {
console.log(element);
}</pre>
<p>
JavaScript also has the <em>break</em> and <em>continue</em> statement, but if possible those should be avoided.</p>
<p>
.</p>
<h2>
Functions</h2>
<p>
As we have seen, functions are at the core of JavaScript. In JavaScript almost everything is a function. Functions can be called by events or by other functions. Functions can have parameters and they can be anonymous. There can also be functions inside functions.</p>
<p>
JavaScript distinuishes between function declaration and function expression.</p>
<h3>
Function Declaration</h3>
<p>
This is most likely the way you have declared functions before. Here the function has a name and parameters, they can also return something, and they exist on the global scope.</p>
<pre style="margin-left: 40px;">
function run() {
print("hi there");
}
<span style="color:#0000ff;">function print(msg)</span> {
console.log(msg);
}</pre>
<h3>
Function Expression</h3>
<p>
Function expressions on the other hand look like they are assigned to a variable. A function expression is only available after it has been declared, and it is not neccessarily of global scope.</p>
<pre style="margin-left: 40px;">
function run() {
<span style="color:#0000ff;">const print = function (msg)</span> {
console.log(msg);
}
print("hi there");
}</pre>
<p>
Notice the space between the keyword <em>function</em> and the parameter list <em>()</em>. This is convention.</p>
<p>
Function expressions are also called anonymous functions. To see why, first notice that in JavaScript functions can also be passed as parameters to other functions. We declare two functions, <em>createMsg()</em> and <em>print()</em>, and we pass the result of one into the other:</p>
<pre style="margin-left: 40px;">
function run() {
const print = function (msg) {
console.log( msg );
}
const createMsg = function () {
return "hi there";
}
<span style="color:#0000ff;">print(createMsg())</span>;
}</pre>
<p>
We can rewrite this with an anonymous function:</p>
<pre style="margin-left: 40px;">
function run() {
const print = function (f) {
console.log( <span style="color:#0000ff;">f()</span> );
}
print(<span style="color:#0000ff;">function () {
return "hi there";
}</span>);
}</pre>
<p>
You may notice that the <em>createMsg()</em> function has disappeared, the code became shorter, but not neccessarily easier to read.</p>
<h3>
Parameters</h3>
<p>
In other languages you may have seen something called <em>overloading</em>, where you have two functions with the same name, but different types or number of parameters. Since JavaScript is weakly typed that does not make a lot of sense, and therefore is not possible. JavaScript's solution to the problem is as simple as it is ingenious: simply define the function with the maximum number of parameters, but when calling it, you do not have to give all parameters. </p>
<pre style="margin-left: 40px;">
function run() {
print("hi there", "how are you?");
print("hi there");
}
function print(msg1, msg2) {
console.log(msg1);
console.log(msg2);
}</pre>
<p>
</p>
<p>
The first version behaves as expected, whereas in the second version, the parameter <em>msg2</em> is <em>undefined</em>. However, the code just runs fine. If you do not like things to be <em>undefined</em>, which is perfectly understandable, you can set parameters to a predefined value:</p>
<pre style="margin-left: 40px;">
function print(msg1, <span style="color:#0000ff;">msg2 = "empty"</span>) {
console.log(msg1);
console.log(msg2);
}</pre>
<p>
.</p>
<h2>
Error Handling</h2>
<p>
Because JavaScript is a weakly typed, interpreted language, it is very easy to use, but it is also very easy to make mistakes. Fortunately, it has a pretty elaborate error handling mechanism, using the try catch syntax.</p>
<h3>
try catch</h3>
<p>
For instance, assigning a variable to something that does not exist, will cause a <em>ReferenceError</em> (assuming you use "use strict"):</p>
<pre style="margin-left: 40px;">
function run() {
let x = y;
}</pre>
<p>
If you want to catch this error, you would surround it with a try catch block, The difference is: without our program will crash, whereas with it will print an error message, and continue to run:</p>
<pre style="margin-left: 40px;">
function run() {
try {
let x = y;
} catch (<span style="color:#0000ff;">error</span>) {
console.log("An error occured: " + <span style="color:#0000ff;">error</span>);
}
}</pre>
<p>
The error object contains information about what kind of error occured, and we can decide what to do next depending on the error.</p>
<p>
In JavaScript, there are many errors, such as <em>TypeError</em>, <em>RangeError</em>, <em>ReferenceError</em>, and <em>SyntaxError</em>:</p>
<pre style="margin-left: 40px;">
function run() {
// TypeError
try {
let fritz;
fritz.setColor(Color.RED);
let num = 1;
num.toUpperCase();
} catch (e) {
console.log(e);
}
// RangeError
try {
let b = new Array(-1)
} catch (e) {
console.log(e);
}
// ReferenceError
try {
let x = 3;
x = x + y;
} catch (e) {
console.log(e);
}
// SyntaxError
try {
eval("let s = 'hi");
} catch (e) {
console.log(e);
}
console.log("still running...");
}</pre>
<p>
Interesting maybe that what would be errors in other languages, are no problem for JavaScript:</p>
<pre style="margin-left: 40px;">
function run() {
try {
// ArithmeticException
let x = 5 / 0;
console.log(x); // Infinity
// NumberFormatException
let y = parseInt("five");
console.log(y); // NaN
// ArrayIndexOutOfBoundsException
let eggs = [0, 1, 2, 3];
console.log(eggs[5]); // undefined
} catch (e) {
console.log("No errors here");
}
console.log("still running...");
}</pre>
<h3>
throw</h3>
<p>
If you want to, you can also throw errors. For instance,</p>
<pre style="margin-left: 40px;">
if (!locateKarel()) {
throw Error("Could not locate Karel in the world");
}</pre>
<p>
would throw an error, which then should be caught with some try catch.</p>
<h3>
"use strict"</h3>
<p>
While we are at errors: recall that in JavaScript we are not required to declare variables. This can lead to problems:</p>
<pre style="margin-left: 40px;">
//"use strict"; // uncomment this line
function run(() {
let fritz = 5;
frits = 4;
console.log(fritz);
}</pre>
<p>
In the third line, we want to reassign a new value to the variable <em>fritz</em>. But we made a typo, and hence instead of a reassignment, we declared a new variable named <em>frits</em>. JavaScript does not care, there is no error here. To avoid these kinds of stupid mistakes, it is highly recommended that you start all of your JavaScript code with the "use strict" keyword. Adding it, will result in an error being thrown.</p>
<p>
.</p>
<h2>
DOM</h2>
<p>
JavaScript per se is independent of the Document Object Model (DOM). But as soon as we say things like</p>
<pre style="margin-left: 40px;">
document.write("Hello World");
console.log("hi there");
</pre>
<p>
we use the DOM. Both <em>document</em> and <em>console</em> are part of the browser, one being the HTML document displayed, the other the browser's console. For JavaScript they are just objects with certain properties and methods. So DOM is just an abstraction of the browser, and whenever we want to interact with the browser, we do that via the DOM.</p>
<p>
The most important objects the DOM provides are the <em>console</em>, which is mostly used for debugging, the <em>document</em>, which allows use to modify the HTML shown, and the <em>window</em> object, which gives us information about the browser window, for instance its size. As an example for what the window object might be good for consider the following code:</p>
<pre style="margin-left: 40px;">
function <span style="color:#0000ff;">main()</span> {
alert("Done loading!");
}
<span style="color:#0000ff;">window.onload = main;</span></pre>
<p>
The last line tells the browser to call the main() function, once the page has completely loaded.</p>
<p>
To see why the <em>document</em> object is useful consider the following two examples. Assume we have the following HTML document:</p>
<pre style="margin-left: 40px;">
<html>
<head>
<script type="text/javascript" src="script.js"></script>
</head>
<body onload="run();">
<span style="color:#0000ff;"><textarea id="hans">Hi there</textarea></span>
</body>
</html></pre>
<p>
where we have a text area element, which has the id named "hans". We can access this element with the <em>getElementById()</em> method:</p>
<pre style="margin-left: 40px;">
function run() {
const element = <span style="color:#0000ff;">document.getElementById("hans")</span>;
console.log(element.innerHTML);
}</pre>
<p>
We can also add, modify, and remove HTML elements. Assume we have an empty HTML document and we want to add a text area. The following code would just do that:</p>
<pre style="margin-left: 40px;">
function run() {
// create text area
let textarea = document.createElement('textarea');
textarea.id = 'hans';
textarea.value = 'Hi there';
textarea.rows = 10;
textarea.cols = 32;
textarea.readOnly = true;
// add text area to body
const _body = document.getElementsByTagName('body')[0];
_body.appendChild(textarea);
textarea.focus();
}</pre>
<p>
This should give you an impression of the power of the DOM.</p>
<p>
.</p>
<h2>
Events</h2>
<p>
Interaction with the user usually happens via events. But there are also events coming from the browser, such as the <em>onload</em> event, we have already seen. Examples of events are</p>
<ul>
<li>
loading of a web page or an image,</li>
<li>
a mouse click or a keystroke,</li>
<li>
submitting an HTML form,</li>
<li>
or a timer event.</li>
</ul>
<p>
We need to tell the browser which events we are interested in, and what to do when the event occurs. This can be done in the HTML or via JavaScript. </p>
<p>
An HTML example we have seen already:</p>
<pre style="margin-left: 40px;">
<html>
<head>
<script type="text/javascript" src="script.js"></script>
</head>
<body <span style="color:#0000ff;">onload="run()</span>;">
</body>
</html></pre>
<p>
Here we tell the browser that if the <em>onload</em> event occurs, that it should call the <em>run()</em> function. We can do the same thing with JavaScript:</p>
<pre style="margin-left: 40px;">
function run() {
document.write("Hello world!");
}
<span style="color:#0000ff;">window.onload = run;</span></pre>
<p>
If you are interested in key events, you would add an event listener:</p>
<pre style="margin-left: 40px;">
function run() {
<span style="color:#0000ff;">document.addEventListener</span>('keydown',
function (ev) {
console.log(ev.key + "," + ev.code);
}
);
}</pre>
<p>
In the same way you can add all kinds of events, such as <em>keydown</em>, <em>keypress</em>, <em>click</em>, <em>onmousedown</em>, <em>change</em> and many more.</p>
<p>
Two interesting functions are the <em>setTimeout()</em> and <em>setInterval()</em> functions: the first allows you to wait a given time before a function is being called, and the second one calls a function repeatedly.</p>
<pre style="margin-left: 40px;">
function run() {
setInterval(<span style="color:#0000ff;">sayHi</span>, 1000);
}
function sayHi() {
document.write("hi there<br/>");
}</pre>
<p>
Please, notice that inside the <em>setInterval()</em> function we are not calling "sayHi()", but instead "sayHi". This makes a big difference, try it for yourself, and make sure you understand the difference!</p>
<p>
.</p>
<h2>
eval()</h2>
<p>
Some people say eval() is evil, I personally think it is the greatest thing since sliced bread. Sure it is dangerous, especially in a web language, but which other language lets you dynamically execute arbitrary new code during run-time?</p>
<pre style="margin-left: 40px;">
function run() {
let code = prompt("Enter some JavaScript code:", "document.write('hi');");
eval(code);
}</pre>
<p>
If this does not shock you, nothing will [6].</p>
<p>
.</p>
<h2>
Classes</h2>
<p>
One of the most welcome additions to JavaScript are classes. The syntax looks quite similar to Java's, however, there are subtle differences:</p>
<pre style="margin-left: 40px;">
function run() {
const hansel = <span style="color:#0000ff;">new Student("Hänschen")</span>;
console.log(hansel.name);
console.log(hansel.toString());
}
class Student {
<span style="color:#0000ff;">constructor(nm)</span> {
this.name = nm;
}
toString() {
return "Student [name=" + this.name + "]";
}
}</pre>
<p>
</p>
<p>
You will immediately notice that the constructor is actually called <em>constructor</em>. Creation of objects using the <em>new</em> keyword also may look familiar. </p>
<p>
Interesting should be the line</p>
<pre style="margin-left: 40px;">
this.name = nm;</pre>
<p>
which seems to indicate that there is an instance variable called <em>name</em>, but if we look, we do not find a declaration. In fact, there is none, this is just JavaScripts way of defining instance variables, very efficient I would say.</p>
<p>
Another interesting thing, there is no overloading in JavaScript, neither for the constructor nor for methods, we talked about this when we were talking about functions before. </p>
<h3>
Closures</h3>
<p>
Let's return to the instance variables. All instance variables defined above are public, meaning anybody can see and modify them. This violates the principle of information hiding. But not all is lost, because we have <em>closures</em> in JavaScript. Assume our Student class should also have a read-only, private property <em>id</em>. This is how we would implement this in JavaScript:</p>
<pre style="margin-left: 40px;">
class Student {
constructor(name, id = -1) {
this.name = name;
<span style="color:#0000ff;"> // closure: read only
this.getId = (function () {
let _id = id;
return function () {
return _id
}
})();</span>
}
toString() {
return "Student [name=" + this.name + ", id=" + <span style="color:#0000ff;">this.getId()</span> + "]";
}
}</pre>
<p>
While we are at it, we can also use closures to implement an increment-only method:</p>
<pre style="margin-left: 40px;">
class Student {
constructor(name, id = -1) {
this.name = name;
...
// closure: increment only
this.incrementCredits = (function (x) {
let _credits = 0;
return function (x) {
if (x !== undefined && x > 0) {
_credits += x;
}
return _credits
}
})();
}
toString() {
return "Student [name=" + this.name + ", id=" + this.getId()
+ ", credits=" + this.incrementCredits() + "]";
}
}</pre>
<p>
If we call <em>incrementCredits()</em> without arguments, it just returns the current value of credits, if we call it with an argument, it will increment the credits by that amount.</p>
<h3>
Inheritance</h3>
<p>
We use the keyword <em>extends</em> to inherit from a parent class:</p>
<pre style="margin-left: 40px;">
class Freshman extends Student {
constructor(name, id = -1) {
super(name, id);
}
toString() {
return "Freshman [name=" + this.name + ", id=" + this.getId()
+ ", credits=" + this.incrementCredits() + "]";
}
}</pre>
<p>
If you know Java this may look familiar to you. As you can see we can override methods if we desire, but we don't have to. And there is the <em>super</em> keyword to call the parent's class constructor or methods of the parent class.</p>
<h3>
Inheritance Chain</h3>
<p>
How about methods of the grandparent class, can we call those as well? JavaScript has a method named <em>getPrototypeOf()</em> that allows you to get a handle to the respective parent, kind of neat:</p>
<pre style="margin-left: 40px;">
function run() {
const hansel = new Freshman("Hänschen", 12345);
let me = Object.getPrototypeOf(hansel);
console.log(me.constructor.name); // Freshman
let parent = Object.getPrototypeOf(me);
console.log(parent.constructor.name); // Student
let grandParent = Object.getPrototypeOf(parent);
console.log(grandParent.constructor.name); // Object
parent.test();
}</pre>
<p>
.</p>
<h2>
Polymorphism</h2>
<p>
If you lookup the meaning of polymorph, it says something like "an object or material which takes various forms". We stay with our Student and Freshman classes. If we have two students, <em>hansel</em> and <em>gretel</em>, <em>hansel</em> being a Freshman and <em>gretel</em> being a Student, then actually both of them are Students:</p>
<pre style="margin-left: 40px;">
function run() {
const hansel = new Freshman("Hänschen");
polymorphic(hansel);
const gretel = new Student("Gretchen");
polymorphic(gretel);
polymorphic("hi there");
}
function polymorphic(studnt) {
console.log(studnt.toString());
}</pre>
<p>
Now in our <em>polymorphic()</em> method, we assume that the parameters passed in are Students, and therefore have the <em>toString()</em> method.</p>
<p>
So using polymorphism in JavaScript is straight forward, the problem is enforcing it: because JavaScript is weakly typed, we can pass actually anything we want. However, again not all is lost, because we can enforce proper datatypes using the <em>instanceof</em> operator:</p>
<pre style="margin-left: 40px;">
function polymorphic(studnt) {
if (studnt <span style="color:#0000ff;">instanceof</span> Student) {
console.log(studnt.toString());
} else {
throw Error("Parameter is not of type Student!");
}
}</pre>
<p>
.</p>
<h2>
Static Methods</h2>
<p>
JavaScript also has <em>static</em> methods, an example is the Random class:</p>
<pre style="margin-left: 40px;">
class Random {
static nextInt(low, high) {
if (high !== undefined) {
return parseInt(low + Math.random() * (high - low));
} else {
return this.nextInt(0, low);
}
}
static nextDouble(low, high) {
if (high !== undefined) {
return low + Math.random() * (high - low);
} else {
return this.nextDouble(0, low);
}
}
}</pre>
<p>
We call these methods directly, i.e., no object needs to be instantiated:</p>
<pre style="margin-left: 40px;">
function run() {
console.log( Random.nextInt(2,7) );
}</pre>
<p>
Another example inspired from Java is <em>System.currentTimeMillis()</em>:</p>
<pre style="margin-left: 40px;">
class System {
static currentTimeMillis() {
return new Date().getTime();
}
}
// const time = System.currentTimeMillis();</pre>
<p>
Don't use static to often, it does more harm than good.</p>
<p>
.</p>
<h2>
Enums and Constants</h2>
<p>
A neat trick on how to create "constants" or something resembling enums is in the following way:</p>
<pre style="margin-left: 40px;">
class Color {
}
Color.RED = 'red';
Color.GREEN = 'green';
Color.BLUE = 'blue';
Color.WHITE = 'white';
Color.BLACK = 'black';
</pre>
<p>
Although neat, be careful, they are not constants!</p>
<p>
.</p>
<h2>
Namespaces</h2>
<p>
Another thing kind of missing in JavaScript are <em>namespaces</em>. But as usual there is a trick. We define an empty object called <em>Utils</em> as a global variable, and then attach our class to it as property:</p>
<pre style="margin-left: 40px;">
<span style="color:#0000ff;">var Utils = {}</span>
<span style="color:#0000ff;">Utils.Random</span> = class {
static nextInt(low, high) {
if (high !== undefined) {
return parseInt(low + Math.random() * (high - low));
} else {
return this.nextInt(0, low);
}
}
}</pre>
<p>
When using it, it looks exactly like a namespace or package would:</p>
<pre style="margin-left: 40px;">
function run() {
console.log( <span style="color:#0000ff;">Utils.Random</span>.nextInt(2,7) );
}</pre>
<p>
But naturally, it is not.</p>
<p>
.</p>
<h2>
Promise</h2>
<p>
Whenever you have to wait for something, most likely you will need a promise. Let's look at two simple examples.</p>
<p>
Assume you want something to happen once per second, that is you want a <em>pause()</em> method. Then the following is an implementation using a Promise:</p>
<pre style="margin-left: 40px;">
const pause = function (milliseconds = 500) {
return new Promise(
function (resolve) {
return setTimeout(resolve, milliseconds);
})
};</pre>
<p>
You would call this method in the following way:</p>
<pre style="margin-left: 40px;">
<span style="color:#0000ff;">async</span> function run() {
let i = 0;
while (true) {
console.log("waiting one second: " + i++);
<span style="color:#0000ff;">await</span> pause(1000);
}
}</pre>
<p>