-
Notifications
You must be signed in to change notification settings - Fork 0
/
Udemy_The_Complete_JavaScript_Course_2021.js
6821 lines (5071 loc) · 233 KB
/
Udemy_The_Complete_JavaScript_Course_2021.js
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
let jsCourse = {
courseName : "The Complete JavaScript Course 2021: From Zero to Expert",
author : "Jonas Schmedttman",
url : "https://www.udemy.com/course/the-complete-javascript-course/"
}
//#region Section 1-8 JS Basics
//#region Part 1
//#region Data Types
let name = 'Nury';
// important: name is a reversed keywoard in JS but can be used. Never use it.
// Constants should be written all uppercase
const PI = 3.14;
/*
Primitive Data Types in JS:
1- Number
2- String
3- Boolean
4- Undefined
5- Null
6- Symbol
7- BigInt
*/
// 1. Number: Floating point number. Used for decimals and integers.
let myNum = 23; // actually its 23.0 even if we dont see it
// important: In other programming languages there are different data types for integers and decimals
// but in javascript there are all same.
// 2. String: Sequence of characters
let myName = 'Nury';
// 3. Boolean: Logical type that can only be true or false
let isCompleted = true;
// 4. Undefined: Value taken by a variable that is not yet defined. ('empty value')
let children;
// 5. Null: Empty value. Similar to undefined.
// 6. Symbol: Introduced in ES2015. Value that is unique and cannot be changed.
// 7. BigInt: Came with ES2020. Larger Integers than the Number can hold.
// important: Javascript has a feature called dynamic typing.
// We dont have to manually define the data type of variable in javascript.
// Instead data types are determined automatically.
let age = 10; // age will automatically be defined as Number
// One another feature of javascript is a variable data type can later be changed to another data type.
let num = 0;
console.log(typeof num); // Number
let num = '0';
console.log(typeof num); // String
let year = 2021;
console.log(typeof year); // Number
let year;
console.log(year); // undefined
console.log(typeof year); // undefined
console.log(typeof null); // object
// important: This is a bug in javascript and it has never corrected for legacy reasons.
// This should be undefined. Be carefull about this bug.
let age = 30;
age = 31; // This is called mutating a varibale in javascript world. Reassigning.
const PI = 3.14; // Constant variables can not be changed later. Immutable.
// We cannot define an empty const variable.
const PI; // This is not legal. Initial value has to be given.
// "let" is block scoped however "var" is function scoped.
let numOne = 2;
let numTwo = 3;
console.log(numOne, numTwo);
console.log(numOne ** numTwo); // Prints out: 8
let ageSara = 22;
let isFullAge = ageSara >= 18;
// Template literals (Came with ES6)
let myName = 'Nury';
let birthYear = 1989;
let me = `Hello, I'm ${myName} and I'm ${new Date().getFullYear() - birthYear} years old.`;
console.log('This is first line \n\
This is second line');
// important: This is a bug in javascript.
console.log(`This is first line
This is second line`);
// This is a proper way of doing it. This syntax is commonly used in creating dynamic HTML tags.
/*
In javaScript, there is type conversion and type coercion. So they sound very similar, but are different.
Type conversion is when we manually convert from one type to another.
On the other hand type coercion is when javascript automatically converts types behind the scenes for us.
So that's necessary in some situation, but it happens implicitly, completely hidden from us.
*/
const inputYear = '1991';
inputYear = Number(inputYear); // This is type conversion.
console.log(Number('Hello')); // NaN
// "NaN" stands for "not a number". So a javascript gives us this, not a number value
// whenever an operation that involves numbers fails to produce a new number.
console.log(typeof NaN); // Number
// important: typeof NaN is Number
// And so again, not a number actually means an invalid number.
// It's still a number of somehow, but it's an invalid one.
console.log(String(23)); // '23'
console.log(String(23), 23); // 23 23 colors will be different
console.log('I am ' + 23 + ' years old.'); // I am 23 years old.
// And it works this way because of type of coercion.
// important: So in javascript, the plus operator that we used here triggers a coercion to strings.
// And so whenever there is an operation between a string and the number,
// the number will be converted to a string.
console.log('23' - '10' - 3); // 10
// And so what this means is that the minus operator actually triggers the opposite conversion.
// So in this case, strings are converted to numbers and not the other way around.
// So instead if we use the plus, what do you think is going to happen?
console.log('23' + '10' + 3); // 23103
// important: all three are converted to a string and then the three strings are concatenated.
// So this is a very important distinction to keep in mind because this is actually confusing.
console.log('3' * '2'); // 8
console.log('4' / '2'); // 2
console.log('4' > '2'); // true
let n = '1' + 1;
n = n - 1;
console.log(n); // 10
console.log(2 + 3 + 4 + '5'); // 95
console.log('10' - '4' - '3' - '2' + '5'); // 15
//#endregion
//#region Truthy and Falsy Values
/*
Falsy values in Javascript
important: 5 falsy values in javascript are: 0, '', undefined, null, NaN
All of these five values will be converted to false when we attempt to convert them to a boolean.
Of course, false itself is already false, so we don't need to include it in the list of falsy values.
They're not exactly false initially, but they will become when converted to a boolean.
So, that's the definition of falsy values.
Everything else are so-called truthy values, values that will be converted to true.
For example, any number that is not zero or any string that is not an empty string
will be converted to true when we attempt to convert them to a boolean.
*/
console.log(Boolean(0)); // false
console.log(Boolean(undefined)); // false
console.log(Boolean('Javscript')); // true
console.log(Boolean({})); // true
console.log(Boolean(1)); // true
const money = 0;
if (money) {
console.log("Dont spend it all.")
}
else{
console.log("You should earn some money.") // this will be executed
}
let height;
if (height) {
console.log("Yay. Height is defined")
}
else{
console.log("Height is undefined") // this will be executed
}
let age = 18;
if (age === 18) {
console.log("You are an adult.") // Strict equality operator
}
// important: Difference between double and triple equal is that
// the three equals is called the "strict equality" operator.
// It's strict, because it does not perform type coercion.
// And so it only returns to when both values are exactly the same.
// On the other hand, there's also the loose equality operator, which is only two equals,
// and the loose equality operator actually does type coercion.
console.log('18' == 18); // true
console.log('18' === 18); // false
// important: so as a general rule for clean code, avoid the loose equality operator as much as you can.
// when comparing values, always use strict equality with the three equal signs.
// The Conditional (Ternary) Operator
const age = 23;
age >= 18 ? console.log("You are an adult.") : console.log("You are not an adult.");
let canDrive = age >= 18 ? "Yes" : "No";
//#endregion
//#endregion
//#region Part 2
//#region Using Strict Mode
/*
Strict mode statement has to be the very first statement in the script.
So if we have any code before this then strict mode will not be activated.
We can also activate strict mode, only for a specific function or a specific block.
But there is no point in doing that and so always use it at the beginning of each script.
So always just put strict mode in the beginning of your scripts and like that write more secure code.
And when secure, I mean that strict mode makes it easier for us developers to avoid accidental errors.
So basically it helps us introduce the bugs into our code and that's because of 2 reasons.
First, strict mode forbids us to do certain things and second,
it will actually create visible errors for us in certain situations in which without strict mode
JavaScript will simply fail silently without letting us know that we did a mistake.
*/
'use strict';
let isActive = false;
isActiv = true; // fails silently
const interface = "Audio"; // failse because interface is a reserved keyword
const private;
//#endregion
//#region Functions
function logger(str) {
console.log(str);
}
// important: calling parameterless function with a parameter has no negative affect
function fruitProcessor(apples, oranges) {
console.log(apples,oranges);
const juice = `Juice with ${apples} apples and ${oranges} oranges`;
return juice;
}
logger(fruitProcessor(2,3));
// Function declaration
function calcAge(birthYear) {
return 2021 - birthYear;
}
const age = calcAge(1989);
// Function expression
// Anonymous function
const calculateAge = function(birthYear) {
return 2021 - birthYear;
}
calculateAge(1989);
// important: In JavaScript, functions are actually just values. So just as a number or a string or a boolean value.
// Function is not a type, okay? It's not like a string or number type but it's also a value.
/*
Now, besides these technical differences, you might be wondering what is the big deal?
So what's the big difference between "function declarations" and "function expressions"?
Well, the main practical difference is that we can actually call "function declarations"
before they are defined in the code.
So we learned about "function declarations" and "function expressions" but there is actually
a third type of function that was added to JavaScript in ES6 and that's the "arrow function".
An arrow function is simply a special form of function expression that is shorter and faster to write.
*/
const calcAge = birthYear => 2021 - birthYear;
// no return keyword no brackets just simple clean code
const yearsLeftUntilRetirement = birthYear => {
const age = 2021 - birthYear;
const yearsLeft = 65 - age;
return yearsLeft;
}
const getSum = (num1 , num2) => num1 + num2;
const yearsLeftUntilRetirement = (name, birthYear) => {
const age = 2021 - birthYear;
const yearsLeft = 65 - age;
return `${name} retires in ${yearsLeft} years`;;
}
logger(yearsLeftUntilRetirement("Bob", 1980));
// important: There is another fundamental difference between the
// "arrow function" and more "traditional functions".
// It's the fact that arrow functions do not get a so-called this keyword.
// VS Code Tip: Select a word in vs code and Ctrl + D will select all instances of that word
//#endregion
//#region Arrays
const cities = ["London", "Paris", "Rome"];
const years = new Array(1991,1995,2001);
// important: Only primitive types are immutable if thay are declared as const, arrays are not
const cities = ["London", "Paris", "Rome"];
cities[2] = "Berlin";
cities = ["Berlin", "Toronto"]; // important: This is illegal. Entire array can not be changed
const nums = [1,2,3];
nums + 5; // important: This is legal. Concatentaion as string. Produces "1,2,35" output
nums - 5; // NaN
// Adding elements to an array
const cities = ["London", "Paris", "Rome"];
const arrLength = cities.push("Madrid") // Adds element to the last index. Returns new array length.
// cities array becomes: ["London", "Paris", "Rome", "Madrid"]
arrLength = cities.unshift("Barcelona") // Adds element to the first index. Returns new array length.
// cities array becomes: ["Barcelona", "London", "Paris", "Rome", "Madrid"]
// Removing elements from an array
const poppedCity = cities.pop("Madrid") // Removes element from the last index. Returns popped element "Madrid"
// cities array becomes: ["Barcelona", "London", "Paris", "Rome"]
const shiftedCity = cities.shift("Barcelona") // Removes element from the first index. Returns removed element "Barcelona"
// cities array becomes: ["London", "Paris", "Rome"]
let cities = ["London", "Paris", "Rome"];
console.log(cities.indexOf("Paris")); // Returns 1. element index
console.log(cities.indexOf("Berlin")); // Returns -1. element does not exist
console.log(cities.includes("Paris")); // Returns true
console.log(cities.includes("Berlin")); // Returns false
//#endregion
//#region Objects
// Array seeming like an object
const mesutArray = [
"Mesut", // FirstName
"Ozil", // LastName
1987, // BirthYear
"Player", // Job
["Crisitiano Ronaldo","Sergio Ramos","Karim Benzema"] //Friends
]
// For array you cannot call value by property like mesutArray(LastName) or mesutArray.
// Values can only be reached with index pointers like mesutArray[1]
// In order to solve this problem objects are created.
// important: Objects are simple key value pairs.
const mesut = {
firstName: "Mesut",
lastName: "Ozil",
birthYear: 1987,
job: "Player",
friends: ["Crisitiano Ronaldo","Sergio Ramos","Karim Benzema"]
};
// This is called object literal syntax
console.log(mesut.firstName); // This is called dot notation
console.log(mesut['lastName']); // This is called bracket notation
// important: For bracket notation, we can actually put any expression that returns value.
let n = "Name";
console.log(mesut['last' + n]); // This still works. But console.log(mesut.'last' + n) does not.
let interestedIn = prompt("What do you want to know about mesut? Choose firstName, lastName or job")
console.log(mesut[interestedIn]) // Works for interestedIn = "firstName"
console.log(mesut[interestedIn]) // Does not work for interestedIn = "location". Undefined
// Undefined is a falsy value so that we can use it inside an if statement
if (mesut[interestedIn]) {
console.log(mesut[interestedIn]);
}
else {
console.log("Not what we expected");
}
const mesut = {
firstName: "Mesut",
lastName: "Ozil",
birthYear: 1987,
job: "Player",
friends: ["Crisitiano Ronaldo","Sergio Ramos","Karim Benzema"],
hasLicense: true,
getAge: function(birthYear) {
return 2021 - birthYear;
}
};
console.log(mesut.getAge(1987)) // Works
console.log(mesut['getAge'](1987)) // Works
// this keyword
const mesut = {
firstName: "Mesut",
lastName: "Ozil",
birthYear: 1987,
job: "Player",
friends: ["Crisitiano Ronaldo","Sergio Ramos","Karim Benzema"],
hasLicense: true,
getAge: function() { // No parameter
return 2021 - this.birthYear;
}
};
console.log(mesut.getAge()) // important: We dont need to pass an argument this way
const myObj = {
objName: "Book",
price: 10,
getInfo:function() {
console.log(this); // logs {objName: "Book", Price: 10, getInfo: ƒ }
}
};
const myObj = {
objName: "Book",
price: 10,
getInfo:function() {
this.info = "Book price is " + this.price + " USD.";
return this.info;
}
};
myObj.getInfo()
"Book price is 10 USD."
// important: myObj.info property is created only if this method is called.
myObj.info
"Book price is 10 USD."
// important: Can only be called after myObj.getInfo() method is called
//#endregion
//#region For loops
// array
const mesut = [
"Mesut",
"Ozil",
1987,
"Player",
["Crisitiano Ronaldo","Sergio Ramos","Karim Benzema"]
];
const types = [];
for (let index = 0; index < mesut.length; index++) {
types[i] = typeof mesut[index];
}
// Alternative approach
for (let index = 0; index < mesut.length; index++) {
types.push(typeof mesut[index]);
}
//#endregion
//#region Some Notes
// www.codewars.com for coding challenges
/*
\r (Carriage Return) → moves the cursor to the beginning of the line without advancing to the next line
\n (Line Feed) → moves the cursor down to the next line without returning to the beginning of the line
\r\n (End Of Line) → a combination of \r and \n
*/
//#endregion
//#region DOM and Javascript
// Web APIs
/*
<section>
<p class="message">Hello</p>
</section>
*/
var txt = document.querySelector('.message').textContent;
document.querySelector('.message').textContent = "Hi";
// <input class="guess" type="text"></input>
var value = document.querySelector('.guess').value;
document.querySelector('.guess').value = "23";
// important: "value" property is used for input fields
// EventListeners
// <button class="btn">Click Me</button>
var myButton = document.querySelector('.btn');
myButton.addEventListener(arg1,arg2);
// There are multiple ways for listening events in javascript. addEventListener is the most used one.
// arg1: Type of the event is passed to addEventListener method
// arg2: Event handler function that will be called when an event happens
document.querySelector('.btn').addEventListener('click', function () {
console.log("Hello, click event is triggered.")
})
// click is the event that is listened
// function () { console.log("Hello, click event is triggered.")} is the event handler
// domElement.addEventListener(event,eventHandlerFunction);
// Generating random number between 0-20
const randNum = Math.trunc(Math.random() * 20) + 1;
let score = 20; // this is a state variable
// This score is so called application state
// property names change in js, in css background-color but in javascript backgroundColor
// same rule applies to all other properties that has multiple words
document.querySelector('body').style.backgroundColor = 'green';
// important: every css property has to be set with string in javascript
document.querySelector('number').style.width = 20; // illegal
document.querySelector('number').style.width = '20px'; // legal
// important: javascript applies styles as an inline style. It does not simply change css file
/*
<button class="show-modal">Show Modal 1</button>
<button class="show-modal">Show Modal 2</button>
<button class="show-modal">Show Modal 3</button>
*/
// querySelector will return only the first modal element
var modals = document.querySelector('show-modal');
// querySelectorAll will return all of the modal elements
var modals = document.querySelectorAll('show-modal');
// important: querySelectorAll method returns nodeList
// https://www.reddit.com/r/learnjavascript/
// https://javascript30.com/
/*
<div class="modal hidden">
<button class="close-modal">Close</button>
<h1>Title</h1>
<p>Lorem ipsum</p>
</div>
*/
var modal = document.querySelector('.modal');
modal.classList.remove('hidden'); // removes "hidden" class from modal
// important: classList is a property to manage classes
// important: We can remove multiple classes with remove method of classList property
modal.classList.remove('hidden','modal');
// document.querySelector('.modal') has to be used with dot before class name
// For classList.remove method we dont need to use dot prefix before class name
// Adding a class
modal.classList.add('newClass');
/*
CSS style of a hidden class
.hidden {
display:none;
}
*/
// Same thing with alternative approach but not the best way
modal.style.display = 'block';
// Same modal can also be closed by clicking overlay element (outside the modal)
const closeModal = overlay.addEventListener('click', function() {
modal.classList.add('hidden');
});
// Alternative approach
const close = function() {
modal.classList.add('hidden');
}
const closeModal = overlay.addEventListener('click', close);
const closeModal = overlay.addEventListener('click', close()); // important: This will not work. Dont call it just point it
// Because () syntax will immediately call the function as soon as javascript executes this line when page rendering
/*
Keyboard events are called global events because they do not happen when a specific element triggered.
We use document object to listen for a keypress events. So we are listening everywhere for an event to be triggered.
There are 3 types of keypress events:
1. keyDown : is fired as soon as the key is pressed.
2. keyPress : is fired continuosly when we hold our finger pressed on a key.
3. keyUp : is fired when a pressed key is released (when we lift finger of the keyboard)
*/
// The following code will work for any pressed key
document.addEventListener('keydown', function() {
modal.classList.add('hidden');
})
/*
The information about which key was pressed will be stored in the event that is going to occur as soon as any key is pressed.
So again, when an event happened we can have access to information about that event in the event handler function.
To acces all information about the event we simply give an argument to an event handler function like below
document.addEventListener('keydown', function(event) {
modal.classList.add('hidden');
})
*/
// important: "e" is the most popular argument passed
document.addEventListener('keydown', function(e) {
console.log(e);
})
/*
Output object will be like below if we press Esc key:
KeyboardEvent {isTrusted: true, key: "Escape", code: "Escape", location: 0, ctrlKey: false, …}
altKey: false
bubbles: true
cancelBubble: false
cancelable: true
charCode: 0
code: "Escape"
composed: true
ctrlKey: false
currentTarget: null
defaultPrevented: false
detail: 0
eventPhase: 0
isComposing: false
isTrusted: true
key: "Escape"
keyCode: 27
location: 0
metaKey: false
path: (4) [body.js-focus-visible, html, document, Window]
repeat: false
returnValue: true
shiftKey: false
sourceCapabilities: InputDeviceCapabilities {firesTouchEvents: false}
srcElement: body.js-focus-visible
target: body.js-focus-visible
timeStamp: 60132.4799999129
type: "keydown"
view: Window {window: Window, self: Window, document: document, name: "", location: Location, …}
which: 27
__proto__: KeyboardEvent
*/
// If escape button is clicked
document.addEventListener('keydown', function(e) {
if(e.key === 'Escape')
modal.classList.add('hidden');
})
const score = document.querySelector('#score');
const score = document.getElementById('score'); // important: no need for # prefix
// selecting by name
const input = document.querySelector('input[name="pwd"]');
let initialScore = 0;
document.querySelector('#score').textContent = initialScore; // JS automatically converts 0 to "0"
// toggle will add the class if it is not there and if it is there, it will remove it.
const player1 = document.querySelector('#player1');
const player2 = document.querySelector('#player2');
player1.classList.toggle('active');
player2.classList.toggle('active');
//#endregion
//#endregion
//#region Part 3
//#region Diving deeper
/*
JavaScript is a high-level, prototype-based, object-oriented, multi-paradigm, interpreted or just-in-time compiled, dynamic,
single-threaded, garbage-collected programming language with first-class functions and a non-blocking event loop concurrency model.
- High-level: we do not have to manage resources at all (js have so-called abstractions that take all of that work away from us)
- Garbage-collected: is basically an algorithm inside JS engine, which automatically removes old, unused objects from the computer memory.
- Interpreted or JIT compiled:
- Multi-paradigm: can be coded using functional, procedural or another paradigm
- Prototype-based object-oriented: almost everything in JavaScript is an object, except for primitive values such as numbers, strings etc.
- First-class functions: functions are treated just as regular variables and this allows for functional-programming.
- Dynamic: variables are dynamically typed.
- Single threaded:
- Non-blocking event loop: JS engine handles multiple tasks happening at the same time.
In programming, a paradigm is an approach and an overall mindset of structuring our code,
which will ultimately direct the coding style and technique in a project that uses a certain paradigm.
Three popular paradigms are:
1. Procedural
2. Object-oriented
3. Functional programming
"Procedural programming" is basically just organizing the code in a very linear way with some functions in between.
Most classical or traditional approach used by many developers.
"Functional programming" is a paradigm in which functions are treated just as regular variables.
So, we can pass functions into other functions and we can even return functions from functions.
And this is extremely powerful because it allows us to use a lot of powerful techniques.
Now, many languages are only procedural or only object-oriented or only functional but JavaScript does all of it.
So it's really flexible and versatile.
Concurrency model: JS engine handles multiple tasks happening at the same time.
JavaScript itself runs in one single-thread, which means that it can only do one thing at a time
and therefore we need a way of handling multiple things happening at the same time.
Global execution context: code that is not inside a function. Top level code.
Now, in any JavaScript project, no matter how large it is, there is only ever one global execution context.
It's always there as the default context, and it's where top-level code will execute.
So the top-level of code is finished, functions finally start to execute as well. And here is how that works.
For each and every function call execution context will be created containing all the information that is
necessary to run exactly that function. And the same goes for methods, of course, because they are simply
functions attached to objects remember? Anyway, all these execution contexts together,
make up the call stack that I mentioned before.
Now, when all functions are done executing, the engine will basically keep waiting for callback functions to
arrive so that it can execute these. For example, a callback function associated with a click event.
So we know now what an execution context is, but don't really know what it's made of.
So, what's inside of it?
The first thing that's inside any execution context is a so-called variable environment.
In this environment, all our variables and function declarations are stored,
and there is also a special arguments object. This object contains, as the name says all the arguments
that were passed into the function that the current execution context belongs to.
Now the program will now actually stay in this state for forever until it is eventually really finished.
And that only happens like when we close the browser tab, or the browser window.
Only when the program is really finished like this, is when the global execution context is also popped off the stack.
And this is in a nutshell how the call stack works.
So hopefully it makes sense now that we say that Java script code runs inside the call stack.
And actually it is more accurate to say that code runs inside of execution contexts that are in the stack.
Scopes in Javascipt
There are three different types of scope in JavaScript:
1. Global Scope
2. Function Scope
3. Block Scope
*/
//#endregion
//#region 1. Global Scope
const age = 33;
const name = 'Mesut';
function first() {
let a = 0;
console.log("first function is called");
}
function second() {
let b = 0;
console.log("second function is called");
}
// Variables "age" and "name" are global variables in the above code.
// So the global scope is once more for top level code.
// So this is for variables that are declared outside of any function or block.
// These variables will be accessible everywhere in our program, in all functions and all blocks.
//#endregion
//#region 2. Function Scope
function sayHi() {
var a = 0;
let str = 'Hi';
console.log("Hi there.");
}
// Variables "a" and "str" are local variables in the above code.
// Each and every function creates a scope in javascript.
// And the variables declared inside that function scope are only accessible inside that function.
// This is also called a local scope opposed to the global scope. So local variables live in the function so to say.
// And outside of the function, the variables are not accessible at all.
//#endregion
//#region 3. Block Scope
// Traditionally, only functions used to create scopes in JavaScript. But starting in ES6, blocks also creates scopes now.
// And with blocks, we mean everything that is between curly braces, such as the block of an if statement or a for loop.
// So just like with functions, variables declared inside a block are only accessible inside that block and not outside of it.
if (you == 'cool') {
const me = 'cool'; // block scoped
let we = 'awesome'; // block scoped
var they = 'fine'; // global scoped
}
// important: the big difference is that block scopes only apply to variables declared with "let" or "const".
// So again, only "let" and "const" variables are restricted to the block in which they were created.
// That's why we say that "let" and "const" variables are block scoped.
// So if I declared a variable using "var" in this block, then that variable would actually still be accessible outside of the block.
// And would be scoped to the current function or to the global scope.
// So in ES5 and before, we only had global scope and function scope.
// And that's why ES5 variables declared with "var", only care about functions, but not about blocks.
// Finally, also starting in ES6, all functions are now also block scoped, at least in strict mode, which you should always be using anyway.
//#endregion
//#region The Scope Chain
const myName = 'Mesut';
function first() {
const age = 33;
if (age >= 33) {
const decade = 3;
var millenial = true;
}
function second() {
const job = 'player';
console.log(`${myName} is a ${age} years old and he is a ${job}`);
}
second();
}
first();
// Mesut is a 33 years old and he is a player
// Global Scope: myName
// First Scope: age, millenial (but can access myName)
// Second Scope: job (but can access age, millenial, myName)
// Block Scope: decade, (but can access age, millenial, myName)
// Every scope always has access to all the variables from all its outer scopes.
// So from all its parent scopes. And by the way, all this also applies to function arguments.
// In other words, if one scope needs to use a certain variable, but cannot find it in the current scope,
// it will look up in the scope chain and see if it can find a variable in one of the parent scopes.
// And this process is called variable lookup.
// A certain scope will never, ever have access to the variables of an inner scope.
// important: "var" is function scoped, "let" and "const" are block scoped.
//#endregion
//#region Scope Chain vs Call Stack
// There is one more thing that we need to talk about, which is the difference between the scope chain and the call stack.
const a = 'Mesut';
first();
function first() {
const b = 'Hello!';
second();
function second() {
const c = 'Hi!';
third();
}
}
function third() {
const d = 'Hey!';
console.log(d + c + b + a); // ReferenceError. Cant access c and b.
}
// The scope chain is all about the order in which functions are written in the code.
// But what's really important to note here is that the scope chain has nothing to do with the order in which functions were called.
// Or in other words, the scope chain has nothing to do with the order of the execution contexts in the call stack.