💯 Score: 20
277 |278 | 🥇 Highscore: 0 279 |
280 |├── 05. HTML & CSS Crash Course.md ├── README.md ├── _The Complete JavaScript - Jonas Schmedtmann.md ├── 04. Developer Skills & Editor Setup.md ├── 09. A Closer Look at Functions.md ├── 12. Advanced DOM and Events.md ├── 01. JavaScript Fundamentals Part 1.md ├── 07. How JavaScript Works Behind the Scenes.md ├── 02. JavaScript Fundamentals Part 2.md ├── 11. Numbers, Dates, Intl and Timers.md ├── 13. Object-Oriented Programming (OOP) .md ├── 13. Object-Oriented Programming (O0P) With JavaScript.md └── 06. DOM and Events Fundamentals.md /05. HTML & CSS Crash Course.md: -------------------------------------------------------------------------------- 1 | # 5. HTML & CSS Crash Course 2 | --- 3 | 4 | ## Basic HTML Structure and Elements and Attributes, Classes and IDs 5 | ```html 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 |19 | You can learn JavaScript without HTML and CSS, but for DOM manipulation 20 | it's useful to have some basic ideas of HTML & CSS. You can learn more 21 | about it 22 | on Udemy. 23 |
24 | 25 |27 | Just another paragraph 28 |
29 | 30 |
34 |
35 |
42 |
43 |
44 | ```
45 |
46 | ## Basic Styling with CSS & Introduction to the CSS Box Model
47 |
48 | ```css
49 | * {
50 | margin: 0;
51 | padding: 0;
52 | box-sizing: border-box;
53 | }
54 |
55 | body {
56 | background-color: rgb(255, 247, 201);
57 | font-family: Arial;
58 | font-size: 20px;
59 | padding: 50px;
60 | }
61 |
62 | h1 {
63 | font-size: 35px;
64 | margin-bottom: 25px;
65 | }
66 |
67 | h2 {
68 | margin-bottom: 20px;
69 | text-align: center;
70 | }
71 |
72 | p {
73 | margin-bottom: 20px;
74 | }
75 |
76 | .first {
77 | color: red;
78 | }
79 |
80 | ##your-name {
81 | background-color: rgb(255, 220, 105);
82 | border: 5px solid ##444;
83 | width: 400px;
84 | padding: 25px;
85 | margin-top: 30px;
86 | }
87 |
88 | input,
89 | button {
90 | padding: 10px;
91 | font-size: 16px;
92 | }
93 |
94 | a {
95 | background-color: yellowgreen;
96 | }
97 |
98 | ##course-image {
99 | width: 300px;
100 | }
101 |
102 | ##your-name h2 {
103 | color: olivedrab;
104 | }
105 | ```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # The Complete Javascript Notes
2 |
3 | ### 🌟 What you'll learn
4 |
5 | - JavaScript fundamentals: variables, if/else, operators, boolean logic, functions, arrays, objects, loops, strings, etc.
6 | - Modern ES6+ from the beginning: arrow functions, destructuring, spread operator, optional chaining (ES2020), etc.
7 | - Modern OOP: Classes, constructors, prototypal inheritance, encapsulation, etc.
8 | - Complex concepts like the 'this' keyword, higher-order functions, closures, etc.
9 | - Asynchronous JavaScript: Event loop, promises, async/await, AJAX calls and APIs
10 | - How to architect your code using flowcharts and common patterns
11 | - Modern tools for 2024 and beyond: NPM, Parcel, Babel and ES6 modules!
12 |
13 | #### 📚 Topics Covered
14 |
15 | 01. [JavaScript Fundamentals Part 1](https://github.com/xoraus/Javascript-Notes/blob/main/01.%20JavaScript%20Fundamentals%20Part%201.md)
16 | 02. [JavaScript Fundamentals Part 2](https://github.com/xoraus/Javascript-Notes/blob/main/02.%20JavaScript%20Fundamentals%20Part%202.md)
17 | 03. How to Navigate This Course
18 | 04. [Developer Skills & Editor Setup](https://github.com/xoraus/Javascript-Notes/blob/main/04.%20Developer%20Skills%20%26%20Editor%20Setup.md)
19 | 05. [OPTIONAL: HTML & CSS Crash Course](https://github.com/xoraus/Javascript-Notes/blob/main/05.%20HTML%20%26%20CSS%20Crash%20Course.md)
20 | 06. [JavaScript in the Browser: DOM and Events Fundamentals](https://github.com/xoraus/Javascript-Notes/blob/main/06.%20DOM%20and%20Events%20Fundamentals.md)
21 | 07. [How JavaScript Works Behind the Scenes](https://github.com/xoraus/Javascript-Notes/blob/main/07.%20How%20JavaScript%20Works%20Behind%20the%20Scenes.md)
22 | 08. [Data Structures, Modern Operators and Strings](https://github.com/xoraus/Javascript-Notes/blob/main/08.%20Data%20Structures%2C%20Modern%20Operators%20and%20Strings.md)
23 | 09. [A Closer Look at Functions](https://github.com/xoraus/Javascript-Notes/blob/main/09.%20A%20Closer%20Look%20at%20Functions.md)
24 | 10. [Working With Arrays](https://github.com/xoraus/Javascript-Notes/blob/main/10.%20Working%20With%20Arrays.md)
25 | 11. [Numbers, Dates, Intl and Timers](https://github.com/xoraus/Javascript-Notes/blob/main/11.%20Numbers%2C%20Dates%2C%20Intl%20and%20Timers.md)
26 | 12. [Advanced DOM and Events](https://github.com/xoraus/Javascript-Notes/blob/main/12.%20Advanced%20DOM%20and%20Events.md)
27 | 13. [Object-Oriented Programming (O0P) With JavaScript](https://github.com/xoraus/Javascript-Notes/blob/main/13.%20Object-Oriented%20Programming%20(O0P)%20With%20JavaScript.md)
28 | 14. [Mapty App: OOP, Geolocation, External Libraries, and More!](https://github.com/xoraus/Javascript-Notes/blob/main/13.%20Object-Oriented%20Programming%20(OOP)%20.md)
29 | 15. [Asynchronous JavaScript: Promises, Async/Await, and AJAX](https://github.com/xoraus/Javascript-Notes/blob/main/14.%20Mapty%20App%20-%20OOP%2C%20Geolocation%2C%20External%20Libraries%2C%20and%20More!.md)
30 | 16. [Modern JavaScript Development: Modules, Tooling, and Functional]()
31 | 17. [Forkify App: Building a Modern Application]()
32 | 18. [Setting Up Git and Deployment]()
33 |
34 | #### 🎓 Certificate
35 |
36 | 
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/_The Complete JavaScript - Jonas Schmedtmann.md:
--------------------------------------------------------------------------------
1 | Up::
2 | Tags:: #Project
3 | Status:: #Active
4 | Links:: [[Javascript MOC]]
5 |
6 | # The Complete JavaScript Course
7 | by Jonas Schmedtmann
8 |
9 | > ## Excerpt
10 | > The modern JavaScript course for everyone! Master JavaScript with projects, challenges and theory. Many courses in one!
11 |
12 | **Course Outcome**
13 |
14 | _By the end of the course, you will have the knowledge and confidence that you need in order to ace your job interviews and become a professional developer._
15 |
16 | **So what exactly is covered in the course?**
17 | - Build 5 beautiful real-world projects for your portfolio! In these projects, you will learn how to plan and architect your applications using flowcharts and common JavaScript patterns
18 | - Master the JavaScript fundamentals: variables, if/else, operators, boolean logic, functions, arrays, objects, loops, strings, and more
19 | - Learn modern JavaScript (ES6+) from the beginning: arrow functions, destructuring, spread operator, default arguments, optional chaining (ES2020), and more
20 | - How JavaScript works behind the scenes: engines, the call stack, hoisting, scoping, the 'this' keyword, reference values, and more.
21 | - Deep dive into functions: arrow functions, first-class and higher-order functions, bind, and closures.
22 | - Deep dive into object-oriented programming: prototypal inheritance, constructor functions (ES5), classes (ES6), encapsulation, abstraction, inheritance, and polymorphism. \[This is like a small standalone course\]
23 | - Deep dive into asynchronous JavaScript: the event loop, promises, async/await, and error handling. You will use these to access data from third-party APIs with AJAX calls. \[This is like a small standalone course\]
24 | - Learn modern tools that are used by professional web developers: NPM, Parcel (module bundler), Babel, and ES6 modules
25 |
26 | # What you'll learn
27 |
28 | - Become an advanced, confident, and modern JavaScript developer from scratch
29 | - Build 6 beautiful real-world projects for your portfolio (not boring toy apps)
30 | - Become job-ready by understanding how JavaScript really works behind the scenes
31 | - How to think and work like a developer: problem-solving, researching, workflows
32 | - JavaScript fundamentals: variables, if/else, operators, boolean logic, functions, arrays, objects, loops, strings, etc.
33 | - Modern ES6+ from the beginning: arrow functions, destructuring, spread operator, optional chaining (ES2020), etc.
34 | - Modern OOP: Classes, constructors, prototypal inheritance, encapsulation, etc.
35 | - Complex concepts like the 'this' keyword, higher-order functions, closures, etc.
36 | - Asynchronous JavaScript: Event loop, promises, async/await, AJAX calls and APIs
37 | - How to architect your code using flowcharts and common patterns
38 | - Modern tools for 2022 and beyond: NPM, Parcel, Babel and ES6 modules
39 | - Practice your skills with 50+ challenges and assignments (solutions included)
40 | - Get fast and friendly support in the Q&A area
41 | - Course pathways: design your unique learning path according to your goals!
42 |
43 | # Cirriculumn
44 | - [[1. JavaScript Fundamentals Part 1]]
45 | - [[2. JavaScript Fundamentals Part 2]]
46 | - [[3. How to Navigate This Course]]
47 | - [[4. Developer Skills & Editor Setup]]
48 | - [[5. HTML & CSS Crash Course]]
49 | - [[6. JavaScript in the Browser - DOM and Events Fundamentals]]
50 | - [[7. How JavaScript Works Behind the Scenes]]
51 | - [[8. Data Structures, Modern Operators and Strings]]
52 | - [[9. A Closer Look at Functions]]
53 | - Working With Arrays
54 | - Numbers, Dates, Intl and Timers
55 | - Advanced DOM and Events
56 | - Object-Oriented Programming (O0P) With JavaScript
57 | - Mapty App: OOP, Geolocation, External Libraries, and More!
58 | - Asynchronous JavaScript: Promises, Async/Await, and AJAX
59 | - Modern JavaScript Development: Modules, Tooling, and Functional
60 | - Forkify App - Building a Modern Application
61 | - Setting Up Git and Deployment
62 |
63 | # Resources
64 | - https://codingheroes.io/resources/
65 |
66 | npm install live-server -g
67 |
68 |
--------------------------------------------------------------------------------
/04. Developer Skills & Editor Setup.md:
--------------------------------------------------------------------------------
1 | # 4. Developer Skills & Editor Setup
2 | ---
3 | ## How to fail at learning to Code
4 |
5 | A person named "_Noob Programmer_"
6 |
7 | - He didn't have a clear goal at the beginning of his journey
8 | - He started by watching courses and reading tutorials, but he would just copy the code without caring how it works. Sometimes he would just copy and paste code!
9 | - He didn't reinforce what he was learning by doing small challenges or taking notes He didn't practice coding, and didn't come up with his own project ideas
10 | - He quickly became frustrated when his code was not perfectly clean or efficient He lost motivation because he thought he could never know everything
11 | - He was learning in isolation
12 | - After finishing a couple of a courses, he thought he now was a web developer and could start applying to jobs. But he couldn't even build an app on his own!
13 |
14 | ## How to succeed at learning to Code
15 |
16 | - He didn’t have a clear goal at the beginning of his journey
17 | - **FIX**
18 | - Set a specific, measurable, realistic and time-based goal
19 | - Know exactly why you are learning to code: Switching careers? Finding a better job?
20 | - Imagine a big project you want to be able to build!
21 | - Research technologies you need and then learn them
22 | - He would just copy the code without caring how it works. Sometimes he would just copy and paste code!
23 | - **FIX**
24 | - Understand the code that you're studying and typing
25 | - Always type the code, don't copy-paste!
26 | - He didn't reinforce what he was learning by doing small challenges or taking notes
27 | - **FIX**
28 | - After you learn a new a feature or concept, use it immediately
29 | - Take notes
30 | - Challenge yourself and practice with small coding exercises and challenges
31 | - Don't be in a hurry to complete the course fast!
32 | - He didn't practice coding, and didn't come up with his own project ideas
33 | - **FIX**
34 | - Practicing on your own is the most important thing to do
35 | - This is NOT optional! Without practice outside of courses, you won't go anywhere!
36 | - Come up with your own project ideas or copy popular sites or applications, or just parts of them in the beginning Don't be stuck in "tutorial hell"
37 | - He quickly became frustrated when his code was not perfectly clean or efficient
38 | - **FIX**
39 | - Don't get stuck trying to write the perfect code!
40 | - Just write tons of code, no matter the quality!
41 | - Clean and efficient code will come with time
42 | - You can always refactor code later
43 | - He lost motivation because he thought he could never know everything
44 | - **FIX**
45 | - Embrace the fact that you will never you know everything
46 | - Just focus on what you need to achieve your goal!
47 | - He was learning in isolation
48 | - **FIX**
49 | - Explain new concepts to other people. If you can explain it, you truly understand it!
50 | - Share your goals to make yourself accountable
51 | - Share your learning progress with the web dev community ( ##100DaysOfCode, ##CodeNewbie, ##webdev, etc.)
52 | - After finishing a couple of courses, he thought he now was a web developer and could start applying to jobs
53 | - **FIX**
54 | - The biggest misconception that people have!
55 | - Courses are an amazing starting point, but are only the beginning of your journey!
56 |
57 | ## Learning how to code is hard, but you can do it!
58 |
59 | ![[4. Developer Skills & Editor Setup-1661521832385.jpeg]]
60 |
61 | ## How to fail at solving problems
62 |
63 | WHENEVER JOHN ENCOUNTERS A PROBLEM:
64 | * He jumps at the problem without much thinking
65 | * He implements his solution in an unstructured way
66 | * He gets stressed out when things don't work
67 | * He is too proud to research solutions
68 | - **FIX**
69 | - Stay calm and slow down, don't just jump at a problem without a plan
70 | - Take a very logical and rational approach (programming is just logic, in the end...)
71 | - Use my 4-step framework to solve any problem
72 | - Make sure you 100% understand the problem. Ask the right questions to get a clear picture of the problem
73 | - Divide and conquer: Break a big problem into smaller sub-problems.
74 | - Don't be afraid to do as much research as you have to
75 | - For bigger problems, write pseudo-code before writing the actual code
76 |
77 | ## What is a software bug?
78 |
79 | - Software bug: Defect or problem in a computer program. Basically, any unexpected or unintended behavior of a computer program is a software bug.
80 | - Bugs are completely normal in software development!
81 | - Debugging: Process of finding, fixing and preventing bugs.
82 | - _Note_ - A real bug which was causing an error in Harvard's computer in the 1940s
83 |
84 | ## The Debugging Process
85 |
86 | ![[4. Developer Skills & Editor Setup-1661522068743.jpeg]]
87 |
88 |
--------------------------------------------------------------------------------
/09. A Closer Look at Functions.md:
--------------------------------------------------------------------------------
1 | # 9. A Closer Look at Functions
2 | ---
3 | ## Default Parameters
4 | ```js
5 | ///////////////////////////////////////
6 | // Default Parameters
7 | const bookings = [];
8 |
9 | const createBooking = function (
10 | flightNum,
11 | numPassengers = 1,
12 | price = 199 * numPassengers
13 | ) {
14 | // ES5
15 | // numPassengers = numPassengers || 1;
16 | // price = price || 199;
17 |
18 | const booking = {
19 | flightNum,
20 | numPassengers,
21 | price,
22 | };
23 | console.log(booking);
24 | bookings.push(booking);
25 | };
26 |
27 | createBooking('LH123');
28 | createBooking('LH123', 2, 800);
29 | createBooking('LH123', 2);
30 | createBooking('LH123', 5);
31 |
32 | createBooking('LH123', undefined, 1000);
33 | ```
34 | - Default function parameters allow named parameters to be initialized with default values if no value or undefined is passed.
35 | - In JavaScript, function parameters default to [`undefined`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined). However, it's often useful to set a different default value.
36 | - Sometimes, you can use the terms argument and parameter interchangeably. However, by definition, parameters are what you specify in the [function declaration](https://www.javascripttutorial.net/javascript-function/) whereas the arguments are what you pass into the function.
37 |
38 | ## How Passing Arguments Works: Value vs. Reference
39 |
40 | - Passing a primitive type to a function is really just the same as creating a copy like this, outside of the function. So the value is simply copied. On the other hand, when we pass an object to a function, it is really just like copying an object like this. And so whatever we change in a copy will also happen in the original.
41 | - In JavaScript, you can pass by value and by reference. The main difference between the two is that passing by value happens when assigning primitives while passing by reference when assigning objects.
42 | - In JavaScript primitive types are passed around as values: meaning that each time a value is assigned, a copy of that value is created.
43 | - On the other side objects (including plain objects, array, functions, class instances) are references. If you modify the object, then all variables that reference that object are going to see the change.
44 | - The comparison operator distinguishes comparing values and references. 2 variables holding references are equal only if they reference exactly the same object, but 2 variables holding values are equal if they simply have 2 same values no matter where the value originates: from a variable, literal, etc.
45 | ```js
46 | ///////////////////////////////////////
47 | // How Passing Arguments Works: Values vs. Reference
48 | const flight = 'LH234';
49 | const jonas = {
50 | name: 'Jonas Schmedtmann',
51 | passport: 24739479284,
52 | };
53 |
54 | const checkIn = function (flightNum, passenger) {
55 | flightNum = 'LH999';
56 | passenger.name = 'Mr. ' + passenger.name;
57 |
58 | if (passenger.passport === 24739479284) {
59 | alert('Checked in');
60 | } else {
61 | alert('Wrong passport!');
62 | }
63 | };
64 |
65 | // checkIn(flight, jonas); // this will modify the jonas object
66 | // console.log(flight);
67 | // console.log(jonas);
68 |
69 | // Is the same as doing...
70 | // const flightNum = flight;
71 | // const passenger = jonas;
72 |
73 | const newPassport = function (person) {
74 | person.passport = Math.trunc(Math.random() * 100000000000);
75 | };
76 |
77 | newPassport(jonas);
78 | checkIn(flight, jonas);
79 | ```
80 |
81 | ## First-Class and Higher-Order Functions
82 | - A programming language is said to have **First-class functions** when functions in that language are treated like any other variable. For example, in such a language, a function can be passed as an argument to other functions, can be returned by another function and can be assigned as a value to a variable.
83 | - **First-class functions** are JavaScript functions that can behave like variables. They can also be parsed as arguments to higher-order functions.
84 | - **Higher-order functions** are functions that return a function or take in a function as an argument.
85 | - So, first class functions is just a feature that a programming language either has or does not have. All it means is that all functions are values. There are no first class functions in practice, It's just a concept.
86 | - Any difference between First Class Function and High Order Function - [Stackoverflow](https://stackoverflow.com/questions/10141124/any-difference-between-first-class-function-and-high-order-function)
87 | - There is a difference. When you say that a language has first-class functions, it means that the language treats functions as values – that you can assign a function into a variable, pass it around etc. Higher-order functions are functions that work on other functions, meaning that they take one or more functions as an argument and can also return a function.
88 | - The “higher-order” concept can be applied to functions in general, like functions in the mathematical sense. The “first-class” concept only has to do with functions in programming languages. It’s seldom used when referring to a function, such as “a first-class function”. It’s much more common to say that “a language has/hasn’t first-class function support”.
89 | - The two things are closely related, as it’s hard to imagine a language with first-class functions that would not also support higher-order functions, and conversely a language with higher-order functions but without first-class function support.
90 |
91 | ![[9. A Closer Look at Functions-1662649740328.jpeg]]
92 |
93 | ## Functions Accepting Callback Functions
94 | ```js
95 | ///////////////////////////////////////
96 | // Functions Accepting Callback Functions
97 | const oneWord = function (str) {
98 | return str.replace(/ /g, '').toLowerCase();
99 | };
100 |
101 | const upperFirstWord = function (str) {
102 | const [first, ...others] = str.split(' ');
103 | return [first.toUpperCase(), ...others].join(' ');
104 | };
105 |
106 | // Higher-order function
107 | const transformer = function (str, fn) {
108 | console.log(`Original string: ${str}`);
109 | console.log(`Transformed string: ${fn(str)}`);
110 |
111 | console.log(`Transformed by: ${fn.name}`);
112 | };
113 |
114 | transformer('JavaScript is the best!', upperFirstWord);
115 | transformer('JavaScript is the best!', oneWord);
116 |
117 | // JS uses callbacks all the time
118 | const high5 = function () {
119 | console.log('👋');
120 | };
121 | document.body.addEventListener('click', high5);
122 | ['Jonas', 'Martha', 'Adam'].forEach(high5);
123 | ```
124 |
125 | ## Functions Returning Functions
126 |
127 | ```js
128 | ///////////////////////////////////////
129 | // Functions Returning Functions
130 | const greet = function (greeting) {
131 | return function (name) {
132 | console.log(`${greeting} ${name}`);
133 | };
134 | };
135 |
136 | const greeterHey = greet('Hey');
137 | greeterHey('Jonas');
138 | greeterHey('Steven');
139 |
140 | greet('Hello')('Jonas');
141 |
142 | // Challenge
143 | const greetArr = greeting => name => console.log(`${greeting} ${name}`);
144 |
145 | greetArr('Hi')('Jonas');
146 |
147 | ```
148 |
149 | ## The call and apply Methods
150 | - The **`apply()/call()`** method calls the specified function with a given `this` value, and `arguments` provided as an array.
151 | - The `call()` method takes arguments **separately**. The `apply()` method takes arguments as an **array**.
152 |
153 | ```js
154 | ///////////////////////////////////////
155 | // The call and apply Methods
156 | const lufthansa = {
157 | airline: 'Lufthansa',
158 | iataCode: 'LH',
159 | bookings: [],
160 | // book: function() {}
161 | book(flightNum, name) {
162 | console.log(
163 | `${name} booked a seat on ${this.airline} flight ${this.iataCode}${flightNum}`
164 | );
165 | this.bookings.push({ flight: `${this.iataCode}${flightNum}`, name });
166 | },
167 | };
168 |
169 | lufthansa.book(239, 'Jonas Schmedtmann');
170 | lufthansa.book(635, 'John Smith');
171 |
172 | const eurowings = {
173 | airline: 'Eurowings',
174 | iataCode: 'EW',
175 | bookings: [],
176 | };
177 |
178 | const book = lufthansa.book;
179 |
180 | // Does NOT work because this is pointing to 'Undefined'
181 | // book(23, 'Sarah Williams');
182 |
183 | // Call method
184 | book.call(eurowings, 23, 'Sarah Williams');
185 | console.log(eurowings);
186 |
187 | book.call(lufthansa, 239, 'Mary Cooper');
188 | console.log(lufthansa);
189 |
190 | const swiss = {
191 | airline: 'Swiss Air Lines',
192 | iataCode: 'LX',
193 | bookings: [],
194 | };
195 |
196 | book.call(swiss, 583, 'Mary Cooper');
197 |
198 | // Apply method
199 | const flightData = [583, 'George Cooper'];
200 | book.apply(swiss, flightData);
201 | console.log(swiss);
202 |
203 | // Instead of using apply + array we can use call + ...rest
204 | book.call(swiss, ...flightData);
205 | ```
206 |
207 | ## The bind Method
208 | - The **`bind()`** method creates a new function that, when called, has its `this` keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
209 | - In an event handler function, **this keyword** always points to the element on which that handler is attached to.
210 | - Partial applications means that we can preset parameters.
211 | -
212 |
213 | ```js
214 | ///////////////////////////////////////
215 | // The bind Method
216 | // book.call(eurowings, 23, 'Sarah Williams');
217 |
218 | const bookEW = book.bind(eurowings);
219 | const bookLH = book.bind(lufthansa);
220 | const bookLX = book.bind(swiss);
221 |
222 | bookEW(23, 'Steven Williams');
223 |
224 | const bookEW23 = book.bind(eurowings, 23);
225 | bookEW23('Jonas Schmedtmann');
226 | bookEW23('Martha Cooper');
227 |
228 | // With Event Listeners
229 | lufthansa.planes = 300;
230 | lufthansa.buyPlane = function () {
231 | console.log(this);
232 |
233 | this.planes++;
234 | console.log(this.planes);
235 | };
236 | // lufthansa.buyPlane();
237 |
238 | document
239 | .querySelector('.buy')
240 | .addEventListener('click', lufthansa.buyPlane.bind(lufthansa));
241 |
242 | // Partial application
243 | const addTax = (rate, value) => value + value * rate;
244 | console.log(addTax(0.1, 200));
245 |
246 | const addVAT = addTax.bind(null, 0.23);
247 | // addVAT = value => value + value * 0.23;
248 |
249 | console.log(addVAT(100));
250 | console.log(addVAT(23));
251 |
252 | const addTaxRate = function (rate) {
253 | return function (value) {
254 | return value + value * rate;
255 | };
256 | };
257 | const addVAT2 = addTaxRate(0.23);
258 | console.log(addVAT2(100));
259 | console.log(addVAT2(23));
260 | ```
261 |
262 | ## Coding Challenge ##1
263 | Let's build a simple poll app!
264 |
265 | A poll has a question, an array of options from which people can choose, and an array with the number of replies for each option. This data is stored in the starter object below.
266 |
267 | Here are your tasks:
268 |
269 | 1. Create a method called 'registerNewAnswer' on the 'poll' object. The method does 2 things:
270 | - 1.1. Display a prompt window for the user to input the number of the selected option. The prompt should look like this:
271 | - What is your favourite programming language?
272 | - 0: JavaScript
273 | - 1: Python
274 | - 2: Rust
275 | - 3: C++
276 | - (Write option number)
277 | - 1.2. Based on the input number, update the answers array. For example, if the option is 3, increase the value AT POSITION 3 of the array by 1. Make sure to check if the input is a number and if the number makes sense (e.g answer 52 wouldn't make sense, right?)
278 | 2. Call this method whenever the user clicks the "Answer poll" button.
279 | 3. Create a method 'displayResults' which displays the poll results. The method takes a string as an input (called 'type'), which can be either 'string' or 'array'. If type is 'array', simply display the results array as it is, using console.log(). This should be the default option. If type is 'string', display a string like "Poll results are 13, 2, 4, 1".
280 | 4. Run the 'displayResults' method at the end of each 'registerNewAnswer' method call.
281 |
282 | HINT: Use many of the tools you learned about in this and the last section 😉
283 |
284 | BONUS: Use the 'displayResults' method to display the 2 arrays in the test data. Use both the 'array' and the 'string' option. Do NOT put the arrays in the poll object! So what shoud the this keyword look like in this situation?
285 |
286 | BONUS TEST DATA 1: [5, 2, 3]
287 | BONUS TEST DATA 2: [1, 5, 3, 9, 6, 1]
288 | ```js
289 | const poll = {
290 | question: 'What is your favourite programming language?',
291 | options: ['0: JavaScript', '1: Python', '2: Rust', '3: C++'],
292 | // This generates [0, 0, 0, 0]. More in the next section 😃
293 | answers: new Array(4).fill(0),
294 | registerNewAnswer() {
295 | // Get answer
296 | const answer = Number(
297 | prompt(
298 | `${this.question}\n${this.options.join('\n')}\n(Write option number)`
299 | )
300 | );
301 | console.log(answer);
302 |
303 | // Register answer
304 | typeof answer === 'number' &&
305 | answer < this.answers.length &&
306 | this.answers[answer]++;
307 |
308 | this.displayResults();
309 | this.displayResults('string');
310 | },
311 |
312 | displayResults(type = 'array') {
313 | if (type === 'array') {
314 | console.log(this.answers);
315 | } else if (type === 'string') {
316 | // Poll results are 13, 2, 4, 1
317 | console.log(`Poll results are ${this.answers.join(', ')}`);
318 | }
319 | },
320 | };
321 |
322 | document
323 | .querySelector('.poll')
324 | .addEventListener('click', poll.registerNewAnswer.bind(poll));
325 |
326 | poll.displayResults.call({ answers: [5, 2, 3] }, 'string');
327 | poll.displayResults.call({ answers: [1, 5, 3, 9, 6, 1] }, 'string');
328 | poll.displayResults.call({ answers: [1, 5, 3, 9, 6, 1] });
329 |
330 | // [5, 2, 3]
331 | // [1, 5, 3, 9, 6, 1]
332 | ```
333 |
334 | ## Immediately Invoked Function Expressions (IIFE)
335 | - IIFEs are functions that are executed _immediately after_ being defined. We can make any function expression an IIFE by wrapping it in parentheses, and adding a following pair of parentheses at the end:
336 | ```js
337 | (function() {
338 | // Code that runs in your function
339 | })()
340 | ```
341 | - Alternatively, you can use the arrow syntax to create an IIFE as follows:
342 | ```js
343 | (() => {
344 | // Code that runs in your function
345 | })()
346 | ```
347 | - The parentheses surrounding the function definition lets JavaScript know that it will process a function expression. The last pair of parentheses invoke the function.
348 | ###### When to Use an IIFE?
349 |
350 | The most common use cases for IIFEs are:
351 |
352 | - Aliasing global variables
353 | - Creating private variables and functions
354 | - Asynchronous functions in loops
355 | ```js
356 | ///////////////////////////////////////
357 | // Immediately Invoked Function Expressions (IIFE)
358 | const runOnce = function () {
359 | console.log('This will never run again');
360 | };
361 | runOnce();
362 |
363 | // IIFE
364 | (function () {
365 | console.log('This will never run again');
366 | const isPrivate = 23;
367 | })();
368 |
369 | // console.log(isPrivate);
370 |
371 | (() => console.log('This will ALSO never run again'))();
372 |
373 | {
374 | const isPrivate = 23;
375 | var notPrivate = 46;
376 | }
377 | // console.log(isPrivate);
378 | console.log(notPrivate);
379 | ```
380 | - [more on IIFE](https://stackabuse.com/javascripts-immediately-invoked-function-expressions/)
381 |
382 | ## Closures
383 | - A **closure** is a function which has access to the variable from another function’s scope. This is accomplished by creating a function inside a function.
384 | - A **closure** is the combination of a function bundled together (enclosed) with references to its surrounding state (the **lexical environment**). In other words, a closure gives you access to an outer function's scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.
385 | - JavaScript variables can belong to the **local** or **global** scope. Global variables can be made local (private) with **closures**.
386 | - [Closures in Javascript for beginners](https://www.codingame.com/playgrounds/6516/closures-in-javascript-for-beginners
387 | - **Creating A Closure**
388 | - ![[9. A Closer Look at Functions-1662920198036.jpeg]]
389 | - Understanding Closure
390 | - ![[9. A Closer Look at Functions-1662920260588.jpeg]]
391 | - Summary
392 | - ![[9. A Closer Look at Functions-1662920308154.jpeg]]
393 | ```js
394 | ///////////////////////////////////////
395 | // Closures
396 | const secureBooking = function () {
397 | let passengerCount = 0;
398 |
399 | return function () {
400 | passengerCount++;
401 | console.log(`${passengerCount} passengers`);
402 | };
403 | };
404 |
405 | const booker = secureBooking();
406 |
407 | booker();
408 | booker();
409 | booker();
410 |
411 | console.dir(booker);
412 | ```
413 |
414 | ## More Closure Examples
415 | - a closure always makes sure that a function does not lose the connection to the variables that were present at its birthplace.
416 | - closure does in fact have priority over the scope chain.
417 | ```js
418 | ///////////////////////////////////////
419 | // More Closure Examples
420 | // Example 1
421 | let f;
422 |
423 | const g = function () {
424 | const a = 23;
425 | f = function () {
426 | console.log(a * 2);
427 | };
428 | };
429 |
430 | const h = function () {
431 | const b = 777;
432 | f = function () {
433 | console.log(b * 2);
434 | };
435 | };
436 |
437 | g();
438 | f(); // output: 46
439 | console.dir(f);
440 |
441 | // Re-assigning f function
442 | h();
443 | f();
444 | console.dir(f);
445 |
446 | // Example 2
447 | const boardPassengers = function (n, wait) {
448 | const perGroup = n / 3;
449 |
450 | setTimeout(function () {
451 | console.log(`We are now boarding all ${n} passengers`);
452 | console.log(`There are 3 groups, each with ${perGroup} passengers`);
453 | }, wait * 1000);
454 |
455 | console.log(`Will start boarding in ${wait} seconds`);
456 | };
457 |
458 | const perGroup = 1000;
459 | boardPassengers(180, 3);
460 | */
461 | ```
462 |
463 | ## Coding Challenge ##2
464 | This is more of a thinking challenge than a coding challenge 🤓
465 |
466 | Take the IIFE below and at the end of the function, attach an event listener that changes the color of the selected h1 element ('header') to blue, each time the BODY element is clicked. Do NOT select the h1 element again!
467 |
468 | And now explain to YOURSELF (or someone around you) WHY this worked! Take all the time you need. Think about WHEN exactly the callback function is executed, and what that means for the variables involved in this example.e
469 |
470 | ```js
471 | (function () {
472 | const header = document.querySelector('h1');
473 | header.style.color = 'red';
474 | document.querySelector('body').addEventListener('click', function () {
475 | header.style.color = 'blue';
476 | });
477 | })();
478 |
479 | ```
--------------------------------------------------------------------------------
/12. Advanced DOM and Events.md:
--------------------------------------------------------------------------------
1 | # 12. Advanced DOM and Events
2 | ---
3 |
4 | ## How the DOM Really Works
5 | ![[12. Advanced DOM and Events-1663411720931.jpeg]]
6 |
7 | - Allows us to make JavaScript interact with the browser;
8 | - We can write JavaScript to create, modify and delete HTML elements; set styles, classes and attributes; and listen and respond to events; DOM tree is generated from an HTML document, which we can then interact with;
9 | - DOM is a very complex API that contains lots of methods and properties to interact with the DOM tree
10 | ```js
11 | .querySelector() / .addEventListener() / .createElement() /
12 | .innerHTML / .textContent / .children / etc ...
13 | ```
14 |
15 | **How the DOM API is organized behind the Scenes**
16 | ![[12. Advanced DOM and Events-1663412092906.jpeg]]
17 |
18 | - A DOM API is broken up into these different types of nodes. also want you to understand that each of these types of nodes has access to different properties and methods and that some of them even inherit more properties and methods from their ancestors in this organization.
19 |
20 | ## Selecting, Creating, and Deleting Elements
21 | ```js
22 | ///////////////////////////////////////
23 | // Selecting, Creating, and Deleting Elements
24 |
25 | // Selecting elements
26 | console.log(document.documentElement);
27 | console.log(document.head);
28 | console.log(document.body);
29 |
30 | const header = document.querySelector('.header');
31 | const allSections = document.querySelectorAll('.section');
32 | console.log(allSections);
33 |
34 | document.getElementById('section--1');
35 | const allButtons = document.getElementsByTagName('button');
36 | console.log(allButtons);
37 |
38 | console.log(document.getElementsByClassName('btn'));
39 |
40 | // Creating and inserting elements
41 | const message = document.createElement('div');
42 | message.classList.add('cookie-message');
43 | // message.textContent = 'We use cookied for improved functionality and analytics.';
44 | message.innerHTML =
45 | 'We use cookied for improved functionality and analytics. ';
46 |
47 | // header.prepend(message);
48 | header.append(message);
49 | // header.append(message.cloneNode(true));
50 |
51 | // header.before(message);
52 | // header.after(message);
53 |
54 | // Delete elements
55 | document
56 | .querySelector('.btn--close-cookie')
57 | .addEventListener('click', function () {
58 | // message.remove(); // new way of removing element
59 | message.parentElement.removeChild(message); // old way of removing element
60 | });
61 | ```
62 |
63 | ## Styles, Attributes and Classes
64 | ```js
65 | message.style.background = '#37383d';
66 | message.style.width = '120%';
67 |
68 | console.log(message.style.color);
69 | console.log(message.style.backgroundColor);
70 |
71 | console.log(getComputedStyle(message).color);
72 | console.log(getComputedStyle(message).height);
73 |
74 | message.style.height =
75 | Number.parseFloat(getComputedStyle(message).height, 10) + 30 + 'px';
76 |
77 | document.documentElement.style.setProperty('--color-primary', 'orangered');
78 |
79 | // Attributes
80 | const logo = document.querySelector('.nav__logo');
81 | console.log(logo.alt);
82 | console.log(logo.src);
83 | console.log(logo.className);
84 |
85 | logo.alt = 'Beautiful minimilist logo';
86 |
87 | // Non-standard
88 | console.log(logo.designer);
89 | console.log(logo.getAttribute('designer'));
90 | logo.setAttribute('company', 'Bankist');
91 |
92 | console.log(logo.src); // Absolute Path
93 | console.log(logo.getAttribute('src')); // Relative Path
94 |
95 | const link = document.querySelector('.twitter-link');
96 | console.log(link.href);
97 |
98 | // Data attributes
99 | console.log(logo.dataset.versionNumber);
100 |
101 | // Classes
102 | logo.classList.add('c', 'j');
103 | logo.classList.remove('c', 'j');
104 | logo.classList.toggle('c');
105 | logo.classList.contains('c'); // not includes as in arrays
106 |
107 | // Don't use
108 | logo.classList = 'xoraus';
109 | ```
110 |
111 | ## Implementing Smooth Scrolling
112 | ```js
113 | const buttonTo = document.querySelector('.btn--scroll-to');
114 | const section1 = document.querySelector('#section--1');
115 |
116 | buttonTo.addEventListener('click', function (e) {
117 | const s1cords = section1.getBoundingClientRect();
118 | console.log(s1cords);
119 |
120 | console.log(e.target.getBoundingClientRect());
121 |
122 | console.log('Current scroll (X/Y', window.pageXOffset, window.pageYOffset);
123 |
124 | console.log(
125 | 'height/width viewport',
126 | document.documentElement.clientHeight,
127 | document.documentElement.clientWidth
128 | );
129 |
130 | // scrolling - Old Implemetion
131 | // window.scrollTo(
132 | // s1cords.left + window.pageXOffset,
133 | // s1cords.top + window.pageYOffset
134 | // );
135 |
136 | // window.scrollTo({
137 | // left: s1cords.left + window.pageXOffset,
138 | // top: s1cords.top + window.pageYOffset,
139 | // behavior: 'smooth',
140 | // });
141 |
142 | // Modern way of implementing scrolling - works only in modern browsers
143 |
144 | section1.scrollIntoView({ behavior: 'smooth' });
145 | });
146 | ```
147 |
148 | ## Types of Events and Event Handlers
149 | - There are two ways why addEventListener is better. The first one is that it allows us to add multiple event listeners to the same event. And the second one is that we can actually remove an event handler in case we don't need it anymore.
150 | ```js
151 | const h1 = document.querySelector('h1');
152 |
153 | const alertH1 = function (e) {
154 | alert('addEventListerner: Great! You are reading the heading :D');
155 | h1.removeEventListener('mouseenter', alertH1);
156 | };
157 |
158 | h1.addEventListener('mouseenter', alertH1);
159 |
160 | // Removing event listener after 3 seconds
161 | setTimeout(() => h1.removeEventListener('mouseenter', alertH1), 3000);
162 |
163 |
164 | /*
165 | // However, this way of listening to events is a bit old school.
166 | h1.onmouseenter = function (e) {
167 | alert('addEventListerner: Great! You are reading the heading :D');
168 | };
169 | */
170 | ```
171 |
172 | ## Event Propagation: Bubbling and Capturing
173 | **Bubbling and Capturing**
174 | ![[12. Advanced DOM and Events-1663427457918.jpeg]]
175 | - Now by default, events can only be handled in the target, and in the bubbling phase.
176 | However, we can set up event listeners in a way that they listen to events in the capturing phase instead. Also, actually not all types of events that do have a capturing and bubbling phase. Some of them are created right on the target element, and so we can only handle them there.
177 | - We can also say that events propagate, which is really what capturing and bubbling is. It's events propagating from one place to another.
178 |
179 | ## Event Propagation in Practice
180 | - The event handler functions are listening for click events that happen on the element itself, and they are also listening for events that keep bubbling up from their child elements and that's the reason why the color changes in all of the parent elements here as well.
181 | - At event listener, it's only listening for events in the bubbling phase, but not in the capturing phase. So that is the default behavior of the add event listener method, and the reason for that is that the capturing phase is usually irrelevant for us.
182 | - Now, on the other hand, the bubbling phase can be very useful for something called event delegation.
183 | - Capturing is actually rarely used these days. And the only reason why both o capturing and bubbling actually exist, is only for historical reasons. So, from the time where different browsers implemented different versions of JavaScript.
184 | ```js
185 | const randomInt = (min, max) =>
186 | Math.floor(Math.random() * (max - min + 1) + min);
187 | const randomColor = () =>
188 | `rgb(${randomInt(0, 255)},${randomInt(0, 255)},${randomInt(0, 255)})`;
189 |
190 | document.querySelector('.nav__link').addEventListener('click', function (e) {
191 | this.style.backgroundColor = randomColor();
192 | console.log('LINK', e.target, e.currentTarget);
193 | console.log(e.currentTarget === this);
194 |
195 | // Stop propagation
196 | // e.stopPropagation();
197 | });
198 |
199 | document.querySelector('.nav__links').addEventListener('click', function (e) {
200 | this.style.backgroundColor = randomColor();
201 | console.log('CONTAINER', e.target, e.currentTarget);
202 | });
203 |
204 | document.querySelector('.nav').addEventListener('click', function (e) {
205 | this.style.backgroundColor = randomColor();
206 | console.log('NAV', e.target, e.currentTarget);
207 | });
208 | ```
209 | ![[12. Advanced DOM and Events-1663431880090.jpeg]]
210 |
211 | ## Event Delegation: Implementing Page Navigation
212 | ```js
213 | // Page Navigation
214 |
215 | document.querySelectorAll('.nav__link').forEach(function (el) {
216 | el.addEventListener('click', function (e) {
217 | e.preventDefault();
218 | const id = this.getAttribute('href');
219 | document.querySelector(id).scrollIntoView({ behavior: 'smooth' });
220 | });
221 | });
222 |
223 | /* Now, as you see, this actually works just fine, but the problem is that it's not really efficient.
224 | So we are adding here the exact same callback function, so this event handler here, we are adding it once to each of these three elements.
225 | So the exact same function is now attached to these three elements. And that's kind of unnecessary. And it's really just not a clean solution in that case. And so, the better solution without a doubt, is to use events delegation. */
226 |
227 | // 1. Add event listener to common parent element
228 | // 2. Determine what element originated the elvent
229 |
230 | document.querySelector('.nav__links').addEventListener('click', function (e) {
231 | e.preventDefault();
232 |
233 | // Matching strategy - The tricky part
234 | if (e.target.classList.contains('nav__link')) {
235 | const id = e.target.getAttribute('href');
236 | document.querySelector(id).scrollIntoView({ behavior: 'smooth' });
237 | }
238 | });
239 | ```
240 |
241 | ## DOM Traversing
242 | ```js
243 | const h1 = document.querySelector('h1');
244 |
245 | // Going downwards: child
246 | console.log(h1.querySelectorAll('.highlight'));
247 | console.log(h1.childNodes);
248 | console.log(h1.children);
249 |
250 | h1.firstElementChild.style.color = 'white';
251 | h1.lastElementChild.style.color = 'orangered';
252 |
253 | // Going upwards
254 | console.log(h1.parentNode);
255 | console.log(h1.parentElement);
256 |
257 | h1.closest('.header').style.background = 'var(--gradient-secondary)';
258 |
259 | h1.closest('h1').style.background = 'var(--gradient-primary)';
260 |
261 | // Going sideways: siblings
262 | console.log(h1.previousElementSibling);
263 | console.log(h1.nextElementSibling);
264 |
265 | console.log(h1.previousSibling);
266 | console.log(h1.nextSibling);
267 |
268 | console.log(h1.parentElement.children);
269 | [...h1.parentElement.children].forEach(function (el) {
270 | if (el !== h1) {
271 | el.style.transform = 'scale(0.5)';
272 | }
273 | });
274 |
275 | ```
276 |
277 | ![[12. Advanced DOM and Events-1663484588539.jpeg]]
278 |
279 | ## Tabbed Component
280 | ```js
281 | ///////////////////////////////////////
282 | // Tabbed component
283 |
284 | tabsContainer.addEventListener('click', function (e) {
285 | const clicked = e.target.closest('.operations__tab');
286 |
287 | // Guard clause
288 | if (!clicked) return;
289 |
290 | // Remove active classes
291 | tabs.forEach(t => t.classList.remove('operations__tab--active'));
292 | tabsContent.forEach(c => c.classList.remove('operations__content--active'));
293 |
294 | // Activate tab
295 | clicked.classList.add('operations__tab--active');
296 |
297 | // Activate content area
298 | document
299 | .querySelector(`.operations__content--${clicked.dataset.tab}`)
300 | .classList.add('operations__content--active');
301 | });
302 | ```
303 |
304 | ![[12. Advanced DOM and Events-1663523150947.jpeg]]
305 |
306 | ## Passing Arguments to Event Handlers
307 | ```js
308 | ///////////////////////////////////////
309 | // Menu fade animation
310 | const handleHover = function (e) {
311 | if (e.target.classList.contains('nav__link')) {
312 | const link = e.target;
313 | const siblings = link.closest('.nav').querySelectorAll('.nav__link');
314 | const logo = link.closest('.nav').querySelector('img');
315 |
316 | siblings.forEach(el => {
317 | if (el !== link) el.style.opacity = this;
318 | });
319 | logo.style.opacity = this;
320 | }
321 | };
322 |
323 | // Passing "argument" into handler
324 | nav.addEventListener('mouseover', handleHover.bind(0.5));
325 | nav.addEventListener('mouseout', handleHover.bind(1));
326 | ```
327 |
328 | ![[12. Advanced DOM and Events-1663524394907.jpeg]]
329 |
330 | ## Implementing a Sticky Navigation: The Scroll Event
331 | ```js
332 | // Sticky navigation
333 | const initialCords = section1.getBoundingClientRect();
334 | window.addEventListener('scroll', function () {
335 | if (this.window.scrollY > initialCords.top) nav.classList.add('sticky');
336 | else nav.classList.remove('sticky');
337 | });
338 | ```
339 | - `window.scrollY` this is a very inefficient method.
340 |
341 | ## A Better Way: The Intersection Observer API
342 | - Well, this API allows our code to basically observe changes to the way that a certain target element intersects another element, or the way it intersects the viewport.
343 | ```js
344 | ///////////////////////////////////////
345 | // Sticky navigation: Intersection Observer API
346 |
347 | const header = document.querySelector('.header');
348 | const navHeight = nav.getBoundingClientRect().height;
349 |
350 | const stickyNav = function (entries) {
351 | const [entry] = entries;
352 | // console.log(entry);
353 |
354 | if (!entry.isIntersecting) nav.classList.add('sticky');
355 | else nav.classList.remove('sticky');
356 | };
357 |
358 | const headerObserver = new IntersectionObserver(stickyNav, {
359 | root: null,
360 | threshold: 0,
361 | rootMargin: `-${navHeight}px`,
362 | });
363 |
364 | headerObserver.observe(header);
365 | ```
366 |
367 | ## Revealing Elements on Scroll
368 | ```js
369 | ///////////////////////////////////////
370 | // Reveal sections
371 | const allSections = document.querySelectorAll('.section');
372 |
373 | const revealSection = function (entries, observer) {
374 | const [entry] = entries;
375 |
376 | if (!entry.isIntersecting) return;
377 |
378 | entry.target.classList.remove('section--hidden');
379 | observer.unobserve(entry.target);
380 | };
381 |
382 | const sectionObserver = new IntersectionObserver(revealSection, {
383 | root: null,
384 | threshold: 0.15,
385 | });
386 |
387 | allSections.forEach(function (section) {
388 | sectionObserver.observe(section);
389 | section.classList.add('section--hidden');
390 | });
391 | ```
392 |
393 | ## Lazy Loading Images
394 | ```js
395 | // Lazy loading images
396 | const imgTargets = document.querySelectorAll('img[data-src]');
397 |
398 | const loadImg = function (entries, observer) {
399 | const [entry] = entries;
400 |
401 | if (!entry.isIntersecting) return;
402 |
403 | // Replace src with data-src
404 | entry.target.src = entry.target.dataset.src;
405 |
406 | entry.target.addEventListener('load', function () {
407 | entry.target.classList.remove('lazy-img');
408 | });
409 |
410 | observer.unobserve(entry.target);
411 | };
412 |
413 | const imgObserver = new IntersectionObserver(loadImg, {
414 | root: null,
415 | threshold: 0,
416 | rootMargin: '200px',
417 | });
418 |
419 | imgTargets.forEach(img => imgObserver.observe(img));
420 | ```
421 |
422 | ## Building a Slider Component: Part 1 & Part 2
423 | ```js
424 | ///////////////////////////////////////
425 | // Slider
426 | const slider = function () {
427 | const slides = document.querySelectorAll('.slide');
428 | const btnLeft = document.querySelector('.slider__btn--left');
429 | const btnRight = document.querySelector('.slider__btn--right');
430 | const dotContainer = document.querySelector('.dots');
431 |
432 | let curSlide = 0;
433 | const maxSlide = slides.length;
434 |
435 | // Functions
436 | const createDots = function () {
437 | slides.forEach(function (_, i) {
438 | dotContainer.insertAdjacentHTML(
439 | 'beforeend',
440 | ``
441 | );
442 | });
443 | };
444 |
445 | const activateDot = function (slide) {
446 | document
447 | .querySelectorAll('.dots__dot')
448 | .forEach(dot => dot.classList.remove('dots__dot--active'));
449 |
450 | document
451 | .querySelector(`.dots__dot[data-slide="${slide}"]`)
452 | .classList.add('dots__dot--active');
453 | };
454 |
455 | const goToSlide = function (slide) {
456 | slides.forEach(
457 | (s, i) => (s.style.transform = `translateX(${100 * (i - slide)}%)`)
458 | );
459 | };
460 |
461 | // Next slide
462 | const nextSlide = function () {
463 | if (curSlide === maxSlide - 1) {
464 | curSlide = 0;
465 | } else {
466 | curSlide++;
467 | }
468 |
469 | goToSlide(curSlide);
470 | activateDot(curSlide);
471 | };
472 |
473 | const prevSlide = function () {
474 | if (curSlide === 0) {
475 | curSlide = maxSlide - 1;
476 | } else {
477 | curSlide--;
478 | }
479 | goToSlide(curSlide);
480 | activateDot(curSlide);
481 | };
482 |
483 | const init = function () {
484 | goToSlide(0);
485 | createDots();
486 |
487 | activateDot(0);
488 | };
489 | init();
490 |
491 | // Event handlers
492 | btnRight.addEventListener('click', nextSlide);
493 | btnLeft.addEventListener('click', prevSlide);
494 |
495 | document.addEventListener('keydown', function (e) {
496 | if (e.key === 'ArrowLeft') prevSlide();
497 | e.key === 'ArrowRight' && nextSlide();
498 | });
499 |
500 | dotContainer.addEventListener('click', function (e) {
501 | if (e.target.classList.contains('dots__dot')) {
502 | const { slide } = e.target.dataset;
503 | goToSlide(slide);
504 | activateDot(slide);
505 | }
506 | });
507 | };
508 | slider();
509 | ```
510 |
511 | ## Lifecycle DOM Events
512 | ```js
513 | ///////////////////////////////////////
514 | // Lifecycle DOM Events
515 | document.addEventListener('DOMContentLoaded', function (e) {
516 | console.log('HTML parsed and DOM tree built!', e);
517 | });
518 |
519 | window.addEventListener('load', function (e) {
520 | console.log('Page fully loaded', e);
521 | });
522 |
523 | window.addEventListener('beforeunload', function (e) {
524 | e.preventDefault();
525 | console.log(e);
526 | e.returnValue = '';
527 | });
528 | ```
529 |
530 | ## Efficient Script Loading: defer and async
531 | **DEFER AND ASYNC SCRIPT LOADING**
532 | ![[12. Advanced DOM and Events-1663584302643.jpeg]]
533 |
534 | **REGULAR VS. ASYNC VS. DEFER**
535 | ![[12. Advanced DOM and Events-1663584339910.jpeg]]
536 | - Because defer will guarantee the correct order of execution. Now, for third party scripts, where the order does not matter, for example, an analytics software like Google Analytics, or an ad script, or something like that, then in this case, you should totally use async.
537 | - So if you need to support all browsers, then you need to put your script tag at the end of the body in and not in the head.
538 |
539 |
540 |
--------------------------------------------------------------------------------
/01. JavaScript Fundamentals Part 1.md:
--------------------------------------------------------------------------------
1 | # 1. JavaScript Fundamentals Part 1
2 | ---
3 |
4 | ## 1. Hello World
5 | ```js
6 | console.log("Hello World!")
7 | ```
8 |
9 | ## 2. A brief introduction to Javascript
10 |
11 | _JavaScript_ was initially created to “make web pages alive”.
12 |
13 | The programs in this language are called _scripts_. They can be written right in a web page’s HTML and run automatically as the page loads.
14 |
15 | Scripts are provided and executed as plain text. They don’t need special preparation or compilation to run.
16 |
17 | ## 3. Linking a JavaScript File
18 |
19 | ```js
20 | let js = "amazing";
21 | console.log(40 + 8 + 23 - 10);
22 | ```
23 |
24 |
25 | ## 4. Values and Variables
26 |
27 | ```js
28 | console.log("xoraus");
29 | console.log(23);
30 |
31 | let firstName = "Matilda";
32 |
33 | console.log(firstName);
34 | console.log(firstName);
35 | console.log(firstName);
36 | ```
37 |
38 | 5. ## Variable name conventions
39 |
40 | ```js
41 | let xoraus_matilda = "JM";
42 | let $function = 27;
43 |
44 | let person = "xoraus";
45 | let PI = 3.1415;
46 |
47 | let myFirstJob = "Coder";
48 | let myCurrentJob = "Teacher";
49 |
50 | let job1 = "programmer";
51 | let job2 = "teacher";
52 |
53 | console.log(myFirstJob);
54 | ```
55 |
56 | ## 6. Data Types
57 |
58 | ```js
59 | let javascriptIsFun = true;
60 | console.log(javascriptIsFun);
61 |
62 | console.log(typeof true);
63 | console.log(typeof javascriptIsFun);
64 | console.log(typeof 23);
65 | console.log(typeof 'xoraus');
66 |
67 | javascriptIsFun = 'YES!';
68 | console.log(typeof javascriptIsFun);
69 |
70 | let year;
71 |
72 | console.log(year);
73 | console.log(typeof year);
74 |
75 | year = 1991;
76 |
77 | console.log(typeof year);
78 | console.log(typeof null);
79 |
80 | let, const and var // us let when you're sure that the vaule will change in future
81 |
82 | // let is block scoped
83 | // VAR is function-scoped
84 |
85 | let age = 30;
86 | age = 31; // here let (age) is mutable
87 |
88 | const birthYear = 1991; // it is immutable
89 | birthYear = 1990;
90 |
91 | const job; // this will throw an error;
92 | var job = 'programmer'; // used in legacy codebases
93 |
94 | job = 'teacher'
95 |
96 |
97 | lastName = 'Ahmed';
98 | console.log(lastName);
99 | ```
100 |
101 | ## 7. Basic Operators
102 |
103 | ###### Math operators
104 |
105 | ```js
106 | const now = 2037;
107 | const ageXoraus = now - 1991;
108 | const ageSarah = now - 2018;
109 |
110 | console.log(ageXoraus, ageSarah);
111 | console.log(ageXoraus * 2, ageXoraus 10, 2 ** 3);
112 |
113 | // 2 ** 3 means 2 to the power of 3 = 2 * 2 * 2
114 |
115 | const firstName = 'xoraus';
116 | const lastName = 'Ahmed';
117 |
118 | console.log(firstName + ' ' + lastName);
119 | ```
120 | ###### Assignment operators
121 |
122 | ```js
123 | let x = 10 + 5; // output: 15
124 |
125 | x += 10; // x = x + 10 - Output: 25
126 |
127 | x *= 4; // x = x * 4 - Output: 100
128 |
129 | x++; // x = x + 1
130 | x--; // x = x - 1
131 | x--;
132 |
133 | console.log(x);
134 | ```
135 |
136 | ###### Comparison operators
137 |
138 | ```js
139 | console.log(ageXoraus > ageSarah); // >, <, >=, <=
140 | console.log(ageSarah >= 18); // Output: true
141 |
142 | const isFullAge = ageSarah >= 18;
143 |
144 | console.log(now - 1991 > now - 2018);
145 | ```
146 |
147 | ## 8. Operator Precedence
148 |
149 | ```js
150 | const now = 2037;
151 | const ageXoraus = now - 1991;
152 | const ageSarah = now - 2018;
153 |
154 | console.log(now - 1991 > now - 2018);
155 |
156 | let x, y;
157 |
158 | x = y = 25 - 10 - 5; // Output: x = y = 10, x = 10 - Assignment works from right to left
159 |
160 | console.log(x, y);
161 |
162 | const averageAge = (ageXoraus + ageSarah) 2;
163 |
164 | console.log(ageXoraus, ageSarah, averageAge);
165 | ```
166 |
167 | ## 9. Coding Challenge ##1
168 |
169 | Mark and John are trying to compare their BMI (Body Mass Index), which is calculated using the formula: BMI = mass / height ** 2 = mass / (height * height). (mass in kg and height in meter).
170 |
171 | 1. Store Mark's and John's mass and height in variables
172 | 2. Calculate both their BMIs using the formula (you can even implement both versions)
173 | 3. Create a boolean variable 'markHigherBMI' containing information about whether Mark has a higher BMI than John.
174 |
175 | - TEST DATA 1: Marks weights 78 kg and is 1.69 m tall. John weights 92 kg and is 1.95 m tall.
176 | - TEST DATA 2: Marks weights 95 kg and is 1.88 m tall. John weights 85 kg and is 1.76 m tall.
177 |
178 | **My Solution**
179 | ```js
180 | const markMass = 78;
181 | const markHeight = 1.69;
182 |
183 | const johnMass = 92;
184 | const johnHeight = 1.95;
185 |
186 | function calculateBMI(mass, height) {
187 | let BMI;
188 | BMI = mass / height ** 2;
189 | return BMI
190 | }
191 |
192 | const markBMI = calculateBMI(markMass,markHeight);
193 | const johnBMI = calculateBMI(johnMass, johnHeight);
194 | const markHigherBMI = markBMI > johnBMI
195 | console.log(markBMI)
196 | console.log(johnBMI)
197 | console.log(markHigherBMI)
198 | ```
199 |
200 | **Solution by xoraus**
201 |
202 | ```js
203 | const massMark = 78;
204 | const heightMark = 1.69;
205 |
206 | const massJohn = 92;
207 | const heightJohn = 1.95;
208 |
209 | const massMark = 95;
210 | const heightMark = 1.88;
211 |
212 | const massJohn = 85;
213 | const heightJohn = 1.76;
214 |
215 | const BMIMark = massMark heightMark ** 2;
216 | const BMIJohn = massJohn (heightJohn * heightJohn);
217 |
218 | const markHigherBMI = BMIMark > BMIJohn;
219 |
220 | console.log(BMIMark, BMIJohn, markHigherBMI);
221 | ```
222 |
223 | ## 10. Strings and Template Literals
224 |
225 | ```js
226 | const firstName = 'xoraus';
227 | const job = 'teacher';
228 |
229 | const birthYear = 1991;
230 | const year = 2037;
231 |
232 | const xoraus = "I'm " + firstName + ', a ' + (year - birthYear) + ' year old ' + job + '!'; // concept of type coercion
233 |
234 | console.log(xoraus);
235 |
236 | const xorausNew = `I'm ${firstName}, a ${year - birthYear} year old ${job}!`; // one of most used ES6 Feature :)
237 |
238 | console.log(xorausNew);
239 |
240 | console.log(`Just a regular string...`);
241 |
242 | console.log('String with \n\
243 | multiple \n\
244 | lines');
245 |
246 | console.log(`String
247 | multiple
248 | lines`);
249 | ```
250 |
251 | ## 11. Taking Decisions: if else Statements
252 |
253 | ```js
254 | const age = 15;
255 | if (age >= 18) {
256 | console.log('Sarah can start driving license 🚗');
257 | } else {
258 | const yearsLeft = 18 - age;
259 | console.log(`Sarah is too young. Wait another ${yearsLeft} years :)`);
260 | }
261 |
262 | const birthYear = 2012;
263 |
264 | let century;
265 | if (birthYear <= 2000) {
266 | century = 20;
267 | } else {
268 | century = 21;
269 | }
270 | console.log(century);
271 | ```
272 |
273 | ## 12. Coding Challenge ##2
274 |
275 | Use the BMI example from Challenge ##1, and the code you already wrote, and improve it:
276 |
277 | 1. Print a nice output to the console, saying who has the higher BMI. The message can be either "Mark's BMI is higher than John's!" or "John's BMI is higher than Mark's!"
278 | 2. Use a template literal to include the BMI values in the outputs. Example: "Mark's BMI (28.3) is higher than John's (23.9)!"
279 |
280 | **My Solution**
281 |
282 | ```js
283 | const markMass = 78;
284 | const markHeight = 1.69;
285 |
286 | const johnMass = 92;
287 | const johnHeight = 1.95;
288 |
289 | function calculateBMI(mass, height) {
290 | let BMI;
291 | BMI = mass / height ** 2;
292 | return BMI
293 | }
294 |
295 | const markBMI = calculateBMI(markMass,markHeight);
296 | const johnBMI = calculateBMI(johnMass, johnHeight);
297 |
298 | // console.log(`BMI of Mark is ${markBMI}`)
299 | // console.log(`BMI of John is ${johnBMI}`)
300 | // console.log(`Does Mark has higher BMI - ${markHigherBMI}`)
301 |
302 | if (markBMI > johnBMI) {
303 | console.log(`Mark's BMI (${markBMI}) is higher than John's (${johnBMI})!`)
304 | } else {
305 | console.log(`John's BMI (${johnBMI}) is higher than Marks's (${markBMI})!`)
306 | }
307 | ```
308 |
309 | **Another Solution**
310 |
311 | ```js
312 | const massMark = 78;
313 | const heightMark = 1.69;
314 |
315 | const massJohn = 92;
316 | const heightJohn = 1.95;
317 |
318 |
319 | const massMark = 95;
320 | const heightMark = 1.88;
321 |
322 | const massJohn = 85;
323 | const heightJohn = 1.76;
324 |
325 | const BMIMark = massMark heightMark ** 2;
326 | const BMIJohn = massJohn (heightJohn * heightJohn);
327 |
328 | console.log(BMIMark, BMIJohn);
329 |
330 | if (BMIMark > BMIJohn) {
331 | console.log(`Mark's BMI (${BMIMark}) is higher than John's (${BMIJohn})!`)
332 | } else {
333 | console.log(`John's BMI (${BMIJohn}) is higher than Marks's (${BMIMark})!`)
334 | }
335 | ```
336 |
337 | ## 13. Type Conversion and Coercion
338 | ```js
339 | // type conversion - type conversion is when we manuallyconvert from one type to another.
340 |
341 | const inputYear = '1991';
342 |
343 | console.log(Number(inputYear), inputYear);
344 | console.log(Number(inputYear) + 18);
345 |
346 | console.log(Number('xoraus')); // Outuput: NaN (Not a Number - it actually means invalid number)
347 | console.log(typeof NaN); // output: number
348 |
349 | console.log(String(23), 23); // String(23) is a string; 23 is a number
350 |
351 | // type coercion - type coercion is when JavaScript automatically converts types behind the scenes for us.
352 | // So basically, type coercion happens whenever an operator is dealing with two values that have different types.
353 |
354 |
355 | console.log('I am ' + 23 + ' years old'); // output: I am 23 years old. Since Javascript has type coercion, the number will be automatically be converted into string.
356 | console.log('23' - '10' - 3); // output: Here the strings are converted to numbers because of (- minus) operator.
357 | console.log('23' * '2'); // strings are converted to numbers
358 | console.log('23' / '2'); // strings are converted to numbers
359 |
360 | let n = '1' + 1; // String - '11'
361 | n = n - 1; // String 11 will be converted to number 11 then 11 - 1 = 10
362 |
363 | console.log(n); // 10
364 |
365 | console.log(2+3+4+'5') // output: 95 as string ; 9 + '5' → 95
366 | console.log('10'-'4'-'3'-2 +'5') // output: 15 as string ; 1 + '5' → 15
367 |
368 | ```
369 |
370 | ## 14. Truthy and Falsy Values
371 |
372 | ```js
373 | // In javascript there are 5 falsy values: 0, '', undefined, null, NaN
374 | console.log(Boolean(0)); // output: false
375 | console.log(Boolean(undefined)); // output: false
376 | console.log(Boolean('Jonas')); // output: true
377 | console.log(Boolean({})); // output: true
378 | console.log(Boolean('')); // output: false
379 |
380 | const money = 100;
381 | if (money) {
382 | console.log("Don't spend it all ;)");
383 | } else {
384 | console.log('You should get a job!');
385 | }
386 |
387 | let height = 0;
388 | if (height) {
389 | console.log('YAY! Height is defined');
390 | } else {
391 | console.log('Height is UNDEFINED'); // this will be the ouput because 0 is a falsy value. But this is a bug because we have defined height as 0. We can fix this using logical operators.
392 | }
393 | ```
394 | So in practice, the conversion to boolean is always implicit, not explicit, or in other words is always typed coercion that JavaScript does automatically behind the scenes.
395 |
396 | But when exactly does JavaScript do type coercion to booleans? Well, it happens in two scenarios. First, when using logical operators, and Second in logical context, like for example, in the condition of an if else statement.
397 |
398 | ## 15. Equality Operators: == vs. ===
399 |
400 | ```js
401 | const age = '18';
402 | if (age === 18) console.log('You just became an adult :D (strict)'); // output: true (strict equality doesn't perform type coercion)
403 | if (age == 18) console.log('You just became an adult :D (loose)'); // Lose equality does the type coercion therefore output: true (the string '18' will be converted to number before checking)
404 |
405 | const favourite = Number(prompt("What's your favourite number?"));
406 | console.log(favourite);
407 | console.log(typeof favourite);
408 |
409 | if (favourite === 23) { // 22 === 23 -> FALSE
410 | console.log('Cool! 23 is an amzaing number!')
411 | } else if (favourite === 7) {
412 | console.log('7 is also a cool number')
413 | } else if (favourite === 9) {
414 | console.log('9 is also a cool number')
415 | } else {
416 | console.log('Number is not 23 or 7 or 9')
417 | }
418 |
419 | if (favourite !== 23) console.log('Why not 23?');
420 | ```
421 | So as a general rule for clean code, avoid the loose equality operator as much as you can. So when comparing values, always use strict equality with the three equal signs,
422 |
423 | ## 16. Logical Operators
424 |
425 | ```js
426 | const hasDriversLicense = true; // A
427 | const hasGoodVision = true; // B
428 |
429 | console.log(hasDriversLicense && hasGoodVision); // output: true
430 | console.log(hasDriversLicense || hasGoodVision); // output: true
431 | console.log(!hasDriversLicense); // output: false
432 |
433 | // if (hasDriversLicense && hasGoodVision) {
434 | // console.log('Sarah is able to drive!');
435 | // } else {
436 | // console.log('Someone else should drive...');
437 | // }
438 |
439 | const isTired = false; // C
440 | console.log(hasDriversLicense && hasGoodVision && isTired); output: false
441 |
442 | if (hasDriversLicense && hasGoodVision && !isTired) {
443 | console.log('Sarah is able to drive!');
444 | } else {
445 | console.log('Someone else should drive...');
446 | }
447 | // output: Sarah is able to drive!
448 | ```
449 |
450 | The NOT operator actually has proceedings over the OR and AND operators.
451 |
452 | ## 17. Coding Challenge ##3
453 |
454 | There are two gymnastics teams, Dolphins and Koalas. They compete against each other 3 times. The winner with the highest average score wins the a trophy!
455 | 1. Calculate the average score for each team, using the test data below
456 | 2. Compare the team's average scores to determine the winner of the competition, and print it to the console. Don't forget that there can be a draw, so test for that as well (draw means they have the same average score).
457 | 3. BONUS 1: Include a requirement for a minimum score of 100. With this rule, a team only wins if it has a higher score than the other team, and the same time a score of at least 100 points. HINT: Use a logical operator to test for minimum score, as well as multiple else-if blocks 😉
458 | 4. BONUS 2: Minimum score also applies to a draw! So a draw only happens when both teams have the same score and both have a score greater or equal 100 points. Otherwise, no team wins the trophy.
459 |
460 | TEST DATA: Dolphins score 96, 108 and 89. Koalas score 88, 91 and 110
461 | TEST DATA BONUS 1: Dolphins score 97, 112 and 101. Koalas score 109, 95 and 123
462 | TEST DATA BONUS 2: Dolphins score 97, 112 and 101. Koalas score 109, 95 and 106
463 |
464 | **My Solution**
465 |
466 | ```js
467 | const scoreDolphins = (96 + 108 + 89) / 3;
468 | const scoreKoalas = (88 + 91 + 110) / 3;
469 |
470 | console.log(scoreDolphins, scoreKoalas);
471 |
472 | if (scoreDolphins > scoreKoalas) {
473 | console.log('Dolphins win the trophy 🏆');
474 | } else if (scoreKoalas > scoreDolphins) {
475 | console.log('Koalas win the trophy 🏆');
476 | } else if (scoreDolphins === scoreKoalas) {
477 | console.log('Both win the trophy!');
478 | }
479 | ```
480 |
481 | BONUS 1
482 |
483 | ```js
484 | const scoreDolphins = (97 + 112 + 80) 3;
485 | const scoreKoalas = (109 + 95 + 50) 3;
486 |
487 | console.log(scoreDolphins, scoreKoalas);
488 |
489 | if (scoreDolphins > scoreKoalas && scoreDolphins >= 100) {
490 | console.log('Dolphins win the trophy 🏆');
491 | } else if (scoreKoalas > scoreDolphins && scoreKoalas >= 100) {
492 | console.log('Koalas win the trophy 🏆');
493 | } else if (scoreDolphins === scoreKoalas && scoreDolphins >= 100 && scoreKoalas >= 100) {
494 | console.log('Both win the trophy!');
495 | } else {
496 | console.log('No one wins the trophy 😭');
497 | }
498 | ```
499 |
500 | ## 18. The switch Statement
501 | ```js
502 | const day = 'friday';
503 |
504 | switch (day) {
505 | case 'monday': // day === 'monday'
506 | console.log('Plan course structure');
507 | console.log('Go to coding meetup');
508 | break;
509 | case 'tuesday':
510 | console.log('Prepare theory videos');
511 | break;
512 | case 'wednesday':
513 | case 'thursday':
514 | console.log('Write code examples');
515 | break;
516 | case 'friday':
517 | console.log('Record videos');
518 | break;
519 | case 'saturday':
520 | case 'sunday':
521 | console.log('Enjoy the weekend :D');
522 | break;
523 | default:
524 | console.log('Not a valid day!');
525 | }
526 |
527 | if (day === 'monday') {
528 | console.log('Plan course structure');
529 | console.log('Go to coding meetup');
530 | } else if (day === 'tuesday') {
531 | console.log('Prepare theory videos');
532 | } else if (day === 'wednesday' || day === 'thursday') {
533 | console.log('Write code examples');
534 | } else if (day === 'friday') {
535 | console.log('Record videos');
536 | } else if (day === 'saturday' || day === 'sunday') {
537 | console.log('Enjoy the weekend :D');
538 | } else {
539 | console.log('Not a valid day!');
540 | }
541 | ```
542 |
543 | ## 19. Statements and Expressions
544 | ```js
545 | 3 + 4 // output: 7 - an expression
546 | 1991
547 | true && false && !false
548 |
549 | // Following is a Statement
550 | if (50 > 10) {
551 | const str = '50 is bigger';
552 | }
553 |
554 | const me = 'Xoraus';
555 | console.log(`I'm ${2050 - 1997} years old ${me}`); // In javascript literals we can use expressions but not statements.
556 | ```
557 |
558 | - an expression is a piece of code that produces a value.
559 | - statements are like full sentences that translate our actions.
560 |
561 | ## 20. The Conditional (Ternary) Operator
562 | ```js
563 | const age = 23;
564 | // age >= 18 ? console.log('I like to drink wine 🍷') : console.log('I like to drink water 💧');
565 |
566 | const drink = age >= 18 ? 'Sharbat-e-Jaam 🍷' : 'water 💧';
567 | console.log(drink);
568 |
569 | let drink2;
570 | if (age >= 18) {
571 | drink2 = 'Sharbat-e-Jaam 🍷';
572 | } else {
573 | drink2 = 'water 💧';
574 | }
575 | console.log(drink2);
576 |
577 | console.log(`I like to drink ${age >= 18 ? 'Sharbat-e-Jaam 🍷' : 'water 💧'}`);
578 | ```
579 |
580 | ## 21. Coding Challenge ##4
581 |
582 | Steven wants to build a very simple tip calculator for whenever he goes eating in a restaurant. In his country, it's usual to tip 15% if the bill value is between 50 and 300. If the value is different, the tip is 20%.
583 | 1. Your task is to calculate the tip, depending on the bill value. Create a variable called 'tip' for this. It's not allowed to use an if else statement 😅 (If it's easier for you, you can start with an if else statement, and then try to convert it to a ternary operator!)
584 | 2. Print a string to the console containing the bill value, the tip, and the final value (bill + tip). Example: 'The bill was 275, the tip was 41.25, and the total value 316.25'
585 |
586 | TEST DATA: Test for bill values 275, 40 and 430
587 |
588 | HINT: To calculate 20% of a value, simply multiply it by 20/100 = 0.2
589 | HINT: Value X is between 50 and 300, if it's >= 50 && <= 300 😉
590 |
591 | ```js
592 | const bill = 275;
593 | const tip = (bill >= 50 && bill <= 300) ? 0.15 * bill : 0.20 * bill;
594 |
595 | const totalValue = bill + tip;
596 |
597 | console.log(`The bill was ${bill}, the tip was ${tip}, and the total value ${bill + tip}`);
598 | ```
599 |
600 |
--------------------------------------------------------------------------------
/07. How JavaScript Works Behind the Scenes.md:
--------------------------------------------------------------------------------
1 | # 7. How JavaScript Works Behind the Scenes
2 |
3 | ## An High-Level Overview of JavaScript
4 |
5 | ### What is Javascript?
6 | Javascript Is a High-Level, Object-Oriented, Multi-Paradigm Programming Language.
7 |
8 | 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
9 |
10 | #### High-level
11 | ![[7. How JavaScript Works Behind the Scenes-1661664454597.jpeg]]
12 | #### Garbage-collected
13 | ![[7. How JavaScript Works Behind the Scenes-1661664479453.jpeg]]
14 | #### Interpreted or just-in-time compiled
15 | ![[7. How JavaScript Works Behind the Scenes-1661664501052.jpeg]]
16 | #### Multi-paradigm
17 | ![[7. How JavaScript Works Behind the Scenes-1661664573105.jpeg]]
18 | #### Prototype-based object-oriented
19 | ![[7. How JavaScript Works Behind the Scenes-1661664597254.jpeg]]
20 | #### First-class functions
21 | ![[7. How JavaScript Works Behind the Scenes-1661664636245.jpeg]]
22 |
23 | #### Dynamic
24 | ![[7. How JavaScript Works Behind the Scenes-1661664652377.jpeg]]
25 |
26 | #### Single-threaded & Non-blocking event loop
27 | ![[7. How JavaScript Works Behind the Scenes-1661664673207.jpeg]]
28 |
29 | ## The JavaScript Engine and Runtime
30 |
31 | ### What is Javascript Engine
32 | ![[7. How JavaScript Works Behind the Scenes-1661670799106.jpeg]]
33 | - So a JavaScript engine is simply a computer program that executes JavaScript code.
34 | - Now every browser has its own JavaScript engine but probably the most well known engine is Google's V-Eight.
35 | - So any JavaScript engine always contains a call stack and a heap. The call stack is where our code is actually executed using something called execution contexts. Then the heap is an unstructured memory pool which stores all the objects that our application needs.
36 | ### Compilation vs Interpretation
37 |
38 | ![[7. How JavaScript Works Behind the Scenes-1661670833417.jpeg]]
39 |
40 |
41 | ### Just in Time Compilation of Javascript
42 | ![[7. How JavaScript Works Behind the Scenes-1661670875764.jpeg]]
43 |
44 | ### Runtime in Browser
45 | ![[7. How JavaScript Works Behind the Scenes-1661670745908.jpeg]]
46 |
47 | ### Runtime in NodeJs
48 |
49 | ![[7. How JavaScript Works Behind the Scenes-1661670767221.jpeg]]
50 |
51 | ## Execution Contexts and The Call Stack
52 | ### What is an Execution Context?
53 | ![[7. How JavaScript Works Behind the Scenes-1661673934102.jpeg]]
54 |
55 | But now what exactly is an execution context?
56 | Well, an execution context is an abstract concept.
57 | But I define it basically as an environment in which a piece of JavaScript is executed. a It's like a box that stores all the necessary information for some code to be executed.
58 | Such as local variables or arguments passed into a function.
59 | So, JavaScript code always runs inside an execution context.
60 |
61 | 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.
62 |
63 | ### Execution Context in Detail
64 | ![[7. How JavaScript Works Behind the Scenes-1661673969086.jpeg]]
65 |
66 | Because remember each function gets its own execution context
67 | as soon as the function is called. So basically all the variables that are somehow declared inside a function, will end up in its variable environment. However, a function can also access variables outside of the function and this works because of something called the scope chain.
68 |
69 | Scope chain basically consists of references to variables that are located outside of the current function. And to keep track of the scope chain, it is stored in each execution context.
70 |
71 | Execution contexts belonging to arrow functions, do not get their own arguments keyword, nor do they get the this keyword, okay? So, basically arrow functions don't have the arguments object and the this keyword. Instead, they can use the arguments object, and the this keyword from their closest regular function parent.
72 |
73 | ### The Call Stack
74 | ![[7. How JavaScript Works Behind the Scenes-1661674004333.jpeg]]
75 |
76 | JavaScript has only one thread of execution. And so it can only do one thing at a time.
77 |
78 | So like to use the analogy of the call stack being like a map for the JavaScript engine.
79 | Because the call stack ensures that the order of execution never gets lost.
80 | ## Scope and The Scope Chain
81 | ### Scope Concepts
82 | - **Scoping**: How our program's variables are organized and accessed. "Where do variables live?" or "Where can we access a certain variable, and where not?",
83 | - **Lexical scoping**: Scoping is controlled by placement of functions and blocks in the code;
84 | - **Scope**: Space or environment in which a certain variable is declared (variable environment in case of functions). There is global scope, function scope, and block scope;
85 | - **Scope of a variable**: Region of our code where a certain variable can be accessed.
86 |
87 | ### The 3 types of Scopes
88 | ![[7. How JavaScript Works Behind the Scenes-1661745363013.jpeg]]
89 |
90 | ### Scope Chain vs. The Call Stack
91 | ![[7. How JavaScript Works Behind the Scenes-1661745401792.jpeg]]
92 |
93 | ### Summary
94 | - Scoping asks the question "Where do variables live?" or "Where can we access a certain variable, and where not?";
95 | - There are 3 types of scope in JavaScript: the global scope, scopes defined by functions, and scopes defined by blocks;
96 | - Only let and const variables are block-scoped. Variables declared with var end up in the closest function scope;
97 | - In JavaScript, we have lexical scoping, so the rules of where we can access variables are based on exactly where in the code functions and blocks are written;
98 | - Every scope always has access to all the variables from all its outer scopes. This is the scope chain!
99 | - When a variable is not in the current scope, the engine looks up in the scope chain until it finds the variable it's looking for. This is called variable lookup;
100 | - The scope chain is a one-way street: a scope will never, ever have access to the variables of an inner scope;
101 | - The scope chain in a certain scope is equal to adding together all the variable environments of the all parent scopes;
102 | - The scope chain has nothing to do with the order in which functions were called. It does not affect the scope chain at all!
103 |
104 | ## Scoping in Practice
105 | ```js
106 | function calcAge(birthYear) {
107 | const age = 2037 - birthYear;
108 |
109 | function printAge() {
110 | let output = `${firstName}, you are ${age}, born in ${birthYear}`;
111 | console.log(output); // output: firstName = Jonas → coming from global scope.
112 |
113 | // Block Scope
114 | if (birthYear >= 1981 && birthYear <= 1996) {
115 | var millenial = true;
116 | // Creating NEW variable with same name as outer scope's variable
117 | const firstName = 'Steven'; // firstName already declared in Global Scope
118 |
119 | // Reasssigning outer scope's variable
120 | output = 'NEW OUTPUT!';
121 |
122 | const str = `Oh, and you're a millenial, ${firstName}`; // output: Steven - This happens because Javascript tries to look the variable name in the current scope.
123 | console.log(str); // output: Oh, and you're a millenial, xoraus
124 |
125 | function add(a, b) {
126 | return a + b; // The scope of this add function is only where it is defined
127 | }
128 | }
129 | console.log(str); // output: // str is not defined
130 | console.log(millenial); //output: true
131 | console.log(add(2, 3)); // output: add is not defined. (in strict mode)
132 | console.log(output); //output: NEW OUTPUT
133 | }
134 | printAge();
135 |
136 | return age;
137 | }
138 |
139 | const firstName = 'xoraus';
140 | calcAge(1997); // output: xoraus you are 50, born in 1997
141 | console.log(age); // output: age is not defined
142 | printAge(); // output: printAge is not defined
143 | ```
144 |
145 | - const and let variables are block scoped.
146 | - so variables declared with the var keyword are function scoped. So they simply ignore the block, because they are not block scoped at all. They're just function scoped.
147 | - that the scope of a variable is the entire region of the code in which the variable is accessible.
148 | - Functions are block scoped in **Strict Mode**
149 | - So the scope chain isn't necessary at all, if the variable that we're looking for is already in the current scope.
150 |
151 | ## Variable Environment: Hoisting and The TDZ
152 | ![[7. How JavaScript Works Behind the Scenes-1661750446465.jpeg]]
153 | - So we learned that an execution context always contains three parts. A variable environment, the scope chain in the in current context, and the this keyword.
154 | - So in JavaScript we have a mechanism called hoisting. And hoisting basically make some types of variables accessible, or let's say usable in the code before they are actually declared in the code. Now, many people simply define hoisting by saying that variables are magically lifted off moved to the top of their scope for example, to the top of a function. And that is actually what hoisting looks like on the surface.
155 | - Instead, behind the scenes the code is basically scanned for variable declarations before it is executed. So this happens during the so-called creation phase of the execution context that we talked about before. Then for each variable that is found is in the code, a new property is created in a variable environment object. And that's how hoisting really works. Now, hoisting does not work the same for all variable types.
156 | - This means that a function expression or arrow function created with var is hoisted to _undefined_. But if created with **let** or **const**, it's not usable before it's declared in a code because of the Temporal Dead Zone so again, just like normal variables. And is this is actually the reason that we cannot use function expressions before we write them in the code, unlike function declarations.
157 |
158 | ![[7. How JavaScript Works Behind the Scenes-1661751743808.jpeg]]
159 |
160 | - So to recap, basically each and every let and const variable get their own Temporal Dead Zone that starts at the beginning of the scope until the line where it is defined.
161 | And the variable is only safe to use after the TDZ, so the Temporal Dead Zone.
162 | - Alright, now what is actually the need for JavaScript to have a Temporal Dead Zone? Well, the main reason that the TDZ was introduced in ES6 is that the behavior I described before makes it way easier to avoid and catch errors. Because using a variable that is set to undefined before it's actually declared can cause serious bugs which might be hard to find.
163 | - So accessing variables before declaration is bad practice and should be avoided. And the best way to avoid it iS by simply getting an error.
164 | - A second and smaller reason why the TDZ exists is to make const variables actually work the way they are supposed to. So as you know, we can't reassign const variables. it So it will not be possible to set them to undefined first and then assign their real value later.
165 | - Now, if hoisting creates so many problems, why does it exist in the first place? I get this question all the time. And so let's quickly talk about that here. So the creator of JavaScript basically implemented hoisting so that we can use function declarations before we use them. Because this is essential for some programming techniques, such as mutual recursion. Some people also think that it makes code a lot more readable. Now, the fact that it also works for var declarations is because that was the only way hoisting could be implemented at the time. So the hoisting of var variables is basically just a byproduct of hoisting functions.
166 | ### Hoisting Example
167 | ```js
168 | Take a look at this code
169 |
170 | test();
171 |
172 | function test() {
173 | console.log("Hello");
174 | }
175 |
176 | // We can call the test() function before it was declared in code. That's the hoisting in practice.
177 |
178 | // Why it's possible?
179 |
180 | // JavaScript engine scans the code before executing it and creates a property for each variable or function in the code. For normal variables, it assigns an undefined value, and for functions it assigns a reference to that function in memory. That's why we can call a function, but if we try to access a variable, we will get undefined.
181 |
182 | function scope() {
183 | console.log(var1); // undefined
184 | console.log(va1); // undefined
185 |
186 | var var1 = "Hello";
187 | var var2 = "Hi";
188 | }
189 | Let me know if you have any questions
190 | ```
191 | ## Hoisting and TDZ in Practice
192 | ```js
193 | // # Hoisting with Variables
194 | console.log(me); // output: Undefined (because of Var)
195 | // console.log(job); // output: Cannot access 'job' before initialization, the origin of this error is that the jobn variable is still in temporal dead zone
196 | // console.log(year); // output: Cannot access 'year' before initialization
197 |
198 | var me = 'Jonas';
199 | let job = 'teacher';
200 | const year = 1991;
201 |
202 | // Functions
203 | console.log(addDecl(2, 3)); //output: 5
204 | // console.log(addExpr(2, 3)); // output: Cannot access 'addExpr' before initialization
205 | console.log(addArrow); // output: Undefined
206 | // console.log(addArrow(2, 3));
207 |
208 | function addDecl(a, b) {
209 | return a + b;
210 | }
211 |
212 | const addExpr = function (a, b) {
213 | return a + b;
214 | };
215 |
216 | var addArrow = (a, b) => a + b;
217 |
218 | // Example
219 | console.log(undefined);
220 | if (!numProducts) deleteShoppingCart(); // output: All products deleted because at this moment the numProducts is 'Undefined' because it is declared with 'var' and that's because how the var works with hosting
221 |
222 | var numProducts = 10;
223 |
224 | function deleteShoppingCart() {
225 | console.log('All products deleted!');
226 | }
227 |
228 | var x = 1; // we get a property of x = 1. we cannot find y or z here in this object and that's because they were declared with let or const
229 | let y = 2;
230 | const z = 3;
231 |
232 | console.log(x === window.x); // output: true
233 | console.log(y === window.y); // output: false
234 | console.log(z === window.z); // output: false
235 | ```
236 |
237 | - variables declared with var, will create a property on the global window object.
238 | And that can have some implications in some cases.
239 |
240 | ## The this Keyword
241 | ![[7. How JavaScript Works Behind the Scenes-1661754569885.jpeg]]
242 |
243 | - Instead, if you use 'the this variable' in an arrow function, it will simply be the this keyword of the surrounding function. So of the parent function and in technical terms, this is called the 'lexical this keyword,' because it simply gets picked up from the outer lexical scope of the arrow function.
244 | - It's also important to know what the, this keyword is not. So this will never point to the function in which we are using it. Also, the this keyword will never point to the variable environment of the function. And these are two pretty common misconceptions
245 |
246 | ## The this Keyword in Practice
247 | ```js
248 | 'use strict'
249 | // The this Keyword in Practice
250 | console.log(this); // output: Window Object
251 |
252 | const calcAge = function (birthYear) {
253 | console.log(2037 - birthYear);
254 | console.log(this); // output: Undefined (in case of strict mode)
255 | };
256 | calcAge(1991);
257 |
258 | const calcAgeArrow = birthYear => {
259 | console.log(2037 - birthYear);
260 | console.log(this); // output: Window (because the arrow function doesn't get the this function So instead the arrow function simply uses the lexical this keyword, which means that it uses the disc keyword of its parent function or of its parents scope.
261 | };
262 | calcAgeArrow(1980);
263 |
264 | const jonas = {
265 | year: 1991,
266 | calcAge: function () {
267 | console.log(this); // output: jonas object - The reason that the this keyword will point to Jonas in this case is because jonas was the object calling that method
268 | console.log(2037 - this.year); // output: 46
269 | },
270 | };
271 | jonas.calcAge();
272 |
273 | const matilda = {
274 | year: 2017,
275 | };
276 |
277 | matilda.calcAge = jonas.calcAge; // method borrowing
278 | matilda.calcAge(); // output: 20 (this will point to year: 2017) - So even though the method is written here inside of the Jonas object the this keyword will still point to Matilda. If it is Matilda, who calls the method.
279 |
280 | const f = jonas.calcAge;
281 | f(); // Cannot read property 'year' of undefined
282 | ```
283 | ## Regular Functions vs. Arrow Functions
284 | ```js
285 | // Regular Functions vs. Arrow Functions
286 | // var firstName = 'Matilda';
287 |
288 | const jonas = {
289 | firstName: 'Jonas',
290 | year: 1991,
291 | calcAge: function () {
292 | // console.log(this);
293 | console.log(2037 - this.year);
294 |
295 | // Solution 1
296 | // const self = this; // self or that
297 | // const isMillenial = function () {
298 | // console.log(self);
299 | // console.log(self.year >= 1981 && self.year <= 1996);
300 | // };
301 |
302 | // Solution 2
303 | const isMillenial = () => {
304 | console.log(this);
305 | console.log(this.year >= 1981 && this.year <= 1996);
306 | };
307 | isMillenial();
308 | },
309 |
310 | greet: () => {
311 | console.log(this); //output: Window
312 | console.log(`Hey ${this.firstName}`); //output: Matilda
313 | },
314 | };
315 | jonas.greet(); // output: Hey Undefined - (using the this keyword from it's parent's this keyword)
316 | jonas.calcAge();
317 |
318 | // arguments keyword
319 | const addExpr = function (a, b) {
320 | console.log(arguments);
321 | return a + b;
322 | };
323 | addExpr(2, 5);
324 | addExpr(2, 5, 8, 12);
325 |
326 | var addArrow = (a, b) => {
327 | console.log(arguments);
328 | return a + b;
329 | };
330 | addArrow(2, 5, 8);
331 |
332 | ```
333 | - Now, just like the this keyword, the arguments keyword is only available in regular functions.
334 | ## Primitives vs. Objects (Primitive vs. Reference Types)
335 | ![[7. How JavaScript Works Behind the Scenes-1661760447942.jpeg]]
336 | ```js
337 | let age = 30;
338 | let oldAge = age;
339 | age = 31;
340 | console.log(age);
341 | console.log(oldAge);
342 |
343 | const me = {
344 | name: 'Jonas',
345 | age: 30,
346 | };
347 | const friend = me;
348 | friend.age = 27;
349 | console.log('Friend:', friend);
350 | console.log('Me', me);
351 | ```
352 | ![[7. How JavaScript Works Behind the Scenes-1661765088951.jpeg]]
353 |
354 | ## Primitives vs. Objects in Practice
355 | ```js
356 | // Primitive types
357 | let lastName = 'Williams';
358 | let oldLastName = lastName;
359 | lastName = 'Davis';
360 | console.log(lastName, oldLastName); // output: Davis Williams
361 |
362 | // Reference types
363 | const jessica = {
364 | firstName: 'Jessica',
365 | lastName: 'Williams',
366 | age: 27,
367 | };
368 | const marriedJessica = jessica;
369 | marriedJessica.lastName = 'Davis';
370 | console.log('Before marriage:', jessica); // output: Before marriage: { firstName: 'Jessica', lastName: 'Davis', age: 27 }
371 | console.log('After marriage: ', marriedJessica); // output: After marriage: { firstName: 'Jessica', lastName: 'Davis', age: 27 }
372 |
373 | // Copying objects
374 | const jessica2 = {
375 | firstName: 'Jessica',
376 | lastName: 'Williams',
377 | age: 27,
378 | family: ['Alice', 'Bob'],
379 | };
380 |
381 | const jessicaCopy = Object.assign({}, jessica2);
382 | jessicaCopy.lastName = 'Davis';
383 |
384 | jessicaCopy.family.push('Mary');
385 | jessicaCopy.family.push('John');
386 |
387 | console.log('Before marriage:', jessica2); // family: [ 'Alice', 'Bob', 'Mary', 'John' ]
388 | console.log('After marriage: ', jessicaCopy); // amily: [ 'Alice', 'Bob', 'Mary', 'John' ]
389 | ```
390 | - And that's why we say that this object.assign only creates a shallow copy
391 | - However, the family object is a deeply nested object. And so therefore, object.assign did not really, behind the scenes, copy it to the new object.
392 | - Now, a deep clone is what we would need here. Usually, we do something like this using an external library, for example, like LoDash, and this library has a ton of helpful tools and one is of them is for deep cloning.
393 |
394 | #### Later in course
395 | - Prototypal Inheritance Object Oriented Programming (00P) With JavaScript
396 | - Event Loop Asynchronous JavaScript: Promises, Async/Await and AJAX
397 | - How the DOM Really Works Advanced DOM and Events
--------------------------------------------------------------------------------
/02. JavaScript Fundamentals Part 2.md:
--------------------------------------------------------------------------------
1 | # 2. JavaScript Fundamentals Part 2
2 | ---
3 | ## 32. Activating Strict Mode
4 | ```js
5 | 'use strict'; // to activate strict mode to
6 | ```
7 | - Always put strict mode in the beginning of the file
8 | - It makes it easier for developer to avoid accidental errors.
9 |
10 | 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.
11 | ```js
12 | 'use strict';
13 |
14 | let hasDriversLicense = false;
15 | const passTest = true;
16 |
17 | if (passTest) hasDriversLicense = true; // if in hasDriver(s)License s is missing the code will behave unexpectedly
18 | if (hasDriversLicense) console.log('I can drive :D');
19 |
20 | // const interface = 'Audio'; // Uncaught SyntaxError: Missing initializer in const declaration
21 | // const private = 534; // Uncaught SyntaxError: Missing initializer in const declaration
22 | ```
23 |
24 | ## 33. Functions
25 | ```js
26 | function logger() {
27 | console.log('My name is xoraus');
28 | }
29 |
30 | // calling / running / invoking function
31 | logger(); // output: My name is xoraus
32 | logger(); // output: My name is xoraus
33 | logger(); // output: My name is xoraus
34 |
35 | function fruitProcessor(apples, oranges) {
36 | const juice = `Juice with ${apples} apples and ${oranges} oranges.`;
37 | return juice;
38 | }
39 |
40 | const appleJuice = fruitProcessor(10, 5);
41 | console.log(appleJuice);1
42 |
43 | const appleOrangeJuice = fruitProcessor(4, 8);
44 | console.log(appleOrangeJuice);
45 |
46 | const num = Number('6833');
47 | ```
48 |
49 | Clean Code - **DRY Principle** that is _Don't Repeat Yourself_
50 |
51 | ## 34. Function Declarations vs. Expressions
52 |
53 | ```js
54 | // Function declaration
55 | function calcAge1(birthYeah) {
56 | return 2047 - birthYeah;
57 | }
58 | const age1 = calcAge1(1997);
59 | // Function expression
60 | const calcAge2 = function (birthYeah) { // Anonymous Functions - this function is an expression. Expressions produce value.
61 | return 2047 - birthYeah;
62 | }
63 | const age2 = calcAge2(1997);
64 |
65 | console.log(age1, age2);
66 | ```
67 | - The parameter is a kind of placeholder in the function and the argument is then the actual value that we use to fill in that placeholder that is the parameter.
68 | - In Javascript functions are just values
69 |
70 | ## 35. Arrow Functions
71 | ```js
72 | const calcAge3 = birthYeah => 2047 - birthYeah;
73 | const age3 = calcAge3(1997);
74 | console.log(age3);
75 |
76 | const yearsUntilRetirement = (birthYeah, firstName) => {
77 | const age = 2047 - birthYeah;
78 | const retirement = 65 - age;
79 | // return retirement;
80 | return `${firstName} retires in ${retirement} years`;
81 | }
82 |
83 | console.log(yearsUntilRetirement(1997, 'xoraus')); console.log(yearsUntilRetirement(2005, 'ahmed'));
84 | ```
85 |
86 | ## 36. Functions Calling Other Functions
87 | ```js
88 | function cutFruitPieces(fruit) {
89 | return fruit * 4;
90 | }
91 |
92 | function fruitProcessor(apples, oranges) {
93 | const applePieces = cutFruitPieces(apples);
94 | const orangePieces = cutFruitPieces(oranges);
95 |
96 | const juice = `Juice with ${applePieces} piece of apple and ${orangePieces} pieces of orange.`;
97 | return juice;
98 | }
99 | console.log(fruitProcessor(2, 3));
100 | ```
101 |
102 | - Arrow functions do not get the **this Keyword**
103 |
104 | ## 37. Reviewing Functions
105 | ```js
106 | const calcAge = function (birthYeah) {
107 | return 2047 - birthYeah;
108 | }
109 |
110 | const yearsUntilRetirement = function (birthYeah, firstName) {
111 | const age = calcAge(birthYeah);
112 | const retirement = 65 - age;
113 |
114 | if (retirement > 0) {
115 | console.log(`${firstName} retires in ${retirement} years`);
116 | return retirement;
117 | } else {
118 | console.log(`${firstName} has already retired 🎉`);
119 | return -1;
120 | }
121 | }
122 |
123 | console.log(yearsUntilRetirement(1997, 'xoraus'));
124 | console.log(yearsUntilRetirement(1980, 'Jordan'));
125 | ```
126 | ![[2. JavaScript Fundamentals Part 2-20220824162950.png]]
127 |
128 | ## 38. Coding Challenge 1
129 | Back to the two gymnastics teams, the Dolphins and the Koalas! There is a new gymnastics discipline, which works differently. Each team competes 3 times, and then the average of the 3 scores is calculated (so one average score per team). A team ONLY wins if it has at least DOUBLE the average score of the other team. Otherwise, no team wins!
130 |
131 | 1. Create an arrow function 'calcAverage' to calculate the average of 3 scores
132 | 2. Use the function to calculate the average for both teams
133 | 3. Create a function 'checkWinner' that takes the average score of each team as parameters ('avgDolhins' and 'avgKoalas'), and then logs the winner to the console, together with the victory points, according to the rule above. Example: "Koalas win (30 vs. 13)".
134 | 4. Use the 'checkWinner' function to determine the winner for both DATA 1 and DATA 2.
135 | 5. Ignore draws this time.
136 |
137 | TEST DATA 1: Dolphins score 44, 23 and 71. Koalas score 65, 54 and 49
138 | TEST DATA 2: Dolphins score 85, 54 and 41. Koalas score 23, 34 and 27
139 |
140 | HINT: To calculate average of 3 values, add them all together and divide by 3
141 | HINT: To check if number A is at least double number B, check for A >= 2 * B. Apply this to the team's average scores 😉
142 |
143 | ```js
144 | calcAverage = (scoreA, scoreB, scoreC) => (scoreA, scoreB, scoreC) / 3
145 |
146 | const teamDolphinAvg = Math.floor(calcAverage(85,54,41));
147 | const teamKoalaAvg = Math.floor(calcAverage(23,34,27));
148 |
149 | console.log(teamDolphinAvg,teamKoalaAvg)
150 |
151 | function checkWinner(teamDolphinAvg,teamKoalaAvg) {
152 | if (teamDolphinAvg >= 2 * teamKoalaAvg) {
153 | console.log(`Dolphins win 🏆 ${teamDolphinAvg} vs ${teamKoalaAvg}`)
154 | } else if (teamKoalaAvg >= 2 * teamDolphinAvg) {
155 | console.log(`Koalas win 🏆 ${teamKoalaAvg} vs. ${teamDolphinAvg}`)
156 | } else {
157 | console.log(`No body won :(`)
158 | }
159 | }
160 |
161 | checkWinner(800,351)
162 |
163 | // Test 2
164 | scoreDolphins = calcAverage(85, 54, 41);
165 | scoreKoalas = calcAverage(23, 34, 27);
166 | console.log(scoreDolphins, scoreKoalas);
167 | checkWinner(scoreDolphins, scoreKoalas);
168 |
169 | ```
170 |
171 |
172 | ## 39. Introduction to Arrays
173 | ```js
174 | const friend1 = 'Al-Farabi';
175 | const friend2 = 'Al-Ghazali';
176 | const friend3 = 'Al- Razi';
177 |
178 | const friends = ['Al-Farabi', 'Al-Ghazali', 'Al- Razi'];
179 | console.log(friends);
180 |
181 | const y = new Array(1991, 1984, 2008, 2020);
182 |
183 | console.log(friends[0]); // output: Al-Farabi
184 | console.log(friends[2]); // output: Al- Razi
185 |
186 | console.log(friends.length); // outpt: 3
187 | console.log(friends[friends.length - 1]); // output: Peter
188 |
189 | friends[3] = 'Al-Qalbi';
190 | console.log(friends); // output: Al-Farabi, Al-Ghazali, Al- Razi
191 | // friends = ['Bob', 'Alice']
192 |
193 | const firstName = 'Jordan';
194 | const xoraus = [firstName, 'Ahmed', 2047 - 1997, 'teacher', friends];
195 | console.log(xoraus);
196 | console.log(xoraus.length);
197 |
198 | // Exercise
199 | const calcAge = function (birthYeah) {
200 | return 2047 - birthYeah;
201 | }
202 | const years = [1990, 1967, 2002, 2010, 2018];
203 |
204 | const age1 = calcAge(years[0]);
205 | const age2 = calcAge(years[1]);
206 | const age3 = calcAge(years[years.length - 1]);
207 | console.log(age1, age2, age3);
208 |
209 | const ages = [calcAge(years[0]), calcAge(years[1]), calcAge(years[years.length - 1])];
210 | console.log(ages);
211 | ```
212 |
213 | ## 40. Basic Array Operations (Methods)
214 | ```js
215 | const friends = ['Al-Farabi', 'Al-Ghazali', 'Al- Razi'];
216 | // const friends = ['Michael', 'Steven', 'Peter'];
217 |
218 | // Add elements
219 | const newLength = friends.push('xoraus');
220 | console.log(friends);
221 | console.log(newLength);
222 |
223 | friends.unshift('Jordan');
224 | console.log(friends);
225 |
226 | // Remove elements
227 | friends.pop(); // Last
228 | const popped = friends.pop();
229 | console.log(popped);
230 | console.log(friends);
231 |
232 | friends.shift(); // First
233 | console.log(friends);
234 |
235 | console.log(friends.indexOf('Al-Farabi'));
236 | console.log(friends.indexOf('Al-Ghazali'));
237 |
238 | friends.push(25);
239 | console.log(friends.includes('Al- Razi'));
240 | console.log(friends.includes('Ahmed'));
241 | console.log(friends.includes(25));
242 |
243 | if (friends.includes('Al-Ghazali')) {
244 | console.log('You have a friend called Al-Ghazali');
245 | }
246 | ```
247 |
248 | ## 41. Coding Challenge ##2
249 | Ahmed is still building his tip calculator, using the same rules as before: Tip 15% of the bill if the bill value is between 50 and 300, and if the value is different, the tip is 20%.
250 |
251 | 1. Write a function 'calcTip' that takes any bill value as an input and returns the corresponding tip, calculated based on the rules above (you can check out the code from first tip calculator challenge if you need to). Use the function type you like the most. Test the function using a bill value of 100.
252 | 2. And now let's use arrays! So create an array 'bills' containing the test data below.
253 | 3. Create an array 'tips' containing the tip value for each bill, calculated from the function you created before.
254 | 4. BONUS: Create an array 'total' containing the total values, so the bill + tip.
255 |
256 | TEST DATA: 125, 555 and 44
257 |
258 | HINT: Remember that an array needs a value in each position, and that value can actually be the returned value of a function! So you can just call a function as array values (so don't store the tip values in separate variables first, but right in the new array)
259 |
260 | ```js
261 | const calcTip = function (bill) {
262 | return bill >= 50 && bill <= 300 ? bill * 0.15 : bill * 0.2;
263 | }
264 | // const calcTip = bill => bill >= 50 && bill <= 300 ? bill * 0.15 : bill * 0.2;
265 |
266 | const bills = [125, 555, 44];
267 | const tips = [calcTip(bills[0]), calcTip(bills[1]), calcTip(bills[2])];
268 | const totals = [bills[0] + tips[0], bills[1] + tips[1], bills[2] + tips[2]];
269 |
270 | console.log(bills, tips, totals);
271 | ```
272 |
273 | ## 42. Introduction to Objects
274 | ```js
275 | const xorausArray = [
276 | 'Jordan',
277 | 'Ahmed',
278 | 2027 - 1997,
279 | 'teacher',
280 | ['Ali', 'Khan', 'Sal']
281 | ];
282 |
283 | const xoraus = {
284 | firstName: 'Jordan',
285 | lastName: 'Ahmed',
286 | age: 2027 - 1997,
287 | job: 'teacher',
288 | friends: ['Ali', 'K', 'Sal']
289 | };
290 | ```
291 |
292 | ## 43. Dot vs. Bracket Notation
293 | ```js
294 | const xoraus = {
295 | firstName: 'Jordan',
296 | lastName: 'Ahmed',
297 | age: 2027 - 1997,
298 | job: 'teacher',
299 | friends: ['Plato', 'Aristotle', 'Socrates']
300 | };
301 | console.log(xoraus);
302 |
303 | console.log(xoraus.lastName); // output: Ahmed
304 | console.log(xoraus['lastName']); // output: Ahmed
305 |
306 | const nameKey = 'Name';
307 | console.log(xoraus['first' + nameKey]); // output: Jordan
308 | console.log(xoraus['last' + nameKey]); // output: Ahmed
309 |
310 | // console.log(xoraus.'last' + nameKey) // this will not work
311 |
312 | const interestedIn = prompt('What do you want to know about Jordan? Choose between firstName, lastName, age, job, and friends');
313 |
314 | if (xoraus[interestedIn]) {
315 | console.log(xoraus[interestedIn]);
316 | } else {
317 | console.log('Wrong request! Choose between firstName, lastName, age, job, and friends');
318 | }
319 |
320 | xoraus.location = 'India';
321 | xoraus['twitter'] = '@xoraus';
322 | console.log(xoraus);
323 |
324 | // Challenge
325 | // "Jonas has 3 friends, and his best friend is called Aristotle"
326 | console.log(`${xoraus.firstName} has ${xoraus.friends.length} friends, and his best friend is called ${xoraus.friends[1]}`);
327 |
328 | ```
329 |
330 | - when we need to first compute the property name, then we have to use the bracket notation otherwise use dot notation.
331 | - we get **undefined ** when when we try to access a property on an object that does not exist.
332 |
333 | ## 44. Object Methods
334 | ```js
335 | const xoraus = {
336 | firstName: 'Jordan',
337 | lastName: 'Ahmed',
338 | birthYeah: 1997,
339 | job: 'Programmer',
340 | friends: ['Socrates', 'Plato', 'Aristotle'],
341 | hasDriversLicense: true,
342 |
343 | // calcAge: function (birthYeah) {
344 | // return 2037 - birthYeah;
345 | // }
346 |
347 | // calcAge: function () {
348 | // // console.log(this);
349 | // return 2027 - this.birthYeah;
350 | // }
351 |
352 | calcAge: function () {
353 | this.age = 2027 - this.birthYeah;
354 | return this.age;
355 | },
356 |
357 | getSummary: function () {
358 | return `${this.firstName} is a ${this.calcAge()}-year old ${xoraus.job}, and he has ${this.hasDriversLicense ? 'a' : 'no'} driver's license.`
359 | }
360 | };
361 |
362 | console.log(xoraus.calcAge());
363 |
364 | console.log(xoraus.age);
365 | console.log(xoraus.age);
366 | console.log(xoraus.age);
367 |
368 | // Challenge
369 | // "Jonas is a 30-year old programmer, and he has a driver's license"
370 | console.log(xoraus.getSummary());
371 | ```
372 | - Any function that is attached to an object is called a method.
373 |
374 | ## 45. Coding Challenge ##3
375 | Let's go back to Mark and John comparing their BMIs! This time, let's use objects to implement the calculations! Remember: BMI = mass / height ** 2 = mass / (height * height). (mass in kg and height in meter)
376 |
377 | 1. For each of them, create an object with properties for their full name, mass, and height (Mark Miller and John Smith)
378 | 2. Create a 'calcBMI' method on each object to calculate the BMI (the same method on both objects). Store the BMI value to a property, and also return it from the method.
379 | 3. Log to the console who has the higher BMI, together with the full name and the respective BMI. Example: "John Smith's BMI (28.3) is higher than Mark Miller's (23.9)!"
380 |
381 | TEST DATA: Marks weights 78 kg and is 1.69 m tall. John weights 92 kg and is 1.95 m tall.
382 |
383 | ```js
384 | const mark = {
385 | fullName: 'Mark Miller',
386 | mass: 78,
387 | height: 1.69,
388 | calcBMI: function () {
389 | this.bmi = this.mass / this.height ** 2;
390 | return this.bmi;
391 | }
392 | };
393 |
394 | const john = {
395 | fullName: 'John Smith',
396 | mass: 92,
397 | height: 1.95,
398 | calcBMI: function () {
399 | this.bmi = this.mass / this.height ** 2;
400 | return this.bmi;
401 | }
402 | };
403 |
404 | mark.calcBMI();
405 | john.calcBMI();
406 |
407 | console.log(mark.bmi, john.bmi);
408 |
409 | // "John Smith's BMI (28.3) is higher than Mark Miller's (23.9)!"
410 |
411 | if (mark.bmi > john.bmi) {
412 | console.log(`${mark.fullName}'s BMI (${mark.bmi}) is higher than ${john.fullName}'s BMI (${john.bmi})`)
413 | } else if (john.bmi > mark.bmi) {
414 | console.log(`${john.fullName}'s BMI (${john.bmi}) is higher than ${mark.fullName}'s BMI (${mark.bmi})`)
415 | }
416 |
417 | ```
418 |
419 | ## 46. Iteration: The for Loop
420 | ```js
421 | // console.log('Lifting weights repetition 1 🏋️♀️');
422 | // console.log('Lifting weights repetition 2 🏋️♀️');
423 | // console.log('Lifting weights repetition 3 🏋️♀️');
424 | // console.log('Lifting weights repetition 4 🏋️♀️');
425 | // console.log('Lifting weights repetition 5 🏋️♀️');
426 | // console.log('Lifting weights repetition 6 🏋️♀️');
427 | // console.log('Lifting weights repetition 7 🏋️♀️');
428 | // console.log('Lifting weights repetition 8 🏋️♀️');
429 | // console.log('Lifting weights repetition 9 🏋️♀️');
430 | // console.log('Lifting weights repetition 10 🏋️♀️');
431 |
432 | // for loop keeps running while condition is TRUE
433 | for (let rep = 1; rep <= 30; rep++) {
434 | console.log(`Lifting weights repetition ${rep} 🏋️♀️`);
435 | }
436 | ```
437 |
438 | ## 47. Looping Arrays, Breaking and Continuing
439 | ```js
440 | const jonas = [
441 | 'Jonas',
442 | 'Schmedtmann',
443 | 2037 - 1991,
444 | 'teacher',
445 | ['Michael', 'Peter', 'Steven'],
446 | true
447 | ];
448 | const types = [];
449 |
450 | // console.log(jonas[0])
451 | // console.log(jonas[1])
452 | // ...
453 | // console.log(jonas[4])
454 | // jonas[5] does NOT exist
455 |
456 | for (let i = 0; i < jonas.length; i++) {
457 | // Reading from jonas array
458 | console.log(jonas[i], typeof jonas[i]);
459 |
460 | // Filling types array
461 | // types[i] = typeof jonas[i];
462 | types.push(typeof jonas[i]);
463 | }
464 |
465 | console.log(types);
466 |
467 | const years = [1991, 2007, 1969, 2020];
468 | const ages = [];
469 |
470 | for (let i = 0; i < years.length; i++) {
471 | ages.push(2037 - years[i]);
472 | }
473 | console.log(ages);
474 |
475 | // continue and break
476 | console.log('--- ONLY STRINGS ---')
477 | for (let i = 0; i < jonas.length; i++) {
478 | if (typeof jonas[i] !== 'string') continue;
479 |
480 | console.log(jonas[i], typeof jonas[i]);
481 | }
482 |
483 | console.log('--- BREAK WITH NUMBER ---')
484 | for (let i = 0; i < jonas.length; i++) {
485 | if (typeof jonas[i] === 'number') break;
486 |
487 | console.log(jonas[i], typeof jonas[i]);
488 | }
489 |
490 | ```
491 |
492 | ## 48. Looping Backwards and Loops in Loops
493 | ```js
494 | const jonas = [
495 | 'Jonas',
496 | 'Schmedtmann',
497 | 2037 - 1991,
498 | 'teacher',
499 | ['Michael', 'Peter', 'Steven'],
500 | true
501 | ];
502 |
503 | // 0, 1, ..., 4
504 | // 4, 3, ..., 0
505 |
506 | for (let i = jonas.length - 1; i >= 0; i--) {
507 | console.log(i, jonas[i]);
508 | }
509 |
510 | for (let exercise = 1; exercise < 4; exercise++) {
511 | console.log(`-------- Starting exercise ${exercise}`);
512 |
513 | for (let rep = 1; rep < 6; rep++) {
514 | console.log(`Exercise ${exercise}: Lifting weight repetition ${rep} 🏋️♀️`);
515 | }
516 | }
517 | ```
518 |
519 | ## 49. The while Loop
520 | ```js
521 | for (let rep = 1; rep <= 10; rep++) {
522 | console.log(`Lifting weights repetition ${rep} 🏋️♀️`);
523 | }
524 |
525 | let rep = 1;
526 | while (rep <= 10) {
527 | // console.log(`WHILE: Lifting weights repetition ${rep} 🏋️♀️`);
528 | rep++;
529 | }
530 |
531 | let dice = Math.trunc(Math.random() * 6) + 1;
532 |
533 | while (dice !== 6) {
534 | console.log(`You rolled a ${dice}`);
535 | dice = Math.trunc(Math.random() * 6) + 1;
536 | if (dice === 6) console.log('Loop is about to end...');
537 | }
538 | ```
539 |
540 | ## 50. Coding Challenge ##4
541 |
542 | Let's improve Steven's tip calculator even more, this time using loops!
543 | 1. Create an array 'bills' containing all 10 test bill values
544 | 2. Create empty arrays for the tips and the totals ('tips' and 'totals')
545 | 3. Use the 'calcTip' function we wrote before (no need to repeat) to calculate tips and total values (bill + tip) for every bill value in the bills array. Use a for loop to perform the 10 calculations!
546 |
547 | TEST DATA: 22, 295, 176, 440, 37, 105, 10, 1100, 86 and 52
548 |
549 | HINT: Call calcTip in the loop and use the push method to add values to the tips and totals arrays 😉
550 |
551 | 1. BONUS: Write a function 'calcAverage' which takes an array called 'arr' as an argument. This function calculates the average of all numbers in the given array. This is a DIFFICULT challenge (we haven't done this before)! Here is how to solve it:
552 | 4.1. First, you will need to add up all values in the array. To do the addition, start by creating a variable 'sum' that starts at 0. Then loop over the array using a for loop. In each iteration, add the current value to the 'sum' variable. This way, by the end of the loop, you have all values added together
553 | 4.2. To calculate the average, divide the sum you calculated before by the length of the array (because that's the number of elements)
554 | 4.3. Call the function with the 'totals' array
555 |
556 | ```js
557 | const calcTip = function (bill) {
558 | return bill >= 50 && bill <= 300 ? bill * 0.15 : bill * 0.2;
559 | }
560 | const bills = [22, 295, 176, 440, 37, 105, 10, 1100, 86, 52];
561 | const tips = [];
562 | const totals = [];
563 |
564 | for (let i = 0; i < bills.length; i++) {
565 | const tip = calcTip(bills[i]);
566 | tips.push(tip);
567 | totals.push(tip + bills[i]);
568 | }
569 | console.log(bills, tips, totals);
570 |
571 | const calcAverage = function (arr) {
572 | let sum = 0;
573 | for (let i = 0; i < arr.length; i++) {
574 | // sum = sum + arr[i];
575 | sum += arr[i];
576 | }
577 | return sum / arr.length;
578 | }
579 | console.log(calcAverage([2, 3, 7]));
580 | console.log(calcAverage(totals));
581 | console.log(calcAverage(tips));
582 | ```
--------------------------------------------------------------------------------
/11. Numbers, Dates, Intl and Timers.md:
--------------------------------------------------------------------------------
1 | # 11. Numbers, Dates, Intl and Timers
2 | ---
3 | ## Converting and Checking Numbers
4 | ```js
5 | ///////////////////////////////////////
6 | // Converting and Checking Numbers
7 | console.log(23 === 23.0);
8 |
9 | // Base 10 - 0 to 9. 1/10 = 0.1. 3/10 = 3.3333333
10 | // Binary base 2 - 0 1
11 | console.log(0.1 + 0.2);
12 | console.log(0.1 + 0.2 === 0.3);
13 |
14 | // Conversion
15 | console.log(Number('23'));
16 | console.log(+'23');
17 |
18 | // Parsing
19 | console.log(Number.parseInt('30px', 10));
20 | console.log(Number.parseInt('e23', 10));
21 |
22 | console.log(Number.parseInt(' 2.5rem '));
23 | console.log(Number.parseFloat(' 2.5rem '));
24 |
25 | // console.log(parseFloat(' 2.5rem '));
26 |
27 | // Check if value is NaN
28 | console.log(Number.isNaN(20));
29 | console.log(Number.isNaN('20'));
30 | console.log(Number.isNaN(+'20X'));
31 | console.log(Number.isNaN(23 / 0));
32 |
33 | // Checking if value is number
34 | console.log(Number.isFinite(20));
35 | console.log(Number.isFinite('20'));
36 | console.log(Number.isFinite(+'20X'));
37 | console.log(Number.isFinite(23 / 0));
38 |
39 | console.log(Number.isInteger(23));
40 | console.log(Number.isInteger(23.0));
41 | console.log(Number.isInteger(23 / 0));
42 | ```
43 | - `Number.parseInt()` Number here provides something called "Namespace".
44 |
45 | ## Math and Rounding
46 | ```js
47 | ///////////////////////////////////////
48 | // Math and Rounding
49 | console.log(Math.sqrt(25));
50 | console.log(25 ** (1 / 2));
51 | console.log(8 ** (1 / 3));
52 |
53 | console.log(Math.max(5, 18, 23, 11, 2));
54 | console.log(Math.max(5, 18, '23', 11, 2));
55 | console.log(Math.max(5, 18, '23px', 11, 2));
56 |
57 | console.log(Math.min(5, 18, 23, 11, 2));
58 |
59 | console.log(Math.PI * Number.parseFloat('10px') ** 2);
60 |
61 | console.log(Math.trunc(Math.random() * 6) + 1);
62 |
63 | const randomInt = (min, max) =>
64 | Math.floor(Math.random() * (max - min) + 1) + min;
65 | // 0...1 -> 0...(max - min) -> min...max
66 | // console.log(randomInt(10, 20));
67 |
68 | // Rounding integers
69 | console.log(Math.round(23.3));
70 | console.log(Math.round(23.9));
71 |
72 | console.log(Math.ceil(23.3));
73 | console.log(Math.ceil(23.9));
74 |
75 | console.log(Math.floor(23.3));
76 | console.log(Math.floor('23.9'));
77 |
78 | console.log(Math.trunc(23.3));
79 |
80 | console.log(Math.trunc(-23.3)); // -23
81 | console.log(Math.floor(-23.3)); // -24
82 |
83 | // Rounding decimals
84 | console.log((2.7).toFixed(0));
85 | console.log((2.7).toFixed(3));
86 | console.log((2.345).toFixed(2));
87 | console.log(+(2.345).toFixed(2));
88 | ```
89 | - max function here actually does type coercion.
90 | - `floor()` is little bit better than `trunc()` because it works in all cases no matter if we are dealing with positive or negative numbers.
91 | - Primitives actually don't have methods. And so behind the scenes, JavaScript will do boxing. Boxing is to basically transform this to a number object, then call the method on that object. And then once the operation is finished it will convert it back to a primitive.
92 |
93 | ## The Remainder Operator
94 | ```js
95 | ///////////////////////////////////////
96 | // The Remainder Operator
97 | console.log(5 % 2);
98 | console.log(5 / 2); // 5 = 2 * 2 + 1
99 |
100 | console.log(8 % 3);
101 | console.log(8 / 3); // 8 = 2 * 3 + 2
102 |
103 | console.log(6 % 2);
104 | console.log(6 / 2);
105 |
106 | console.log(7 % 2);
107 | console.log(7 / 2);
108 |
109 | const isEven = n => n % 2 === 0;
110 | console.log(isEven(8));
111 | console.log(isEven(23));
112 | console.log(isEven(514));
113 |
114 | labelBalance.addEventListener('click', function () {
115 | [...document.querySelectorAll('.movements__row')].forEach(function (row, i) {
116 | // 0, 2, 4, 6
117 | if (i % 2 === 0) row.style.backgroundColor = 'orangered';
118 | // 0, 3, 6, 9
119 | if (i % 3 === 0) row.style.backgroundColor = 'blue';
120 | });
121 | });
122 | ```
123 |
124 | ## Numeric Separators - ES2021
125 | ```js
126 | ///////////////////////////////////////
127 | // Numeric Separators
128 |
129 | // 287,460,000,000
130 | const diameter = 287_460_000_000;
131 | console.log(diameter);
132 |
133 | const price = 345_99;
134 | console.log(price);
135 |
136 | const transferFee1 = 15_00;
137 | const transferFee2 = 1_500;
138 |
139 | const PI = 3.1415;
140 | console.log(PI);
141 |
142 | console.log(Number('230_000'));
143 | console.log(parseInt('230_000'));
144 |
145 | ```
146 |
147 | ## Working with BigInt - ES2020
148 | - The `BigInt` is a new primitive type that can represent whole numbers bigger than `253 - 1`, which is the largest number Javascript can reliably represent with the `number` type.
149 | - Append `n` to a literal integer or use `BigInt()` function to create a `bigint`.
150 | ```js
151 | ///////////////////////////////////////
152 | // Working with BigInt
153 | console.log(2 ** 53 - 1);
154 | console.log(Number.MAX_SAFE_INTEGER);
155 | console.log(2 ** 53 + 1);
156 | console.log(2 ** 53 + 2);
157 | console.log(2 ** 53 + 3);
158 | console.log(2 ** 53 + 4);
159 |
160 | console.log(4838430248342043823408394839483204n);
161 | console.log(BigInt(48384302));
162 |
163 | // Operations
164 | console.log(10000n + 10000n);
165 | console.log(36286372637263726376237263726372632n * 10000000n);
166 | // console.log(Math.sqrt(16n));
167 |
168 | const huge = 20289830237283728378237n;
169 | const num = 23;
170 | console.log(huge * BigInt(num));
171 |
172 | // Exceptions
173 | console.log(20n > 15);
174 | console.log(20n === 20);
175 | console.log(typeof 20n);
176 | console.log(20n == '20');
177 |
178 | console.log(huge + ' is REALLY big!!!');
179 |
180 | // Divisions
181 | console.log(11n / 3n);
182 | console.log(10 / 3);
183 | ```
184 |
185 | ## Creating Dates
186 | ```js
187 | ///////////////////////////////////////
188 | // Creating Dates
189 |
190 | // Create a date
191 |
192 | const now = new Date();
193 | console.log(now);
194 |
195 | console.log(new Date('Aug 02 2020 18:05:41'));
196 | console.log(new Date('December 24, 2015'));
197 | console.log(new Date(account1.movementsDates[0]));
198 |
199 | console.log(new Date(2037, 10, 19, 15, 23, 5));
200 | console.log(new Date(2037, 10, 31));
201 |
202 | console.log(new Date(0));
203 | console.log(new Date(3 * 24 * 60 * 60 * 1000));
204 |
205 |
206 | // Working with dates
207 | const future = new Date(2037, 10, 19, 15, 23);
208 | console.log(future);
209 | console.log(future.getFullYear());
210 | console.log(future.getMonth());
211 | console.log(future.getDate());
212 | console.log(future.getDay());
213 | console.log(future.getHours());
214 | console.log(future.getMinutes());
215 | console.log(future.getSeconds());
216 | console.log(future.toISOString());
217 | console.log(future.getTime());
218 |
219 | console.log(new Date(2142256980000));
220 |
221 | console.log(Date.now());
222 |
223 | future.setFullYear(2040);
224 | console.log(future);
225 | ```
226 |
227 | ## Operations With Dates
228 | ```js
229 | ///////////////////////////////////////
230 | // Operations With Dates
231 | const future = new Date(2037, 10, 19, 15, 23);
232 | console.log(+future);
233 |
234 | const calcDaysPassed = (date1, date2) =>
235 | Math.abs(date2 - date1) / (1000 * 60 * 60 * 24);
236 |
237 | const days1 = calcDaysPassed(new Date(2037, 3, 4), new Date(2037, 3, 14));
238 | console.log(days1);
239 |
240 |
241 | ///////////////////////////////////////
242 | // Internationalizing Numbers (Intl)
243 | const num = 3884764.23;
244 |
245 | const options = {
246 | style: 'currency',
247 | unit: 'celsius',
248 | currency: 'EUR',
249 | // useGrouping: false,
250 | };
251 |
252 | console.log('US: ', new Intl.NumberFormat('en-US', options).format(num));
253 | console.log('Germany: ', new Intl.NumberFormat('de-DE', options).format(num));
254 | console.log('Syria: ', new Intl.NumberFormat('ar-SY', options).format(num));
255 | console.log(
256 | navigator.language,
257 | new Intl.NumberFormat(navigator.language, options).format(num)
258 | );
259 | ```
260 |
261 | ## Internationalizing Numbers (Intl)
262 | ```js
263 | ///////////////////////////////////////
264 | // Internationalizing Numbers (Intl)
265 | const num = 3884764.23;
266 |
267 | const options = {
268 | style: 'currency',
269 | unit: 'celsius',
270 | currency: 'EUR',
271 | // useGrouping: false,
272 | };
273 |
274 | console.log('US: ', new Intl.NumberFormat('en-US', options).format(num));
275 | console.log('Germany: ', new Intl.NumberFormat('de-DE', options).format(num));
276 | console.log('Syria: ', new Intl.NumberFormat('ar-SY', options).format(num));
277 | console.log(
278 | navigator.language,
279 | new Intl.NumberFormat(navigator.language, options).format(num)
280 | );
281 |
282 | ```
283 |
284 | ## Timers
285 | ```js
286 | ///////////////////////////////////////
287 | // Timers
288 |
289 | // setTimeout
290 | const ingredients = ['olives', 'spinach'];
291 | const pizzaTimer = setTimeout(
292 | (ing1, ing2) => console.log(`Here is your pizza with ${ing1} and ${ing2} 🍕`),
293 | 3000,
294 | ...ingredients
295 | );
296 | console.log('Waiting...');
297 |
298 | if (ingredients.includes('spinach')) clearTimeout(pizzaTimer);
299 |
300 | // setInterval
301 | setInterval(function () {
302 | const now = new Date();
303 | console.log(now);
304 | }, 1000);
305 | ```
306 |
307 | ## Project Bankist Code
308 | ```js
309 | 'use strict';
310 |
311 | /////////////////////////////////////////////////
312 | /////////////////////////////////////////////////
313 | // BANKIST APP
314 |
315 | /////////////////////////////////////////////////
316 | // Data
317 |
318 | // DIFFERENT DATA! Contains movement dates, currency and locale
319 |
320 | const account1 = {
321 | owner: 'Jonas Schmedtmann',
322 | movements: [200, 455.23, -306.5, 25000, -642.21, -133.9, 79.97, 1300],
323 | interestRate: 1.2, // %
324 | pin: 1111,
325 |
326 | movementsDates: [
327 | '2019-11-18T21:31:17.178Z',
328 | '2019-12-23T07:42:02.383Z',
329 | '2020-01-28T09:15:04.904Z',
330 | '2020-04-01T10:17:24.185Z',
331 | '2020-05-08T14:11:59.604Z',
332 | '2020-07-26T17:01:17.194Z',
333 | '2020-07-28T23:36:17.929Z',
334 | '2020-08-01T10:51:36.790Z',
335 | ],
336 | currency: 'EUR',
337 | locale: 'pt-PT', // de-DE
338 | };
339 |
340 | const account2 = {
341 | owner: 'Jessica Davis',
342 | movements: [5000, 3400, -150, -790, -3210, -1000, 8500, -30],
343 | interestRate: 1.5,
344 | pin: 2222,
345 |
346 | movementsDates: [
347 | '2019-11-01T13:15:33.035Z',
348 | '2019-11-30T09:48:16.867Z',
349 | '2019-12-25T06:04:23.907Z',
350 | '2020-01-25T14:18:46.235Z',
351 | '2020-02-05T16:33:06.386Z',
352 | '2020-04-10T14:43:26.374Z',
353 | '2020-06-25T18:49:59.371Z',
354 | '2020-07-26T12:01:20.894Z',
355 | ],
356 | currency: 'USD',
357 | locale: 'en-US',
358 | };
359 |
360 | const accounts = [account1, account2];
361 |
362 | /////////////////////////////////////////////////
363 | // Elements
364 | const labelWelcome = document.querySelector('.welcome');
365 | const labelDate = document.querySelector('.date');
366 | const labelBalance = document.querySelector('.balance__value');
367 | const labelSumIn = document.querySelector('.summary__value--in');
368 | const labelSumOut = document.querySelector('.summary__value--out');
369 | const labelSumInterest = document.querySelector('.summary__value--interest');
370 | const labelTimer = document.querySelector('.timer');
371 |
372 | const containerApp = document.querySelector('.app');
373 | const containerMovements = document.querySelector('.movements');
374 |
375 | const btnLogin = document.querySelector('.login__btn');
376 | const btnTransfer = document.querySelector('.form__btn--transfer');
377 | const btnLoan = document.querySelector('.form__btn--loan');
378 | const btnClose = document.querySelector('.form__btn--close');
379 | const btnSort = document.querySelector('.btn--sort');
380 |
381 | const inputLoginUsername = document.querySelector('.login__input--user');
382 | const inputLoginPin = document.querySelector('.login__input--pin');
383 | const inputTransferTo = document.querySelector('.form__input--to');
384 | const inputTransferAmount = document.querySelector('.form__input--amount');
385 | const inputLoanAmount = document.querySelector('.form__input--loan-amount');
386 | const inputCloseUsername = document.querySelector('.form__input--user');
387 | const inputClosePin = document.querySelector('.form__input--pin');
388 |
389 | /////////////////////////////////////////////////
390 | // Functions
391 |
392 | const formatMovementDate = function (date, locale) {
393 | const calcDaysPassed = (date1, date2) =>
394 | Math.round(Math.abs(date2 - date1) / (1000 * 60 * 60 * 24));
395 |
396 | const daysPassed = calcDaysPassed(new Date(), date);
397 | console.log(daysPassed);
398 |
399 | if (daysPassed === 0) return 'Today';
400 | if (daysPassed === 1) return 'Yesterday';
401 | if (daysPassed <= 7) return `${daysPassed} days ago`;
402 |
403 | // const day = `${date.getDate()}`.padStart(2, 0);
404 | // const month = `${date.getMonth() + 1}`.padStart(2, 0);
405 | // const year = date.getFullYear();
406 | // return `${day}/${month}/${year}`;
407 | return new Intl.DateTimeFormat(locale).format(date);
408 | };
409 |
410 | const formatCur = function (value, locale, currency) {
411 | return new Intl.NumberFormat(locale, {
412 | style: 'currency',
413 | currency: currency,
414 | }).format(value);
415 | };
416 |
417 | const displayMovements = function (acc, sort = false) {
418 | containerMovements.innerHTML = '';
419 |
420 | const movs = sort
421 | ? acc.movements.slice().sort((a, b) => a - b)
422 | : acc.movements;
423 |
424 | movs.forEach(function (mov, i) {
425 | const type = mov > 0 ? 'deposit' : 'withdrawal';
426 |
427 | const date = new Date(acc.movementsDates[i]);
428 | const displayDate = formatMovementDate(date, acc.locale);
429 |
430 | const formattedMov = formatCur(mov, acc.locale, acc.currency);
431 |
432 | const html = `
433 | (Between 1 and 20)
266 | 267 |💯 Score: 20
277 |278 | 🥇 Highscore: 0 279 |
280 |43
663 |Current
665 |0
666 |24
671 |Current
673 |0
674 |
678 |
679 |
680 |
681 |