├── .gitignore ├── 01_basics.md ├── 02_functions.md ├── 03_bits.md ├── 04_dom.md ├── 05_events.md ├── 06_SeriousPractice.md ├── 07_LogicAndFlowControl.md ├── 08_DataTypes.md ├── 09_GettingLoopy.md ├── 10_HarderPracticeExercises.md ├── 11_Prototype.md ├── 12_AdvancedFlowControl.md ├── 13_AjaxAndFetchingData.md ├── 14_ESModulesAndStructuringLargerApps.md ├── img ├── ModulesStructure.png ├── ObkectKeysValuesEntries.png ├── ajaxData.png ├── ajaxFetch.png ├── arrayFrom.png ├── bind.png ├── bind2.png ├── bubblingCapture.png ├── call,apply.png ├── callbackQueue.png ├── coercion.png ├── eventLoopCallbackHell.png ├── exportDefault.png ├── function-definition.jpg ├── importDefault.png ├── namedExport.png ├── namedImport.png ├── newKeyword.png ├── prototype.png ├── reduceOrderTotals.png ├── renameImports.png ├── thisKeyword.png └── truthyFalsy.png ├── readme.md └── tableOfContent.md /.gitignore: -------------------------------------------------------------------------------- 1 | #Files: 2 | .DS_store -------------------------------------------------------------------------------- /01_basics.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # **Module #1 - The Basics** 4 | 5 | --- 6 | 7 | 8 | 9 | ## **LOADING AND RUNNING JAVASCRIPT** 10 | 11 | add ` 17 | 18 | ``` 19 | 20 |
21 | 22 | 23 | 24 | ## **VARIABLES** 25 | 26 | - **var** (_value can be updated_) 27 | - **let** (_value can be updated_) 28 | - **const** (_value can't be updated_) 29 | 30 | ```js 31 | var name = "Wes"; 32 | let age = 100; 33 | const cool = true; 34 | ``` 35 | 36 | 37 | 38 | ## **TYPE OF VARIABLES:** 39 | 40 | 41 | 42 | - ### String: 43 | 44 | represent letter, paragraphs, phases, etc. Can be declared with quotes, double-quotes or back ticks. 45 | 46 | ```js 47 | const name = "Wes"; 48 | const middle = "topher"; 49 | const last = `Bos`; 50 | ``` 51 | 52 | sentence 53 | with "\ esc", quotes, single quotes and backtick option: 54 | sentence = She´s so "cool" 55 | 56 | ```js 57 | const sentence = 'she´s so "cool"'; 58 | const sentence = 'she´s so "cool"'; 59 | const sentence = `She's so "cool"`; 60 | ``` 61 | 62 | concatenation & interpolation 63 | 64 | ```js 65 | const hello = `hello my name is ${variable_name} nice yo meet you. I'm ${ 66 | 30 + 5 67 | } years old`; 68 | ``` 69 | 70 | 71 | 72 | - ### Numbers: 73 | 74 | Numbers on Javascript includes float, integers, etc ... 75 | there are all the basic operation (addition, subtraction, multiplication and division). 76 | 77 | ```js 78 | let a = 10 + 10; // addition 79 | let b = 20 - 10; // subtraction 80 | let c = 10 * 10; // multiplication 81 | let d = 100 / 10; // division 82 | let e = 1000 % 3; // modulo 83 | ``` 84 | 85 | Javascript have helper methods like: 86 | 87 | ```js 88 | Math.round(20.5); //result 21, round number up or down 89 | Math.floor(20.2); //result 20, will give you the lower 90 | Math.ceil(20.9); // result 21, will give you the upper 91 | Math.random(); // gives random number between 0 and 1 92 | ``` 93 | 94 | NaN is an other number, that means _Not a number_ 95 | 96 | ```js 97 | let a = 10 / "dog"; 98 | console.log(a); 99 | 100 | // result: NaN 101 | ``` 102 | 103 | 104 | 105 | - ### Objects 106 | 107 | Everything in javascript is an object, are use for collections of data or functionality. 108 | 109 | ```js 110 | const person { 111 | firstName = 'Cesar', 112 | lastName = 'Gomez', 113 | age = '35' 114 | }; 115 | ``` 116 | 117 | order doesn't matter in objects, we can access to the properties, the easiest way is: 118 | 119 | ```js 120 | person.firstName; // access to the first name properties 121 | person.lastName; // access to the last name properties 122 | person.age; // access to the age properties 123 | ``` 124 | 125 | 126 | 127 | - ### Null and Undefined 128 | 129 | **Undefined:** comes when you try to access toa variable that has been created, but not set. 130 | 131 | ```js 132 | let dog; 133 | console.log(dog); //result should be undefined 134 | ``` 135 | 136 | **Null:** is a value of nothing 137 | 138 | ```js 139 | let somethingNull = null; 140 | ``` 141 | 142 | 143 | 144 | - ### Booleans and equality 145 | 146 | **Booleans:** is a value of true or false, can be manually set or calculate: 147 | 148 | ```js 149 | //manually set 150 | let isDrawing = true; 151 | 152 | //calculate 153 | const age = 18; 154 | const ofAge = age > 19; 155 | console.log(ofAge); // result should be false 156 | ``` 157 | 158 | **Equality:** we have: 159 | 160 | - = (setting or updating a variable) 161 | - == (it compares the value but not the type of ) 162 | - === (compares the value and type of ) 163 | 164 | ```js 165 | // = 166 | let dog = "Sharon"; 167 | 168 | // == 169 | "10" == 10; //result is true, it compares the value but not the type of (both values are 10) 170 | 171 | // === 172 | "10" === 10; // result is false, compares value and type of (first one is string, second one is number) 173 | ``` 174 | 175 |
176 | 177 | --- 178 | 179 | back to [Table of Content](tableOfContent.md) 180 | next [Functions](02_functions.md) 181 | -------------------------------------------------------------------------------- /02_functions.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # **Module #2 - Functions** 4 | 5 | --- 6 | 7 | 8 | 9 | ## **BUILD FUNCTIONS** 10 | 11 | Functions can do anything, they´re group together set of instructions, often taking in values, doing some work and then returning a new value or set of values. 12 | 13 | Functions are create or defined and then they later can be call. 14 | 15 | the function calculate bill will calculate what the bill would be regarding how much the tip was and how much the tax is. 16 | 17 | ```js 18 | // create or defined a function 19 | function calculateBill() { 20 | const total = 100 * 1.13; 21 | return total; 22 | } 23 | 24 | // call a function 25 | calculateBill(); 26 | ``` 27 | 28 | the total is not available out of the function, because we need to capture the return value of the function into a variable: 29 | 30 | ```js 31 | const myTotal = calculateBill(); 32 | ``` 33 | 34 |
35 | 36 | 37 | 38 | ## **PARAMETERS AND ARGUMENTS** 39 | 40 | ![parameters and arguments](./img/function-definition.jpg) 41 | 42 | function using parameters and arguments 43 | 44 | ```js 45 | function calculateBill(billAmount, taxRate) { 46 | const total = billAmount * (1 + taxRate); 47 | return total; 48 | } 49 | 50 | const myTotal = calculateBill(500, 0.3); 51 | ``` 52 | 53 | you can pass expressions to a function 54 | 55 | ```js 56 | const myTotal = calculateBill(20 + 20 + 30 + 20, 0.3); 57 | ``` 58 | 59 | and also you can pass functions as arguments 60 | 61 | ```js 62 | function doctorize(firstName) { 63 | return `Dr. ${name}`; 64 | } 65 | 66 | function yell(name) { 67 | return `Hey ${name.toUpperCase()}`; 68 | } 69 | 70 | yell(doctorize("Cesar")); 71 | // return "Hey DR. CESAR" 72 | ``` 73 | 74 | you can set default values to the parameters: 75 | 76 | > taxRate = 0.13 77 | > tipRate = 0.15 78 | 79 | if no one pass the parameter taxRate and tipRate for calculateBill function it will take by default the 0.13 for tax rate and 0.15 for tip rate 80 | 81 | ```js 82 | function calculateBill(billAmount, taxRate = 0.13, tipRate = 0.15) { 83 | const total = billAmount + billAmount * taxRate + billAmount * tipRate; 84 | return total; 85 | } 86 | 87 | calculateBill(100); 88 | ``` 89 | 90 | if you want to use only one of the default values, like tipRate but not taxRate 91 | 92 | ```js 93 | calculateBill(100, undefined, 0.2); 94 | ``` 95 | 96 | the undefined will fallback to the default value of 0.13 for taxRate 97 | 98 |
99 | 100 | 101 | 102 | ## **DIFFERENT WAYS TO DECLARE FUNCTIONS** 103 | 104 | Javascript functions are values in themselves that can be stored into variables or can be passed into other functions. 105 | 106 | there are different ways to declare functions 107 | 108 | 109 | 110 | - ### Regular function declaration 111 | 112 | ```js 113 | function doctorize(firstName){ 114 | return `Dr. ${fistName}; 115 | } 116 | ``` 117 | 118 | 119 | 120 | - ### Anonymous function 121 | 122 | is a function without name 123 | 124 | ```js 125 | function (firstName){ 126 | return `Dr. ${fistName}; 127 | } 128 | ``` 129 | 130 | 131 | 132 | - ### Function Expression 133 | 134 | is an anonymous function stored into a variable 135 | 136 | ```js 137 | const doctorize = function (firstName){ 138 | return `Dr. ${fistName}; 139 | } 140 | ``` 141 | 142 | the difference between regular function declaration and function expression is how they operate on the hoisting 143 | 144 | 145 | 146 | - ### Arrow Function 147 | 148 | are anon functions, always need to be sticky into a variable. 149 | 150 | ```js 151 | //regular function: 152 | function inchToCM(inches) { 153 | const cm = inches * 2.54; 154 | return cm; 155 | } 156 | 157 | //arrow function: 158 | const inchesToCm = (inches) => inches * 2.54; 159 | ``` 160 | 161 | other example: 162 | 163 | ```js 164 | //regular function: 165 | function add(a, b = 3) { 166 | const total = a + b; 167 | return total; 168 | } 169 | 170 | //arrow function 171 | const add = (a, b = 3) => a + b; 172 | ``` 173 | 174 | you cannot delete the _()_ on _(a, b=3)_ because there are more than one parameter. 175 | 176 | 177 | 178 | - ### Returning an Object 179 | 180 | ```js 181 | //regular function: 182 | function makeABaby(fisrName, lastName) { 183 | const baby = { 184 | name: `${first} ${last}`, 185 | age: 0, 186 | }; 187 | return baby; 188 | } 189 | 190 | //arrow function: 191 | const makeABaby = (first, last) => { 192 | return (baby = { 193 | name: `${first} ${last}`, 194 | age: 0, 195 | }); 196 | }; 197 | 198 | //arrow function 2: 199 | const makeABaby = (first, last) => ({ name: `${first} ${last}`, age: 0 }); 200 | ``` 201 | 202 | 203 | 204 | - ### IIFE 205 | 206 | means Immediately Invoked Function Expression 207 | 208 | ```js 209 | //anon function 210 | function(){ 211 | console.log('Running the anon function'); 212 | return 'you are cool'; 213 | } 214 | 215 | //you can run immediately by doing this: 216 | (function(age){ 217 | console.log('Running the anon function'); 218 | return `you are cool and age ${age}`; 219 | })(10); 220 | ``` 221 | 222 | 223 | 224 | - ### Methods 225 | 226 | is a function that lives inside an object like: 227 | 228 | ```js 229 | console.log; 230 | ``` 231 | 232 | Log is the function that lives inside the console which is the Object 233 | we can create our own methods: 234 | 235 | ```js 236 | const wes = { 237 | name: "wes bos", 238 | sayHi: function () { 239 | return `Hey! wes`; 240 | }, 241 | }; 242 | ``` 243 | 244 | there is a shorthand for that 245 | 246 | ```js 247 | const wes = { 248 | name: "wes bos", 249 | sayHi() { 250 | return `Hey! wes`; 251 | }, 252 | }; 253 | ``` 254 | 255 | and we can setup as an arrow function but you cannot access to the .this. 256 | 257 | ```js 258 | sayHi() => `Hey! wes`; 259 | ``` 260 | 261 |
262 | 263 | 264 | 265 | ## **CALLBACK FUNCTIONS** 266 | 267 | - **click callback function** 268 | 269 | ```js 270 | const button = document.querySelector('.clickMe'); 271 | 272 | function handleClick(){ 273 | console.log(great click); 274 | } 275 | 276 | button.addEventListener('click', handleClick); 277 | ``` 278 | 279 | is a function passed into other function, that then can be called by the browser at a later point. 280 | 281 | - **timer callback function** 282 | 283 | ```js 284 | setTimeout(function()){ 285 | console.log('Time to eat!'); 286 | }, 1000); 287 | ``` 288 | 289 | this will run after 1000 ms 290 | 291 |
292 | 293 | --- 294 | 295 | back to [Table of Content](tableOfContent.md) 296 | previous [The basics](01_basics.md) 297 | next [The Tricky Bits](03_bits.md) 298 | -------------------------------------------------------------------------------- /03_bits.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # **Module #3 - The tricky bits** 4 | 5 | --- 6 | 7 | 8 | 9 | ## **SCOPE** 10 | 11 | 12 | 13 | - ### Global variables 14 | 15 | when variable is created a variable not inside a function, not inside a module, not inside if statement, you can access them from any other javascript that's running on the page via script tag or console. 16 | in the browser the global scope is called **_window_** 17 | 18 | ```js 19 | windows.setTimeOut(); 20 | ``` 21 | 22 | Var variables are attached to the window object and they are globally scoped, const and let still being global scope but not attached to the window. 23 | functions are attached to global scope as well 24 | 25 | 26 | 27 | - ### function scope 28 | 29 | when variables are created inside a function, those variables are only a available inside of that function unless we were to explicitly return it and put it into it's own variable when that function is run 30 | 31 | ```js 32 | const age = 100; 33 | 34 | function go(){ 35 | const hair = 'blonde'; 36 | } 37 | go(); 38 | console log (hair); // this gives you an error because hair variable is inside of a function 39 | console.log(age); 40 | 41 | // right way to do it: 42 | const age = 100; 43 | 44 | function go(){ 45 | const hair = 'blonde'; 46 | console log (hair); 47 | } 48 | go(); 49 | console.log(age); 50 | 51 | // also you can access to global variables from inside of a function 52 | const age = 100; 53 | 54 | function go(){ 55 | const hair = 'blonde'; 56 | console log (hair); 57 | console.log(age); 58 | } 59 | go(); 60 | ``` 61 | 62 | 63 | 64 | - ### block scope 65 | 66 | var let and const variables are scoped differently 67 | 68 | ```js 69 | if (1 === 1) { 70 | let cool = true; 71 | } 72 | console.log(cool); 73 | ``` 74 | 75 | when you have a set of curly brackets "{...}" that is what is referred to as a block. 76 | you will not be able to access to the cool variable, because is inside of curly brackets. 77 | the solution will be to create a variable above it and updated inside the block. 78 | 79 | ```js 80 | let cool; 81 | 82 | if (1 === 1) { 83 | cool = true; 84 | } 85 | console.log(cool); 86 | ``` 87 | 88 | or 89 | 90 | ```js 91 | function isCool(name) { 92 | let cool; 93 | if (name === "wes") { 94 | cool = true; 95 | } 96 | return cool; 97 | } 98 | ``` 99 | 100 |
101 | 102 | 103 | 104 | ## **HOISTING** 105 | 106 | Hoisting allows you to access functions and variables before they have been created, there´s two things in javascript that are hoisted: 107 | 108 | - functions declarations 109 | 110 | ```js 111 | sayHi(); 112 | 113 | function sayHi() { 114 | console.log("Hey!"); 115 | console.log(add(10, 2)); 116 | } 117 | 118 | function add(a, b) { 119 | return a + b; 120 | } 121 | ``` 122 | 123 | - variable declarations 124 | javascript hoist variable declarations, but will not hoisted actual setting value: 125 | 126 | ```js 127 | // this will give you undefined 128 | console.log(age); 129 | var age = 10; 130 | 131 | //Reference error if you use let (age is not defined) 132 | console.log(age); 133 | let age = 10; 134 | ``` 135 | 136 |
137 | 138 | 139 | 140 | ## **CLOSURES** 141 | 142 | Closures are the ability for a child function or inner function (child scope) to access variables from a higher level scope (parent scope) even after the functions have been called or closed 143 | 144 | ```js 145 | function parentScope() { 146 | const parentVar = "I am the parent variable"; 147 | function childScope() { 148 | const childVar = "I am the child variable"; 149 | console.log(childVar); 150 | console.log(parentVar); 151 | } 152 | return childScope; 153 | } 154 | 155 | const childFinal = parentScope(); 156 | childFinal(); 157 | ``` 158 | 159 | in the example below, you stick a function into a variable and at a later point you have access to that child function. 160 | the closure is the fact that even though the parent function is done still maintain the variable in memory and you are able to access at later time. 161 | 162 |
163 | 164 | --- 165 | 166 | back to [Table of Content](tableOfContent.md) 167 | previous [Functions](02_functions.md) 168 | next [The DOM](04_dom.md) 169 | -------------------------------------------------------------------------------- /04_dom.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # **Module #4 - The DOM** 4 | 5 | --- 6 | 7 | Javascript can be run in many types of environment, can be run in the browser, in the server, in robots, the most popular is way to introduce is through the web browser. 8 | The browser turns your html into something that is called **DOM** (_Document Object Model_) 9 | 10 | - **The Window:** 11 | is the global scope in the browser, _the window_ is everything about the current open window, including the browser bar, the tabs, scroll bars. 12 | 13 | ```js 14 | window.location; 15 | window.innerWidth; 16 | ``` 17 | 18 | - **The Document:** 19 | Is responsible for everything from the opening `` to the closing `` including the `` 20 | 21 | - **The Navigator:** 22 | Is in a higher level than the window. 23 | it gives you information about the device itself, like battery, webcam, audio access, gps coordinates, etc. 24 | 25 |
26 | 27 | 28 | 29 | ## **SELECTING ELEMENTS** 30 | 31 | When you need to be able to access the specific elements on the page, like H2 tag (`

`), a div tag (`
`), a button (` 20 | 21 | ``` 22 | 23 | javascript 24 | 25 | ```js 26 | // select elements 27 | const butts = document.querySelector(".butts"); 28 | 29 | // add the event listener 30 | butts.addEventListener("click", function () { 31 | console.log("it got clicked!"); 32 | }); 33 | ``` 34 | 35 | `addEventListener` will take usually two arguments, the first one is the type of event that you want to listen to (in this case is _click_), and the second one is a callback function 36 | 37 | > **NOTE:** callback function is a regular function that will be called in a later point and the browser will call that function for us when it needs to. 38 | 39 | we can also create a named function outside and passed in as a reference: 40 | 41 | ```js 42 | // select elements 43 | const butts = document.querySelector('.butts'); 44 | 45 | // function (same function converted in an arrow function) 46 | function handleClick = () => console.log('it got clicked!'); 47 | 48 | // add the event listener 49 | butts.addEventListener('click', handleClick); 50 | ``` 51 | 52 | the benefits of making an outside function is that you can use the same function on different buttons or any other event listener, the second benefit is that if you want to remove an event lister it will be reference to a function in the second argument: 53 | 54 | ```js 55 | butts.removeEventListener("click", handleClick); 56 | ``` 57 | 58 | We can also select multiple items, lets se that with an example: 59 | 60 | ```HTML 61 | 62 | 63 | 64 | 65 | 66 | ``` 67 | 68 | suppose that we have to attach an event listener for a click on each button 69 | 70 | - first we need to select the items 71 | - if we look into the prototype there is a method called `forEach` that we will need to use in order to attach an event listener for avery element 72 | 73 | ```js 74 | //listen on multiple items 75 | const buyButtons = document.querySelectorAll(".buy"); 76 | 77 | // function to buy items on the page 78 | function buyItem() { 79 | console.log("Buying items"); 80 | } 81 | 82 | //loop into the elements (attach event listener for each element) 83 | buyButtons.forEach(function (buyButton) { 84 | buyButton.addEventListener("click", buyItem); 85 | }); 86 | ``` 87 | 88 | > **Note:** the parameter in the `forEach` method can be called whatever you want, is like a placeholder, in this case it was called buyButton in singular 89 | 90 | we can also create a function outside and pass it to the forEach method 91 | 92 | ```js 93 | // function to attach event listener 94 | function attachListenerToButtons(buyButton) { 95 | buyButton.addEventListener("click", buyItem); 96 | } 97 | 98 | // loop into each element 99 | buyButtons.forEach(attachListenerToButtons); 100 | ``` 101 | 102 | > You can find the example [here](https://codepen.io/cgope/pen/QWKLXWK) 103 | 104 |
105 | 106 | 107 | 108 | ## **TARGETS, BUBBLING, PROPAGATION AND CAPTURE** 109 | 110 | Continue with the last example "buy buttons" 111 | 112 | ```js 113 | const buyButtons = document.querySelectorAll('button.buy'); 114 | 115 | function handleBuyButtonClick(){ 116 | console.log('you are buying'); 117 | } 118 | 119 | buyButtons.forEach(function(buyButton){ 120 | buyButton.addEventListener('click, handleBuyButtonClick); 121 | }); 122 | ``` 123 | 124 | The `handleBuyButtonClick` function is handle the clicking for buttons, so how do i know which specific button they have clicked? 125 | That information is hidden away in the **event object** 126 | The event object is an is object that is filled with all kind of information of user useful information and methods to work with the event. 127 | 128 | In order to access the event object, we modify our callback to accept a param that is the **event** 129 | 130 | ```js 131 | function handleBuyButtonClick(event) { 132 | console.log("you are buying"); 133 | } 134 | ``` 135 | 136 | > **Note:** Parameters are placeholders so when we define a function we can put a parameter and call it event, and it doesn't matter how we called as long as is the first argument of our callback.
You can [click here](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#The_event_listener_callback) for more information. 137 | 138 | Now we can console log the event `console.log(event)` and we will see the pointer event, the pointer event is the consolidated of all the events we have like clicks, touches and all these mouse events. 139 | We will use target and current target for the next examples. 140 | Lets add a price to the buttons: 141 | 142 | ```HTML 143 | 144 | 145 | 146 | 147 | 148 | ``` 149 | 150 | Now using the target we should be able to access the price of each button, but these price is a string so we will parse as number (float): 151 | 152 | ```js 153 | const buyButtons = document.querySelectorAll("button.buy"); 154 | 155 | function handleBuyButtonClick(event) { 156 | console.log("you are buying"); 157 | console.log(parseFloat(event.target.dataset.price)); 158 | } 159 | 160 | buyButtons.forEach(function (buyButton) { 161 | buyButton.addEventListener("click", handleBuyButtonClick); 162 | }); 163 | ``` 164 | 165 | > You can find the example [here](https://codepen.io/cgope/pen/wvzMdaJ?editors=0010) 166 | 167 | The difference between `target` and `currentTarget`? 168 | The difference comes in when you have elements that are nested inside of the element that you are listening to, for example lets wrap the number of the buy button inside a strong tag 169 | 170 | ```HTML 171 | 172 | 173 | 174 | 175 | 176 | ``` 177 | 178 | so if you click in the number inside the button you will notice that `event.target` is the thing that actually got clicked (the number) and the `event.currentTarget` is the thing that fired the event listener 179 | 180 | Is possible to be clicking on multiple things at certain time, at that is **_propagation_** meaning that if we click in the strong tag, we also click the button, and we also click in the body, and also clicked the html, window, etc ... 181 | The way that you can prevent that is with a method on the event that's called stop propagation 182 | 183 | ```js 184 | // stop this event from bubbling up 185 | event.stopPropagation(); 186 | ``` 187 | 188 | The events can be the opposite, that is called **_Capture_** which is the opposite to propagation 189 | the following image should explain this: 190 | 191 | ![Propagation, capture, target](./img/bubblingCapture.png) 192 | 193 | > you can click [here](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) for more information about bubbling and capture 194 | 195 |
196 | 197 | 198 | 199 | ## **PREVENT DEFAULT AND FORM EVENTS** 200 | 201 | There's a couple elements in HTML that have default functionality when they're clicked, for example a submit button, and we can stop the default action by using: 202 | 203 | ```js 204 | event.preventDefault(); 205 | ``` 206 | 207 | For example we want to prevent the submit default if the name of a input form is "chad" 208 | 209 | ```HTML 210 |
211 |
212 | 213 | 214 | 215 | 216 | 217 | 218 |
219 | 220 |
221 |
222 | ``` 223 | 224 | so our javascript should be something like: 225 | 226 | ```js 227 | const signupForm = document.querySelector('[name="singup"]'); 228 | 229 | signupForm.addEventListener("submit", function (event) { 230 | const name = event.currentTarget.name.value; 231 | if (name.includes("chad")) { 232 | alert("sorry bro"); 233 | event.preventDefault(); 234 | } 235 | }); 236 | ``` 237 | 238 | The `preventDefault()` will help us to stop the default action, so if the name is chad it will not sent the information when you click submit, if you remove the `preventDefault()`, it will send the information after the validation. 239 | 240 | > you can see the example [here](https://codepen.io/cgope/pen/eYdJWeb?editors=0010) 241 | 242 |
243 | 244 | 245 | 246 | ## **ACCESSIBILITY GOTCHAS AND KEYBOARD CODES** 247 | 248 | The differences between buttons and links: 249 | Buttons are to be used for actions tha happen inside the application. 250 | Links are used to change the page. 251 | that means that links are not to be used where buttons are. 252 | 253 | Every key has a code, and the event have a bunch of information theres a Wes Bos website called [keycode.info](https://www.keycode.info) where you can literally just press on any key to get meta information about that key. 254 | 255 |
256 | 257 | --- 258 | 259 | back to [Table of Content](tableOfContent.md) 260 | previous [The DOM](04_dom.md) 261 | next [Serious practice exercises](06_SeriousPractice.md) 262 | -------------------------------------------------------------------------------- /06_SeriousPractice.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # **Module #6 - Serious practice exercises** 4 | 5 | --- 6 | 7 | 8 | 9 | ## **ETCH-A-SKETCH** 10 | 11 | > Example [here](https://codepen.io/cgope/pen/yLaVayG) 12 | 13 | We need to select all elements on the page. 14 | The canvas is the element and the place were we will drawing is called context (ctx), then we call the getContext method which in this case is 2d 15 | 16 | ```js 17 | const canvas = document.querySelector("#etch-a-sketch"); 18 | 19 | const ctx = canvas.getContext("2d"); 20 | 21 | const shakeButton = document.querySelector(".shake"); 22 | 23 | const MOVE_AMOUNT = 10; 24 | ``` 25 | 26 | then set up canvas for drawing 27 | 28 | ```js 29 | const { width, height } = canvas; 30 | 31 | let x = Math.floor(Math.random() * width); 32 | 33 | let y = Math.floor(Math.random() * height); 34 | ``` 35 | 36 | After that we will create random x and y starting points on the canvas 37 | 38 | ```js 39 | ctx.lineJoin = "round"; 40 | ctx.lineCap = "round"; 41 | ctx.lineWidth = MOVE_AMOUNT; 42 | 43 | let hue = 0; 44 | ctx.strokeStyle = `hsl(${hue}, 100%, 50%)`; 45 | ctx.beginPath(); //start drawing 46 | ctx.moveTo(x, y); 47 | ctx.lineTo(x, y); 48 | ctx.stroke(); 49 | ``` 50 | 51 | Now we can write a draw function 52 | 53 | ```js 54 | function draw({ key }) { 55 | //increment the hue 56 | hue += 5; 57 | ctx.strokeStyle = `hsl(${hue}, 100%, 50%)`; 58 | ctx.beginPath(); 59 | ctx.moveTo(x, y); 60 | //move our x and y values depending on what the user did 61 | switch (key) { 62 | case "ArrowUp": 63 | y -= MOVE_AMOUNT; 64 | break; 65 | case "ArrowRight": 66 | x += MOVE_AMOUNT; 67 | break; 68 | case "ArrowDown": 69 | y += MOVE_AMOUNT; 70 | break; 71 | case "ArrowLeft": 72 | x -= MOVE_AMOUNT; 73 | break; 74 | default: 75 | break; 76 | } 77 | ctx.lineTo(x, y); 78 | ctx.stroke(); 79 | } 80 | ``` 81 | 82 | Now we need to write a handler for keys 83 | 84 | ```js 85 | function handleKey(e) { 86 | if (e.key.includes("Arrow")) { 87 | e.preventDefault(); 88 | draw({ key: e.key }); 89 | } 90 | } 91 | ``` 92 | 93 | And now we can work on the clean/shake button 94 | 95 | ```js 96 | function clearCanvas() { 97 | canvas.classList.add("shake"); 98 | ctx.clearRect(0, 0, width, height); 99 | canvas.addEventListener( 100 | "animationend", 101 | function () { 102 | canvas.classList.remove("shake"); 103 | }, 104 | { once: true } 105 | ); 106 | } 107 | ``` 108 | 109 | Finally we will have to listen for the arrow keys and shake button 110 | 111 | ```js 112 | window.addEventListener("keydown", handleKey); 113 | shakeButton.addEventListener("click", clearCanvas); 114 | ``` 115 | 116 |
117 | 118 | 119 | 120 | ## **CLICK OUTSIDE MODAL** 121 | 122 | > Example [here](https://codepen.io/cgope/pen/vYypLMO) 123 | 124 | The main goal of this exercise is to know about the clicking outside, the example is about we have some cards which contains an image, a title and a button, so if you click on the button a higher version of the image will be displayed, then if you click outside it will close it and return to the main cards. 125 | 126 | So first thing is select the button for each card, loop into each button and add and event listener for the click that will trigger a function called _**handleCardButtonClick**_: 127 | 128 | ```js 129 | //select the buttons 130 | const cardButtons = document.querySelectorAll(".card button"); 131 | 132 | //loop into each button and listen for a click 133 | cardButtons.forEach((button) => 134 | button.addEventListener("click", handleCardButtonClick) 135 | ); 136 | ``` 137 | 138 | Next step is grab something to show in the modal, so it will be the image in a higher version, the data description, this will happen in the function: 139 | 140 | ```js 141 | function handleCardButtonClick(event) { 142 | //grab the button and card 143 | const button = event.currentTarget; 144 | const card = button.closest(".card"); 145 | //grab the img src 146 | const imgSrc = card.querySelector("img").src; 147 | const desc = card.dataset.description; 148 | const name = document.querySelector("h2").textContent; 149 | //populate modal with new info 150 | modalInner.innerHTML = ` 151 | ${name} 152 |

${desc}

153 | `; 154 | 155 | //Show the modal 156 | modalOuter.classList.add("open"); 157 | } 158 | ``` 159 | 160 | we use the _closest_ method to get the card associated with the button that got clicked. 161 | The replace the 200 for 500 to get the higher version of the image, meaning that instead of the img of 200px we will use the 500px version of the same image. 162 | 163 | And don't forget to select the modal before we try to show the modal in the function: 164 | 165 | ```js 166 | const modalOuter = document.querySelector(".modal-outer"); 167 | const modalInner = document.querySelector(".modal-inner"); 168 | ``` 169 | 170 | Now the most important part of the exercise is to close the card, so we need to write a function for that: 171 | 172 | ```js 173 | function closeModal() { 174 | modalOuter.classList.remove("open"); 175 | } 176 | ``` 177 | 178 | this simple remove the class of open, but now we need to close the modal when we click in the outside of the inner modal. 179 | we can do this using a event listener and making sure that the user clicked outside the modal. 180 | so the _closest_ method can be helpful here too to tell us if the click happens outside or inside the inner modal, so if you click inside of the modal inner it will find the modal inner, if not it will not be able to find anything, then we can convert into a boolean, so if find something it will be false and if don't find something it will be true: 181 | 182 | ```js 183 | modalOuter.addEventListener("click", function (event) { 184 | //the ! will convert into a boolean 185 | const isOutSide = !event.target.closest(".modal-inner"); 186 | if (isOutSide) { 187 | closeModal(); 188 | } 189 | }); 190 | ``` 191 | 192 | a feature can be added with the Esc key, so if the user type the esc key it will close the modal as well: 193 | 194 | ```js 195 | window.addEventListener("keydown", (event) => { 196 | if (event.key === "Escape") { 197 | closeModal(); 198 | } 199 | }); 200 | ``` 201 | 202 | you can find the event key for whatever key you want you can go to [keycode](https://keycode.info/) website 203 | 204 |
205 | 206 | 207 | 208 | ## **SCROLL EVENTS AND INTERSECTION OBSERVER** 209 | 210 | > Example [here](https://codepen.io/cgope/pen/vYypLMO) 211 | 212 | In the example we work with Terms and Conditions, maybe scroll event isn't the best way to approach this because you will have to deal offsets, margin, padding, heights, instead of scroll events we will use _Intersection Observer_ 213 | 214 | first thing first is select the Terms and conditions and the button: 215 | 216 | ```js 217 | const terms = document.querySelector(".terms-and-conditions"); 218 | 219 | const button = document.querySelector(".agree"); 220 | ``` 221 | 222 | After select the elements we can create a function called obCallBack, this function will give us a payload. 223 | we will use `payload[0]` since it will be the first thing in the payload, you can watch for multiple items. 224 | `IntersectionRatio` will tell us how much is visible on the page. 225 | so when the intersection ratio it's equals to 1 we can enable the button to accept the terms and conditions. 226 | 227 | ```js 228 | function obCallBack(payload) { 229 | if (payload[0].intersectionRatio === 1) { 230 | button.disabled = false; 231 | //stop observing the button 232 | ob.unobserve(terms.lastElementChild); 233 | } 234 | } 235 | ``` 236 | 237 | Now we can create the Intersection Observer, this will watch if an element is on or off or partway on or off of the page. 238 | the way that we know is 100% visible on the page is by using the second argument can be an options object: 239 | first the **root** of what we are scrolling with by default is the body, in this case is terms, and the **threshold** we can give it an array like [0, 0.5, 1] where 0 means off, 0/5 means halfway on and 1 means totally on, for our case we only care when is totally on 240 | 241 | ```js 242 | const ob = new IntersectionObserver(obCallBack, { 243 | root: terms, 244 | threshold: 1, 245 | }); 246 | ``` 247 | 248 | the intersection observer is going to take a callback (obCallBack in this case) 249 | 250 | > NOTE: a callback is a function that gets called at a certain point. Intersection observer is a callback that will be fired every single time that it needs to check if something is currently on the page, for more info you can visit [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API). 251 | 252 | this still do anything until we told it to watch for any element, which in this case will be the terms. 253 | the way that we know that is the user scroll to the bottom is looking for the last element inside terms and conditions, which is the `
` and we wait until the tag be 100% on the screen, for that we use `lastElementChild` 254 | 255 | ```js 256 | ob.observe(terms.lastElementChild); 257 | ``` 258 | 259 |
260 | 261 | 262 | 263 | ## **TABS** 264 | 265 | > Example [here](https://codepen.io/cgope/pen/NWbBbpQ) 266 | 267 | This example contains roles and aria labels in the HTML, this is important to make your tabs accessible and your content will be easily read by search engine. 268 | We will need the tabs, buttons and panels: 269 | 270 | ```js 271 | const tabs = document.querySelector(".tabs"); 272 | 273 | const tabButtons = tabs.querySelectorAll('[role="tab"]'); 274 | 275 | //convert into an array to use the find method in the function by using Array.from 276 | const tabPanels = Array.from(tabs.querySelectorAll('[role="tabpanel"]')); 277 | ``` 278 | 279 | for buttons (`tabButtons`) we are going to select from `tabs` looking for anything with the role of "tab" because you can have multiple tabs on the same page and this can be reused for any number of tabs. 280 | `tabPanels` should be converted from a node list into an array in order to use the Find method to show the panels, how to will be explained at the end of this Module. 281 | 282 | Then add the listener for each tab buttons: 283 | 284 | ```js 285 | tabButtons.forEach((button) => 286 | button.addEventListener("click", handleTabClick) 287 | ); 288 | ``` 289 | 290 | Now create the function to handle the click: 291 | 292 | ```js 293 | function handleTabClick(event) { 294 | //hide all tab panels 295 | tabPanels.forEach((panel) => { 296 | panel.hidden = true; 297 | }); 298 | //mark all tabs as unselected 299 | tabButtons.forEach((tab) => { 300 | tab.setAttribute("aria-selected", false); 301 | }); 302 | //mark the clicked tab as selected 303 | event.currentTarget.setAttribute("aria-selected", true); 304 | //find the associated tabPanel and show it! 305 | const id = event.currentTarget.id; 306 | 307 | /*Method 1 308 | const tabPanel = tabs.querySelector(`[aria-labelledby="${id}"]`); 309 | tabPanel.hidden = false; 310 | */ 311 | 312 | //Method 2 - find method 313 | const tabPanel = tabPanels.find( 314 | (panel) => panel.getAttribute("aria-labelledby") === id 315 | ); 316 | tabPanel.hidden = false; 317 | } 318 | ``` 319 | 320 | When somebody click on a tab, we need to hide all of the other tab panels. 321 | After that we need to mark all tabs as unselected, the way we can do it its by using the `setAttribute` because its a custom properties. 322 | then we need to mark the tab that user clicked as selected, and find the ID associated panel for the tab and show it, there are many ways to do it, this example contains 2 of them: 323 | The first one is by matching the aria-attribute from the panels with the ID of the tabs, if its a match then we can change the hidden to false. 324 | 325 | ```js 326 | const tabPanel = tabs.querySelector(`[aria-labelledby="${id}"]`); 327 | tabPanel.hidden = false; 328 | ``` 329 | 330 | The second option is by using the find method, we can loop into tabPanels until it finds the one that match if you want to use this method make sure that you turn the selected item as an array first: 331 | 332 | ```js 333 | const tabPanels = Array.from(tabs.querySelectorAll('[role="tabpanel"]')); 334 | ``` 335 | 336 | after that you can take each panel and get the attribute from the aria label to match with the ID of the tab 337 | 338 | ```js 339 | const tabPanel = tabPanels.find( 340 | (panel) => panel.getAttribute("aria-labelledby") === id 341 | ); 342 | tabPanel.hidden = false; 343 | ``` 344 | 345 |
346 | 347 | --- 348 | 349 | back to [Table of Content](tableOfContent.md) 350 | previous [Events](05_events.md) 351 | next [Logic and flow control](07_LogicAndFlowControl.md) 352 | -------------------------------------------------------------------------------- /07_LogicAndFlowControl.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # **Module #7 - Logic and flow control** 4 | 5 | --- 6 | 7 | 8 | 9 | ## **BEDMAS** 10 | 11 | BEDMAS refers to the order of operations, is the same as Maths do it: 12 | 13 | **B** = brackets - **E** = exponents - **D** = division - **M** = multiplication - **A** = addition - **S** = subtraction 14 | 15 | So the order means that things inside the brackets or parentheses go first, then we do exponents (which is sort of like the power of). 16 | Then division, multiplication, addition and subtraction. 17 | 18 | This is like exponents looks like in javascript: 19 | 20 | ```js 21 | 2 ** 2; // result is 4 22 | 2 ** 10; // result 1024 23 | ``` 24 | 25 | Back to order of operation: 26 | 27 | **Example:** First multiplication then subtraction. 28 | 29 | ```js 30 | const example = 10 * 5 - 2; 31 | //result should be 48 32 | ``` 33 | 34 | **Example 2:** First the subtraction due to the parentheses, then the multiplication. 35 | 36 | ```js 37 | const example1 = 10 * (5 - 2); 38 | //result should be 30 39 | ``` 40 | 41 |
42 | 43 | 44 | 45 | ## **FLOW CONTROL - IF STATEMENTS, FUNCTION, RETURNS, TRUTHY, FALSY** 46 | 47 |
48 | 49 | 50 | 51 | - ### **Statements** 52 | 53 | Statements are the foundation of all logic in javascript, they expect boolean which is a type in Javascript that is always either true or false. 54 | To explain the mechanics of an if statement we will use the greater or less than operators: 55 | 56 | we want to evaluate a condition that will be true or false 57 | 58 | ```js 59 | if (10 > 2) { 60 | console.log("yes, 10 is greater than 2"); 61 | } 62 | ``` 63 | 64 | the condition is `(10 > 2)` if that is true then what ever things that needs to happen should be inside the block which is delimitated by the curly brackets that are opening and closing the block. 65 | We can have multiple conditions by using `else if` 66 | 67 | ```js 68 | if (10 > 2) { 69 | console.log("yes, 10 is greater than 2"); 70 | } else if (11 > 10) { 71 | console.log("yes, 11 is greater than 10"); 72 | } else if (3 > 1) { 73 | console.log("yes, 3 is greater than 1"); 74 | } 75 | ``` 76 | 77 | But if the first one is true, even id ones that come later are also true they will never run, that means that we only get the first one (`yes, 10 s greater than 2`) 78 | 79 | If you want to check for multiple things that are true or false you will need three separate statements 80 | 81 | ```js 82 | if (10 > 2) { 83 | console.log("yes, 10 is greater than 2"); 84 | } 85 | 86 | if (11 > 10) { 87 | console.log("yes, 11 is greater than 10"); 88 | } 89 | 90 | if (3 > 1) { 91 | console.log("yes, 3 is greater than 1"); 92 | } 93 | ``` 94 | 95 | Additionally if nothing match you can put an `else` to the end, and the else does not need a condition 96 | 97 | ```js 98 | const age = 50; 99 | 100 | if (age > 70) { 101 | console.log("in your seventies"); 102 | } else if (age > 60) { 103 | console.log("in your sixties"); 104 | } else if (age > 50) { 105 | console.log("in your 50s"); 106 | } else { 107 | console.log("nothing was true"); 108 | } 109 | ``` 110 | 111 |
112 | 113 | 114 | 115 | - ### **If statements inside a function** 116 | 117 | And statement into a function can return different values, we have a function called slugify, and what this function does is take a sentence and a boolean of whether we should lowercase or not, then we return the sentence calling a replace method and using a _Regex_ (regular expression) we will replace the spaces for dashes. 118 | In this case Regex looks like this 119 | 120 | ```js 121 | /\s/g, "-"; 122 | ``` 123 | 124 | Regex always start with an `/` and it closes with another slash `/` 125 | The `\s` is referring to and space 126 | The `g` is referring to a global, so find them all, not just the first space. 127 | Finally every space will be replaced by a dash. 128 | So this is the function: 129 | 130 | ```js 131 | function slugify(sentence, lowercase) { 132 | if (lowercase) { 133 | return sentence.replace(/\s/g, "-").toLowerCase(); 134 | } else { 135 | return sentence.replace(/\s/g, "-"); 136 | } 137 | } 138 | ``` 139 | 140 | some developers prefers to keep as much logic out of the brackets, to prevent delete something, so lets remake the function 141 | 142 | ```js 143 | function slugify(sentence, lowercase) { 144 | let slug = sentence.replace(/\s/g, "-"); 145 | 146 | if (lowercase) { 147 | return slug.toLowerCase(); 148 | } 149 | return slug; 150 | } 151 | ``` 152 | 153 | The first thing is removing the else, since we are using the return is not necessary the else 154 | 155 | > the return means to return a value from a function and stop that function from running. 156 | 157 | Then we can create a variable for the replace. 158 | 159 | Another way we can use statements in functions is for example if we have a function that checks if a name is inside a word like the word _awesome_ 160 | 161 | ```js 162 | function nameIsAwesome(name) { 163 | return "awesome".includes(name); 164 | } 165 | ``` 166 | 167 | Then we can check with and if statement if that condition is true or false 168 | 169 | ```js 170 | if (nameIsAwesome('wes'){ 171 | console.log('Cool name'); 172 | } 173 | ``` 174 | 175 |
176 | 177 | 178 | 179 | - ### **Operators** 180 | 181 | In [previous module](01_basics.md#booleans) we learn about equals, double equals and triple equals, now we can use _not equal_ operator by using a bang followed by double equals `!==` and that means not equal, other operators and examples: 182 | 183 | - `!==` means not equal 184 | - `>` means greater than `10 > 2` 185 | - `>=` means greater or equal to `10 >= 10` 186 | - `<` means less than `10 < 11` 187 | - `<=` means less or equal to `10 < 10` 188 | - `||` means or operator 189 | - `&&` means and operator 190 | 191 | > greater and less operator only works with numbers 192 | 193 | Lets see how `||` and `&&` works with and example: 194 | 195 | - OR example: we want to check if someone name is equal to Wes or Scott 196 | 197 | ```js 198 | const name = "wes"; 199 | 200 | if (name === "wes" || name === "scott") { 201 | console.log("cool name"); 202 | } 203 | ``` 204 | 205 | - AND example: we want to check if the first name and last name are the same 206 | 207 | ```js 208 | const name = "wes"; 209 | const last = "bos"; 210 | 211 | if (name === "wes" && last === "bos") { 212 | console.log("cool name"); 213 | } 214 | ``` 215 | 216 | - BEDMAS example: we can combine OR and AND together and check if the name is equal to Scott **OR** the name is equal to Wes **AND** last name is equal to bos 217 | 218 | ```js 219 | const name = "wes"; 220 | const last = "bos"; 221 | 222 | if (name === "scott" || (name === "wes" && last === "bos")) { 223 | console.log("cool name"); 224 | } 225 | ``` 226 | 227 | in order to this can work the whole **AND** condition ned to be true 228 | 229 |
230 | 231 | 232 | 233 | - ### **Truthy Falsy** 234 | 235 | There are values that are truthy and false, lets see that: 236 | 237 | | Truthy values | Falsy values | 238 | | :-----------: | :-------------------------: | 239 | | 1 | 0 | 240 | | -10 | undefined variable | 241 | | full string | variable set as null | 242 | | string of "0" | variable `"hello" -10 (NaN) | 243 | | empty array | empty string | 244 | | empty object | | 245 | | | | 246 | 247 | You can check by copy and past this code in your console browser: 248 | 249 | ```js 250 | const values = [ 251 | [], 252 | {}, 253 | -10, 254 | 1, 255 | 0, 256 | "", 257 | "full string", 258 | " ", 259 | undefined, 260 | NaN, 261 | null, 262 | ]; 263 | 264 | console.group("truthy or falsy values"); 265 | values.forEach((value) => { 266 | if (value) { 267 | console.log(value, "is truthy"); 268 | } else { 269 | console.log(value, "is falsy"); 270 | } 271 | }); 272 | console.groupEnd(); 273 | ``` 274 | 275 | This is the output: 276 | 277 | ![truthyFalsy](./img/truthyFalsy.png) 278 | 279 | This is how it looks like in an example: 280 | Lets use an string and an empty string, an empty string is falsy and a string is truthy. 281 | So we have an if statement that will compare a variable called dog, if the variable is truthy it will tell us _you have a dog_ but if the variable is falsy it will tell us _you don't have a dog_ 282 | 283 | ```js 284 | const dog = ''; 285 | 286 | if (dog){ 287 | console.log('you have a dog'); 288 | } else { 289 | console.log('you don't have a dog'); 290 | } 291 | ``` 292 | 293 | If you run this with an empty string like in the example, the return will be _you don't have a dog_ since an empty string has a value of falsy, but if you assign a value to the variable dog, you will get _you have a dog_ since a string has a truthy value 294 | 295 |
296 | 297 | 298 | 299 | ## **COERCION, TERNARIES AND CONDITIONAL ABUSE** 300 | 301 | 302 | 303 | - ### **Coercion** 304 | 305 | Coercion is when we force a different type, like string, number or an object, etc, into a real boolean. 306 | As an example, if we have a variable called name and we assign a string value to that variable we can coercing into true or false using the bang operator. 307 | Then we can check if the variable has a value or not 308 | ![coercion](./img/coercion.png) 309 | 310 | 311 | 312 | - ### **Ternaries** 313 | 314 | Is something like a shorthand if statement, used to quickly assign or run functionality based on something being true or false. 315 | Ternaries needs 3 things: 316 | 317 | - condition 318 | - what to do if it's true 319 | - what to do if it's false 320 | 321 | As an example: 322 | we want to know how many items you have in a cart 323 | 324 | ```js 325 | const count = 2; 326 | let word; 327 | 328 | if (count === 1) { 329 | word = "item"; 330 | } else { 331 | word = "items"; 332 | } 333 | 334 | const sentence = `you have ${count} ${word} in your cart`; 335 | console.log(sentence); 336 | ``` 337 | 338 | If the number is equal to 1 the word will be item, otherwise the word will be items. 339 | 340 | Now we have the 3 conditions to make it as a ternary, and will look like this: 341 | 342 | ```js 343 | const count = 2; 344 | 345 | const word = count === 1 ? "item" : "items"; 346 | 347 | const sentence = `you have ${count} ${word} in your cart`; 348 | console.log(sentence); 349 | ``` 350 | 351 | so we have: 352 | 353 | - the condition (`count === 1`) 354 | - what to do if its true (`? 'item'`) 355 | - what to do if its false (`: 'items'`) 356 | 357 | We can use the ternary directly into the variable sentence: 358 | 359 | ```js 360 | const count = 2; 361 | 362 | const sentence = `you have ${count} item ${ 363 | count === 1 ? "" : "s" 364 | } in your cart`; 365 | 366 | console.log(sentence); 367 | ``` 368 | 369 | We can also use ternaries for running functions: 370 | In this case if the variable isAdmin is true will run the function if not it will do nothing, and to do nothing the word _null_ should be there (is the false case) 371 | 372 | ```js 373 | function showAdminBar() { 374 | console.log("showing admin bar"); 375 | } 376 | 377 | const isAdmin = true; 378 | 379 | isAdmin ? showAdminBar() : null; 380 | ``` 381 | 382 |
383 | 384 | 385 | 386 | - ### **Conditional abuse** 387 | 388 | This is related with the _AND AND TRICK_ 389 | 390 | ```js 391 | function check1() { 392 | console.log("running check 1"); 393 | return true; 394 | } 395 | function check2() { 396 | console.log("running check 2"); 397 | return true; 398 | } 399 | function check3() { 400 | console.log("running check 3"); 401 | return true; 402 | } 403 | ``` 404 | 405 | If we want to make sure that all this functions are true we can run an if statement like this: 406 | 407 | ```js 408 | if (check1() && check2() && check3()) { 409 | console.log("all checks passed"); 410 | } else { 411 | console.log("some check failed"); 412 | } 413 | ``` 414 | 415 | If one of those is false, the next one will never run. 416 | 417 | writing the _isAdmin_ example with the AND AND TRICK, it looks like that: 418 | 419 | ```js 420 | function showAdminBar() { 421 | console.log("showing admin bar"); 422 | } 423 | 424 | const isAdmin = true; 425 | 426 | isAdmin && showAdminBar(); 427 | ``` 428 | 429 | The way that works can be consider abuse, the last part of code is validating: 430 | 431 | - if isAdmin is true then it will run the function. 432 | - if isAdmin is false it will stop, since the && only works if all is true. 433 | 434 |
435 | 436 | 437 | 438 | - ### **Blockless if statements** 439 | 440 | This means that if something is on the same line, you dont need the block of the statements: 441 | 442 | ```js 443 | if (isAdmin) { 444 | showAdminBar(); 445 | } 446 | ``` 447 | 448 | this can be blockless like this: 449 | 450 | ```js 451 | if (isAdmin) showAdminBAr(); 452 | ``` 453 | 454 |
455 | 456 | 457 | 458 | ## **CASE SWITCH AND ANIMATING A TURTLE WITH CSS VARIABLES** 459 | 460 | Switch should be used when you have a whole bunch of different cases and each have to be clearly defined, we are not comparing values, what we want is to do different things according of what key was typed. 461 | 462 | the syntax of a switch statement looks like this: 463 | 464 | ```js 465 | switch (expression) { 466 | case 1: 467 | // code block 468 | break; 469 | case 2: 470 | // code block 471 | break; 472 | case 3: 473 | // code block 474 | break; 475 | default: 476 | // code block 477 | } 478 | ``` 479 | 480 | it always need a break and the end of each case, if you don't break then it will keep going down of each cases. 481 | If theres no match the default code will be executed. 482 | 483 | To apply this concepts we are going to make a cool example of an a turtle that will walk through the screen 484 | 485 | > Example [here](https://codepen.io/cgope/pen/BaQEexo) 486 | 487 | First thing is select elements: 488 | 489 | ```js 490 | const turtle = document.querySelector(".turt"); 491 | ``` 492 | 493 | we will need to listen for a key down and then run a function to handle the movement, we only care for the arrow keys (up, down, left, right). 494 | 495 | ```js 496 | window.addEventListener("keydown", handleKeyDown); 497 | ``` 498 | 499 | Now the function: 500 | 501 | ```js 502 | function handleKeyDown(event) { 503 | //if is not an arrow key, we don't care 504 | if (!event.key.includes("Arrow")) { 505 | return; 506 | } 507 | //switch 508 | switch (event.key) { 509 | case "ArrowUp": 510 | y = y - 1; 511 | rotate = -90; 512 | break; 513 | case "ArrowDown": 514 | y = y + 1; 515 | rotate = 90; 516 | break; 517 | case "ArrowRight": 518 | x = x + 1; 519 | flipped = false; 520 | rotate = 0; 521 | break; 522 | case "ArrowLeft": 523 | x = x - 1; 524 | flipped = true; 525 | rotate = 0; 526 | break; 527 | default: 528 | alert("this is not a valid move"); 529 | break; 530 | } 531 | turtle.setAttribute( 532 | "style", 533 | ` 534 | --x: ${x * speed}px; 535 | --y: ${y * speed}px; 536 | --rotate: ${rotate}deg; 537 | --rotateX: ${flipped ? "180deg" : "0"}; 538 | ` 539 | ); 540 | } 541 | ``` 542 | 543 | the first part of the function will help to notice that if is not a arrow key, will do nothing 544 | 545 | ```js 546 | //if is not an arrow key, we don't care 547 | if (!event.key.includes("Arrow")) { 548 | return; 549 | } 550 | ``` 551 | 552 | otherwise we will go into a switch statement, and for that we need to create some variables for the movements 553 | 554 | ```js 555 | //variables for turtle moves 556 | let x = 0; 557 | let y = 0; 558 | const speed = 10; 559 | let flipped = false; 560 | let rotate = 0; 561 | ``` 562 | 563 | - so the x will be right or left. 564 | - the y will be up and down. 565 | - speed is to move a little faster 566 | - flipped means if goes to the left the img will flip (the head of the turtle will be pointed into the right direction) 567 | - rotate means that if turtle goes up or down the head will point into the right direction 568 | 569 | We create some CSS variables that then will be updated via Javascript. 570 | The way that we can update the CSS variables is by using the `setAttribute` because there are not standard properties. 571 | 572 | ```js 573 | turtle.setAttribute( 574 | "style", 575 | ` 576 | --x: ${x * speed}px; 577 | --y: ${y * speed}px; 578 | --rotate: ${rotate}deg; 579 | --rotateX: ${flipped ? "180deg" : "0"}; 580 | ` 581 | ); 582 | ``` 583 | 584 | If you want to update standard CSS properties you can do like: 585 | 586 | ```js 587 | turtle.style["background"] = red; 588 | ``` 589 | 590 | Now lets explain the switch: 591 | 592 | ```js 593 | case 'ArrowRight': 594 | x = x + 1; 595 | flipped = false; 596 | rotate = 0; 597 | break; 598 | ``` 599 | 600 | If an arrow right key was typed then we have to add 1 to the x in order to move the turtle to the right, then it will not flipped because the head is pointed to the right, the rotate will be 0. 601 | If an arrow up was typed then we need to subtract 1 to the y, we don't need to flip the turtle, but we need to rotate the turtle to -90deg in order to point the head of the turtle up 602 | 603 | ```js 604 | case 'ArrowUp': 605 | y = y - 1; 606 | rotate = -90; 607 | break; 608 | ``` 609 | 610 |
611 | 612 | 613 | 614 | ## **INTERVALS AND TIMERS** 615 | 616 | 617 | 618 | - ### **Timeout:** 619 | 620 | If you want to run something after sometime (i.e. after five seconds). 621 | 622 | `setTimeout();` is a method globally scoped that takes 2 arguments 623 | The first one is the callback or an anonymous function and the second thing is the numbers of milliseconds to run after: 624 | 625 | ```js 626 | //with an anonymous function 627 | setTimeOut(function () { 628 | console.log("Done!"); 629 | }, 500); 630 | 631 | //with a function outside 632 | function buzzer() { 633 | console.log("ENNGGGGGG"); 634 | } 635 | 636 | setTimeout(buzzer, 500); 637 | ``` 638 | 639 | An important thing to remember is the asynchronous nature of Javascript, that means that if you have: 640 | 641 | ```js 642 | console.log("starting"); 643 | setTimeout(buzzer, 500); 644 | console.log("finishing"); 645 | ``` 646 | 647 | the output will show: 648 | 649 | - starting 650 | - finishing 651 | - ENNGGGGGG 652 | 653 | Thats because javascript will execute the first line _(starting)_ then go to the setTimeout and skipped because that one should be executed after 500 milliseconds, then go into the second console log _(finishing)_, and finally comeback to the setTimeout after 500 milliseconds. 654 | 655 | > callback is something that we call it at a later point in time 656 | 657 |
658 | 659 | 660 | 661 | - ### **Intervals:** 662 | 663 | If you want to run something every so often. (i.e. every five seconds) 664 | 665 | `setInterval();` works in the same way that the timeout. 666 | The first one is the callback or an anonymous function and the second thing is the numbers of milliseconds to run after: 667 | 668 | ```js 669 | function buzzer() { 670 | console.log("ENNGGGGGG"); 671 | } 672 | 673 | setInterval(buzzer, 500); 674 | ``` 675 | 676 | The only thing that you have to remember is that intervals doesn't run immediately, it runs after the time that you setup. 677 | 678 | If you want to run an interval immediately we need to code our own interval: 679 | 680 | ```js 681 | function buzzer() { 682 | console.log("ENNGGGGGG"); 683 | } 684 | 685 | function setImmediateInterval(funcToRun, ms) { 686 | //right away call that function 687 | funcToRun(); 688 | // run a regular interval 689 | return setInterval(funcToRun, ms); 690 | } 691 | 692 | setImmediateInterval(buzzer, 2000); 693 | ``` 694 | 695 | This example will be executed immediately and then every 2000 milliseconds. 696 | The `funcToRun()` works like an argument for the `setImmediateInterval()` function, and this argument will be executed when we pass an other function which is `buzzer()` so it will be executed immediately and then every 2 seconds. 697 | 698 | 699 | 700 | - ### **Clear timers and intervals:** 701 | 702 | The way that you can clear timers and intervals is by reference into a variable, that later you can use. 703 | 704 | we have a page with a button, if you click the button before 5 seconds you will save the page, if not the page will be destroyed. 705 | 706 | > You can see the example [here](https://codepen.io/cgope/pen/WNoqqBZ) 707 | 708 | first thing create the HTML: 709 | 710 | ```HTML 711 |
712 |

Please click the button before 5 seconds to save the page

713 | 714 |
715 | ``` 716 | 717 | Now variable for the timer and selecting elements: 718 | 719 | ```js 720 | //save timer into a variable 721 | const bombTimer = setTimeout(destroy, 5000); 722 | 723 | //select button save 724 | const save = document.querySelector(".save"); 725 | ``` 726 | 727 | then we create the function destroy: 728 | 729 | ```js 730 | //function destroy 731 | function destroy() { 732 | document.body.innerHTML = ` 733 |

DESTROYED

734 | `; 735 | } 736 | ``` 737 | 738 | and finally the event listener: 739 | 740 | ```js 741 | //add event lister to the button 742 | save.addEventListener("click", function () { 743 | alert("You save the page"); 744 | clearTimeout(bombTimer); 745 | }); 746 | ``` 747 | 748 |
749 | 750 | --- 751 | 752 | back to [Table of Content](tableOfContent.md) 753 | previous [Serious practice exercises](06_SeriousPractice.md) 754 | next [Data types](08_DataTypes.md) 755 | -------------------------------------------------------------------------------- /08_DataTypes.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # **Module #8 - Data types** 4 | 5 | --- 6 | 7 | 8 | 9 | ## **OBJECTS** 10 | 11 | Objects allow us to group together properties and values (or key and values), they have many uses from storing related data, storing functionality, and creating custom types. 12 | Is important to note that in objects the order of properties doesn't matter. 13 | 14 | 15 | 16 | - ### **Create Object** 17 | 18 | Syntax: 19 | 20 | ```js 21 | const person = { 22 | name: "Cesar", 23 | age: "100", 24 | }; 25 | ``` 26 | 27 | > Note: properties in the left, values at the right 28 | 29 | We can use variables into an object: 30 | 31 | ```js 32 | const age = 100; 33 | const person = { 34 | name: "Cesar", 35 | age: "age", 36 | }; 37 | ``` 38 | 39 | In this case since the variable name is equals to the property name we can do: 40 | 41 | ```js 42 | const age = 100; 43 | 44 | const person = { 45 | name: "Cesar", 46 | age, 47 | }; 48 | ``` 49 | 50 | you can also have nested properties or objects to an object: 51 | 52 | ```js 53 | const age = 100; 54 | const person = { 55 | name: "Cesar", 56 | age, 57 | clothing: { 58 | shirts: 1, 59 | pants: 1, 60 | }, 61 | }; 62 | ``` 63 | 64 | 65 | 66 | - ### **Adding/modify a property** 67 | 68 | Adding a property after the object has been created is possible, same syntax if you want to over-write a property: 69 | 70 | ```js 71 | // add new property 72 | person.job = "Web Developer"; 73 | 74 | //over-write a property 75 | person.age = 50; 76 | ``` 77 | 78 |
79 | 80 | 81 | 82 | - ### **Frozen Object** 83 | 84 | You can modify any property of the object, but if you want to create an object that can't be modified any of their properties you can use **frozen object**: 85 | 86 | ```js 87 | const personFroze = object.freeze(person); 88 | ``` 89 | 90 | this will create a frozen object from the object called person, this will not freeze the original person object, it will return a new freeze object, and you can't modify any of the properties, on this new object. 91 | 92 |
93 | 94 | 95 | 96 | - ### **Access into a property of an Object** 97 | 98 | You can access to the objects properties from 2 different ways: 99 | 100 | - dot notation 101 | 102 | ```js 103 | //access 104 | person.name; 105 | 106 | //one level depp access 107 | person.clothing.shirts; 108 | ``` 109 | 110 | - square brackets notation 111 | 112 | ```js 113 | //access 114 | person["name"]; 115 | 116 | //one level depp access 117 | person["clothing"]["shirts"]; 118 | ``` 119 | 120 | > Example [here](https://codepen.io/cgope/pen/MWJwxxw) 121 | 122 |
123 | 124 | 125 | 126 | - ### **Delete Object properties** 127 | 128 | To delete a property of an object you can use the `delete` key word 129 | 130 | ```js 131 | delete person.job; 132 | ``` 133 | 134 |
135 | 136 | 137 | 138 | - ### **Functions inside Object** 139 | 140 | We can have functions inside an objects, that what is call **Method** 141 | 142 | ```js 143 | const person = { 144 | name: "Cesar", 145 | sayHello: function (greeting = "Hey") { 146 | return `${greeting} ${this.name}`; 147 | }, 148 | }; 149 | ``` 150 | 151 | There's also a method shorthand: 152 | 153 | ```js 154 | const person = { 155 | name: "Cesar", 156 | sayHello(greeting = "Hey") { 157 | return `${greeting} ${this.name}`; 158 | }, 159 | }; 160 | ``` 161 | 162 | Or can be an arrow function, but if that's the case we can't use the **this** keyword 163 | 164 | ```js 165 | const person = { 166 | name: "Cesar", 167 | sayHello: (greeting = "hey") => { 168 | console.log(`${greeting} ${person.name}`); 169 | }, 170 | }; 171 | ``` 172 | 173 |
174 | 175 | 176 | 177 | ## **OBJECT REFERENCE VS VALUES** 178 | 179 | 180 | 181 | - ### **Compare Objects** 182 | 183 | When we compare objects is important to know that the comparison is done by reference to the object and not the values inside of it. 184 | meaning that we can have: 185 | 186 | ```js 187 | const person1 = { 188 | first: "Cesar", 189 | last: "Gomez", 190 | }; 191 | 192 | const person2 = { 193 | first: "Cesar", 194 | last: "Gomez", 195 | }; 196 | ``` 197 | 198 | and if we compare `person1` vs `person2`, the result should be false 199 | 200 | ```js 201 | person1 === person2; 202 | ``` 203 | 204 |
205 | 206 | 207 | 208 | - ### **Copy Objects** 209 | 210 | Theres a couple ways you can make a copy of an object, one of them is using **spread** (3 dot operator) another way is with `Object.assign` but this is an old way 211 | 212 | ```js 213 | //spread 214 | const person3 = { ...person1 }; 215 | 216 | //Object assign 217 | const person3 = Object.assign({}, person1); 218 | ``` 219 | 220 | > with these ways to copy and object you can only go one level deep 221 | 222 | If you want to do a deeper copy or a deep clone of all of the properties (an object with another object inside) you may use a utility library called [lodash](https://lodash.com/). 223 | 224 | If you do 225 | 226 | ```js 227 | const person3 = person1; 228 | ``` 229 | 230 | This will not do a copy, it just reference or point the person3 to the original person1, meaning that if you update something on one of those the other will be updated with same values as well 231 | 232 |
233 | 234 | 235 | 236 | - ### **Merge Objects** 237 | 238 | The spread also can be helpful to merge 2 or more objects into 1 239 | 240 | ```js 241 | const meatInventory = { 242 | bacon: 2, 243 | sausage: 3, 244 | }; 245 | 246 | const veggieInventory = { 247 | lettuce: 5, 248 | tomatoes: 3, 249 | }; 250 | 251 | //merge 252 | const Inventory = { ...meatInventory, ...veggieInventory }; 253 | 254 | //result 255 | const meatInventory = { 256 | bacon: 2, 257 | sausage: 3, 258 | lettuce: 5, 259 | tomatoes: 3, 260 | }; 261 | ``` 262 | 263 | If you have duplicated values, meaning that the objects that you want to merge contains the same properties but with different values, the merge will take the value of the object that you put at the end, in this case _veggieInventory_ 264 | 265 | If you passed an Object or Array into a function, you will modified: 266 | 267 | ```js 268 | //function 269 | function doStuff(data) { 270 | data.tomatoes = 10000000000; 271 | } 272 | 273 | //run the function with an object as an argument 274 | doStuff(inventory); 275 | ``` 276 | 277 | This will modify the tomatoes property on inventory object to be: 278 | 279 | ```js 280 | const meatInventory = { 281 | bacon: 2, 282 | sausage: 3, 283 | lettuce: 5, 284 | tomatoes: 10000000000, 285 | }; 286 | ``` 287 | 288 |
289 | 290 | 291 | 292 | ## **MAPS** 293 | 294 | Maps are similar to an object. 295 | You can use map if you do ned to maintain the order of the items. 296 | You can not use function (methods) inside a map, they are only to store data. 297 | 298 | Syntax 299 | 300 | ```js 301 | const myMap = new Map(); 302 | ``` 303 | 304 | In order to add/check/remove items to a Map we have the `.set` API, `.has` API, and `.delete` API. 305 | 306 | 307 | 308 | - ### **Set** 309 | 310 | `.set` is useful to add items into a Map 311 | 312 | ```js 313 | const myMap = new Map(); 314 | myMap.set("name", "Cesar"); 315 | myMap.set(100, "This is a number"); 316 | ``` 317 | 318 | the first value of a `.set` is the key, and the second is the value, notice that the key can be whatever type (string, number, array, object, etc). 319 | 320 | You can pass an object into a Map as a key 321 | 322 | ```js 323 | const person1 = { 324 | name: "Cesar", 325 | age: 100, 326 | }; 327 | 328 | //pass the object as a key into the map 329 | myMap.set(person1, "really cool"); 330 | ``` 331 | 332 | Also we can use `.get` to catch the value of a key. 333 | 334 | > Example [here](https://codepen.io/cgope/pen/LYxGPjq) 335 | 336 | 337 | 338 | - ### **Has** 339 | 340 | it works to check if you have an element by key in the Map 341 | 342 | ```js 343 | const myMap = new Map(); 344 | myMap.set("name", "Cesar"); 345 | myMap.set(100, "This is a number"); 346 | 347 | //has 348 | myMap.has("name"); // return true 349 | 350 | myMap.has("last"); // return false 351 | ``` 352 | 353 | 354 | 355 | - ### **Delete** 356 | 357 | you can delete an element of the map by key: 358 | 359 | ```js 360 | const myMap = new Map(); 361 | myMap.set("name", "Cesar"); 362 | myMap.set(100, "This is a number"); 363 | 364 | //has 365 | myMap.delete("name"); 366 | ``` 367 | 368 |
369 | 370 | 371 | 372 | ## **ARRAYS** 373 | 374 | Used for holding a list of items where the order matters. 375 | Each thing inside an array is called **items**, and the position is called **index**. 376 | The number of items in an array is called **length** and each item inside can be any type (string, boolean, number, nested array, etc). 377 | 378 | Syntax: 379 | 380 | ```js 381 | const names = ["item1", "item3", "item3"]; 382 | ``` 383 | 384 |
385 | 386 | 387 | - ### **Access to the index** 388 | 389 | Arrays are referred to as zero based, meaning that the counting starts at zero. 390 | 391 | if we want ot access to any of the index we can do 392 | 393 | ```js 394 | console.log(names[0]); 395 | //this will return the first item 396 | 397 | console.log(names[1]); 398 | // this will return the second item 399 | ``` 400 | 401 | If you want to know how big is we can use `.length` 402 | 403 | ```js 404 | console.log(names.length); 405 | ``` 406 | 407 | To check the last item of an Array: 408 | 409 | ```js 410 | console.log(names[names.length - 1]); 411 | ``` 412 | 413 | 414 | 415 | - ### **Mutable and Immutable and take a copy of an array** 416 | 417 | **Mutable:** methods perform mutations, meaning when something changes the original version of it. 418 | **Immutable:** means that the methods do not change the original thing, they simply return a new array. 419 | 420 | - Mutation method: 421 | 422 | ```js 423 | const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 424 | const numbersBackwards = numbers.reverse(); 425 | 426 | console.log(numbersBackwards); 427 | console.log(numbers); 428 | ``` 429 | 430 | The original array (numbers) has been also reversed, this is a mutation, so we don't need a new variable like `numbersBackwards` because the original array `numbers` has been modified as well 431 | 432 | - Immutable method: 433 | 434 | ```js 435 | const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 436 | const pizzaSlice = numbers.slice(2, 4); 437 | 438 | console.log(numbers); 439 | console.log(pizzaSlice); 440 | ``` 441 | 442 | The slice method take a portion of the original array, in this case position 2 and 4. 443 | This is immutable because the original array still as it is, and slice method create a new array called `pizzaSlice` with position 2 and 4 (items 3, 4) 444 | 445 | Anytime you have to use a mutation method but you need to keep the original, you can take a **copy** the original array 446 | 447 | ```js 448 | const numbersReverse = [...numbers].reverse(); 449 | ``` 450 | 451 |
452 | 453 | 454 | 455 | - ### **Add items** 456 | 457 | You can add items into an array by using the `.push` method 458 | 459 | ```js 460 | const names = ["Cesar", "Wes", "Sharon"]; 461 | 462 | names.push("Lux"); 463 | 464 | console.log(names); 465 | //the output will be : Cesar, wes, Sharon, Lux 466 | ``` 467 | 468 | You can also add items to the front you can use `.unshift` 469 | 470 | ```js 471 | names.unshift("poppy"); 472 | //the output will be : poppy, Cesar, wes, Sharon, Lux 473 | ``` 474 | 475 | If you want to add items to the middle : 476 | 477 | ```js 478 | const bikes = ["bianchi", "miele", "panasonic", "miyata"]; 479 | ``` 480 | 481 | we want to add benotto between miele and panasonic, so: 482 | 483 | ```js 484 | const newBikes = [ 485 | ...bikes.slice(0, 2), //start in position 0, and take the first 2 items 486 | "benotto", 487 | ...bikes.slice(2), // starts adding the items after position 2 488 | ]; 489 | console.log(newBikes); 490 | // output: bianchi, miele, benotto, panasonic, miyata 491 | ``` 492 | 493 |
494 | 495 | 496 | 497 | - ### **Find and remove items** 498 | 499 | If we need to find and remove items we can use a function an return a new array without the item we want to delete. 500 | 501 | I.e we have an array of comments and we want to delete one on them: 502 | 503 | ```js 504 | const comments = [ 505 | { text: "cool beans", id: 123 }, 506 | { text: "love this", id: 133 }, 507 | { text: "nice", id: 233 }, 508 | { text: "good bikes", id: 333 }, 509 | { text: "so good", id: 433 }, 510 | ]; 511 | ``` 512 | 513 | so we have to create a function that find the comment id, delete the comment and return a new array without the comment 514 | 515 | ```js 516 | function deleteComment(id, comments) { 517 | //find the comment id 518 | const commentIndex = comments.findIndex((comment) => comment.id === id); 519 | //return new array without the comment 520 | return [ 521 | ...comments.slice(0, commentIndex), 522 | ...comments.slice(commentIndex + 1), 523 | ]; 524 | } 525 | ``` 526 | 527 |
528 | 529 | 530 | 531 | ## **ARRAY CARDIO - STATIC METHODS** 532 | 533 | - ### **Array.of** 534 | 535 | Is another way to create an array. 536 | The difference between `Array.of()` and the Array constructor is in the handling of integer arguments: `Array.of(7)` creates an array with a single element, 7, whereas `Array(7)` creates an empty array with a length property of 7 537 | 538 | > this implies an array of 7 empty slots, not slots with actual undefined values 539 | 540 |
541 | 542 | - ### **Array.from** 543 | 544 | Take an iterable and returns a new array from that iterable, and also takes a second argument which is referred as a map argument. 545 | You can create a range with this 546 | 547 | ```js 548 | function createRange(start, end) { 549 | const range = Array.from( 550 | { length: end - start + 1 }, 551 | function (item, index) { 552 | return index + start; 553 | } 554 | ); 555 | return range; 556 | } 557 | ``` 558 | 559 | this will be the return 560 | 561 | ![arrayFrom](img/arrayFrom.png) 562 | 563 |
564 | 565 | - ### **Array.isArray** 566 | 567 | Is used to check is its an Array since the `typeOf` doesn't work with arrays, it returns "object" 568 | 569 | ```js 570 | Array.isArray(createRange); 571 | ``` 572 | 573 | The output should be a boolean, in this case true. 574 | 575 |
576 | 577 | - ### **Object.entries - Object.keys - Object.values** 578 | 579 | this is the way to convert an Object into an array, using the keys, values or both (entries). 580 | 581 | ```js 582 | const meats = { 583 | beyond: 10, 584 | beef: 5, 585 | pork: 7, 586 | }; 587 | 588 | console.log(Object.keys(meats)); 589 | console.log(Object.values(meats)); 590 | console.log(Object.entries(meats)); 591 | ``` 592 | 593 | the result is: 594 | 595 | ![ObjectKeysValuesEntries](img/ObkectKeysValuesEntries.png) 596 | 597 | the same thing can be done with the `forEach` for the `Object.entries` 598 | 599 | ```js 600 | Object.entries(meat).forEach(([key, value]) => { 601 | console.log(key, value); 602 | }); 603 | ``` 604 | 605 |
606 | 607 | 608 | 609 | ## **ARRAY CARDIO - INSTANCE METHODS** 610 | 611 | Instance methods are other methods that lives inside on each array. 612 | 613 | - ### **.join()** 614 | 615 | what this does is turns the array into a string, .joins take an argument and that is what you want to join or not 616 | 617 | ```js 618 | const buns = ["egg", "wonder", "brioche"]; 619 | 620 | buns.join(" or "); 621 | //"egg or wonder or brioche" 622 | ``` 623 | 624 | - ### **.split()** 625 | 626 | what this does is turns a string into an array into a string, this is not an array methods, is a string method. 627 | 628 | ```js 629 | const foodString = "Hot dogs, hamburgers, sausages, corn"; 630 | 631 | buns.split(","); 632 | /* 633 | 0: "Hot dog" 634 | 1: "hamburgers" 635 | 2: "sausages" 636 | 3: "corn" 637 | */ 638 | ``` 639 | 640 | - ### **.pop()** 641 | 642 | pop removes the last item of an array, is a mutable method 643 | 644 | ```js 645 | const toppings = [ 646 | "mushrooms", 647 | "tomatoes", 648 | "eggs", 649 | "chili", 650 | "lettuce", 651 | "avocado", 652 | "chiles", 653 | "pickles", 654 | "onions", 655 | "cheese", 656 | ]; 657 | 658 | toppings.pop(); 659 | // ["mushrooms", "tomatoes", "eggs", "chili", "lettuce", "avocado", "chiles", "pickles", "onions"] 660 | ``` 661 | 662 | - ### **.push()** 663 | 664 | add an items to the last position, and return the element removed 665 | 666 | ```js 667 | toppings.push("cheese"); 668 | // ["mushrooms", "tomatoes", "eggs", "chili", "lettuce", "avocado", "chiles", "pickles", "onions", "cheese"] 669 | ``` 670 | 671 | - ### **.shift()** 672 | 673 | removes the first item of an array and return the element removed 674 | 675 | ```js 676 | toppings.shift(); 677 | // ["tomatoes", "eggs", "chili", "lettuce", "avocado", "chiles", "pickles", "onions", "cheese"] 678 | ``` 679 | 680 | - ### **.unshift()** 681 | 682 | add one or more items in the first position of an array 683 | 684 | ```js 685 | toppings.unshift("mushrooms"); 686 | // ["tomatoes", "eggs", "chili", "lettuce", "avocado", "chiles", "pickles", "onions", "cheese"] 687 | ``` 688 | 689 | - ### **.indexOf()** 690 | 691 | returns the index of an item, it works for any types. 692 | 693 | ```js 694 | const avocadoIndex = toppings.indexOf("avocado"); 695 | // 5 696 | ``` 697 | 698 | - ### **.includes()** 699 | 700 | check if an item exist into the array, is not case sensitive 701 | 702 | ```js 703 | toppings.includes("hot sauce"); 704 | // false 705 | ``` 706 | 707 | 708 | 709 | ## **ARRAY CARDIO - CALLBACK METHODS** 710 | 711 | These are instance methods that receive a function as an argument that also are callback 712 | 713 | ```js 714 | const feedback = [ 715 | { comment: "love the burgers", rating: 4 }, 716 | { comment: "horrible service", rating: 2 }, 717 | { comment: "smoothies are great, liked the burger too", rating: 5 }, 718 | { comment: "ambiance needs work", rating: 3 }, 719 | { comment: "i don't like burgers", rating: 1 }, 720 | ]; 721 | ``` 722 | 723 | - ### **find()** 724 | 725 | Return true or false, when it has found the item that it wants 726 | Find the first rating that talks about burger 727 | 728 | ```js 729 | function findBurgerRating(singleFeedback) { 730 | return singleFeedback.comment.includes("burg"); 731 | } 732 | 733 | const burgRating = feedback.find(findBurgerRating); 734 | 735 | console.log(burgRating); 736 | ``` 737 | 738 | We can also do a fnd by word function: 739 | 740 | ```js 741 | function findByWord(word) { 742 | return function (singleFeedback) { 743 | return singleFeedback.comment.includes(word); 744 | }; 745 | } 746 | 747 | const burgRating = feedback.find(findByWord("burg")); 748 | ``` 749 | 750 |
751 | 752 | - ### **filter()** 753 | 754 | Filter is pretty much the same as find but this one returns a new array instead of one item 755 | 756 | ```js 757 | const goodReviews = feedback.filter( 758 | (singleFeedback) => singleFeedback.rating > 2 759 | ); 760 | 761 | console.table(goodReviews); 762 | ``` 763 | 764 | We can do a universal function as well to find by value 765 | 766 | ```js 767 | function filterByMinRating(minRating) { 768 | return function (singleFeedback) { 769 | return singleFeedback.rating > minRating; 770 | }; 771 | } 772 | 773 | const goodReviews = feedback.filter(filterByMinRating(2)); 774 | console.table(goodReviews); 775 | ``` 776 | 777 | - ### **some() and every()** 778 | 779 | having the object meats 780 | 781 | ```js 782 | const meats = { 783 | beyond: 10, 784 | beef: 5, 785 | pork: 7, 786 | }; 787 | ``` 788 | 789 | we need to: 790 | 791 | - 1. Check if there is at least of 5 units of one type of meat with some() 792 | 793 | ```js 794 | const isThereEnoughOfAtLeastOneMeat = Object.values(meats).some( 795 | (meatValue) => (meatValue) => 5 796 | ); 797 | 798 | console.log(isThereEnoughOfAtLeastOneMeat); 799 | ``` 800 | 801 | - 2. Make sure we have at least of 3 units of every meat with every() 802 | 803 | ```js 804 | const isThereEnoughOfEveryMeat = Object.values(meats).every( 805 | (meatValue) => (meatValue) => 3 806 | ); 807 | 808 | console.log(isThereEnoughOfEveryMeat); 809 | ``` 810 | 811 | - ### **sort()** 812 | 813 | having the object toppings 814 | 815 | ```js 816 | const toppings = { 817 | "mushrooms", 818 | "tomatoes", 819 | "eggs", 820 | "chili", 821 | "lettuce", 822 | "avocado", 823 | "chiles", 824 | "pickles", 825 | "onions", 826 | "cheese", 827 | }; 828 | ``` 829 | 830 | we can order alphabetically like: 831 | 832 | ```js 833 | console.log(toppings.sort()); 834 | ``` 835 | 836 | is different if we work with numbers, lets try to organize the numbers from lowest to highest 837 | 838 | ```js 839 | const numbers = [1, 2, 100, 3, 200, 400, 155]; 840 | 841 | const numbersSorted = numbers.sort(function (firstItem, secondItem) { 842 | if (firstItem > secondItem) { 843 | return 1; 844 | } else if (secondItem > firstItem) { 845 | return -1; 846 | } else { 847 | return 0; 848 | } 849 | }); 850 | 851 | /*short way: 852 | const numbersSorted = numbers.sort( 853 | (firstItem, secondItem) => firstItem - secondItem 854 | ); 855 | */ 856 | 857 | console.log(numbersSorted); 858 | ``` 859 | 860 | Try to order the totals from most expensive to least with sort(): 861 | 862 | ```js 863 | const orderTotals = [342, 1002, 523, 34, 634, 854, 1644, 2222]; 864 | 865 | function numberSort(a.b){ 866 | return a - b; 867 | } 868 | 869 | console.log(orderTotals.sort(numberSort)); 870 | ``` 871 | 872 | lets try to sort an object: 873 | 874 | ```js 875 | const prices = { 876 | hotDog: 453, 877 | burger: 765, 878 | sausage: 634, 879 | corn: 234, 880 | }; 881 | 882 | const productsSortedByPrice = Object.entries(prices).sort(function ( 883 | first, 884 | second 885 | ) { 886 | const firstPrice = a[1]; 887 | const secondPrice = b[1]; 888 | return firstPrice - secondPrice; 889 | }); 890 | 891 | console.table(productsSortedByPrice); 892 | 893 | //put back into an object: 894 | console.table(Object.fromEntries(productsSortedByPrice)); 895 | ``` 896 | 897 |
898 | 899 | --- 900 | 901 | back to [Table of Content](tableOfContent.md) 902 | previous [Logic and flow control](07_LogicAndFlowControl.md) 903 | next [Getting loopy](09_GettingLoopy.md) 904 | -------------------------------------------------------------------------------- /09_GettingLoopy.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # **Module #8 - Data types** 4 | 5 | --- 6 | 7 | 8 | 9 | ## **ARRAY FOR EACH** 10 | 11 | is useful for things called side effects. 12 | Side effects is when you are inside of a function and you reach outside of that function to do something else, meaning when you need to loop with some data and do something with each piece of data, like login the value, attaching a event listener for a click, displaying the data on the page, etc. 13 | 14 | Having an array: 15 | 16 | ```js 17 | const toppings = [ 18 | "mushrooms", 19 | "tomatoes", 20 | "eggs", 21 | "chili", 22 | "lettuce", 23 | "avocado", 24 | "chiles", 25 | "pickles", 26 | "onions", 27 | "cheese", 28 | ]; 29 | ``` 30 | 31 | we can loop by doing: 32 | 33 | ```js 34 | function logToppings(topping) { 35 | console.log(topping); 36 | } 37 | 38 | toppings.forEach(logTopping); 39 | ``` 40 | 41 | or with an arrow function: 42 | 43 | ```js 44 | toppings.forEach((topping) => { 45 | console.log(topping); 46 | }); 47 | ``` 48 | 49 | we can do more with `forEach` 50 | 51 | ```js 52 | function logToppings(topping, index, array) { 53 | //Log the topping 54 | console.log(topping); 55 | 56 | //Log the prev topping 57 | const prevTopping = array[index - 1]; 58 | prevTopping ? console.log(prevTopping) : null; 59 | 60 | //log the next topping 61 | const nextTopping = array[index + 1]; 62 | nextTopping ? console.log(nextTopping) : null; 63 | 64 | //if its the last item in the array say good bye 65 | index === array.length - 1 ? console.log('good bye') : console.log('Getting the next topping'); 66 | console.log(-------🍕-------); 67 | } 68 | 69 | toppings.forEach(logTopping); 70 | ``` 71 | 72 |
73 | 74 | 75 | 76 | ## **MAP** 77 | 78 | Map, filter and reduce are useful when you need to take data, do something with that data and return that data that has been modified, massaged or transformed in some way. 79 | 80 | Map is like a machine in a factory, it takes in data, perform an operation and spits it out on the other side. 81 | 82 | > Map will always produce the same length of the array as it starts with. 83 | 84 | Map works with strings, numbers, objects etc... 85 | 86 | some examples: 87 | 88 | ```js 89 | const names = ['wes', 'kait', 'puppy']; 90 | 91 | const orderTotals = [342, 1002, 523, 34, 634, 854, 1644, 2222]; 92 | 93 | const people = [ 94 | { 95 | birthday: 'April 22, 1993', 96 | names { 97 | first: 'Keith', 98 | last: 'Buckley', 99 | } 100 | } 101 | { 102 | birthday: 'January 3, 1975', 103 | names { 104 | first: 'Larry', 105 | last: 'Heep', 106 | } 107 | } 108 | { 109 | birthday: 'February 12, 1944', 110 | names { 111 | first: 'Linda', 112 | last: 'Bermeer', 113 | } 114 | } 115 | ] 116 | ``` 117 | 118 | now we will work with map to do some modifications 119 | 120 | 1. **names array:** Add the word 'Bos' as last name for each name, and put the first letter of each name in capitals 121 | 2. **orderTotals array:** add taxes to each amount. 122 | 3. **people array:** figure it out how old they are and return their full name and birthday in an object 123 | 124 | ```js 125 | // point # 1 126 | function capitalize(word) { 127 | return `${word[0].toUpperCase()}${word.slice(1)}`; 128 | } 129 | function bosify(name) { 130 | return `${name} Bos`; 131 | } 132 | 133 | const fullNames = names.map(capitalize).map(bosify); 134 | console.log(fullNames); 135 | 136 | //point # 2 137 | const orderTotalsWithTax = orderTotals.map((total) => total * 1.13); 138 | console.log(orderTotalsWithTax); 139 | 140 | //point # 3 141 | const cleanPeople = people.map(function (person) { 142 | //get their birthday, getTime will convert into milliseconds javascript format 143 | const birthday = new Date(person.birthday).getTime(); 144 | 145 | //how old they are 146 | const now = Date.now(); 147 | const age = math.floor((now - birthday) / 31536000000); 148 | 149 | //return their full name and birthday in an object 150 | return { 151 | age, 152 | name: `${person.names.first} ${person.names.last}`, 153 | }; 154 | }); 155 | console.table(cleanPeople); 156 | ``` 157 | 158 | > to work with timestamps (milliseconds or dates) you can go to [Epoch converter](https://epoch.vercel.app) 159 | 160 | > If you want to work with dates you must visit [Date functions](https://date-fns.org) 161 | 162 |
163 | 164 | 165 | 166 | ## **FILTER, FIND AND HIGHER ORDER FUNCTIONS** 167 | 168 | - **Filter** 169 | Filter will loop into all the items and return all of the items that matches with what you want. 170 | lets filter the array persons to get the older than 40 years 171 | 172 | ```js 173 | const over40 = cleanPeople.filter((person) => person.age > 40); 174 | 175 | console.table(over40); 176 | ``` 177 | 178 | - **Find** 179 | Filter will only find one item in the array and return it. 180 | 181 | Having the array of student: 182 | 183 | ```js 184 | const students = [ 185 | { 186 | id: "11ce", 187 | first_name: "Dall", 188 | last_name: "Puckring", 189 | }, 190 | { 191 | id: "2958", 192 | first_name: "Margarete", 193 | last_name: "Brandi", 194 | }, 195 | { 196 | id: "565a", 197 | first_name: "Bendicty", 198 | last_name: "Woodage", 199 | }, 200 | { 201 | id: "3a16", 202 | first_name: "Micki", 203 | last_name: "Mattes", 204 | }, 205 | ]; 206 | ``` 207 | 208 | lets find by ID: 209 | 210 | ```js 211 | const student = students.find((stud) => stud.id === "565a"); 212 | 213 | console.log(student); 214 | ``` 215 | 216 | > Find returns the object instead Filter returns the array 217 | 218 | - **Higher order functions** 219 | Function inside another function is what is called higher other function. 220 | With higher order functions we can also go further and write a function to find by properties (id, first name, last name, etc) 221 | 222 | ```js 223 | function findByProp(prop, propWeAreLookingFor) { 224 | return function isStudent(student) { 225 | return student[prop] === propWeAreLookingFor; 226 | }; 227 | } 228 | const student = students.find(findByProp(id, "565a")); 229 | const student2 = students.find(findByProp(first_name, "Micki")); 230 | 231 | console.log(student); 232 | console.log(student2); 233 | ``` 234 | 235 |
236 | 237 | 238 | 239 | ## **REDUCE** 240 | 241 | Reduce does so much and there are a handful of different cases for it. 242 | Reduce it takes in an array of data and it will return a result or a single value. 243 | 244 | lets add all of these up: 245 | 246 | ```js 247 | const orderTotals = [342, 1002, 523, 34, 634, 854, 1644, 2222]; 248 | ``` 249 | 250 | ```js 251 | function tallyNumbers(accumulator, currentTotal) { 252 | console.log(`the current accumulator is ${accumulator}`); 253 | console.log(`the current total is ${currentTotal}`); 254 | console.log("---------------------------"); 255 | //return the accumulator plus the amount of the order 256 | return accumulator + currentTotal; 257 | } 258 | 259 | const allOrders = orderTotals.reduce(tallyNumbers, 0); 260 | 261 | console.log(allOrders); 262 | ``` 263 | 264 | the result is: 265 | 266 | ![reduceOrderTotals](img/reduceOrderTotals.png) 267 | 268 | next example with an inventory: 269 | 270 | ```js 271 | const inventory = [ 272 | { type: "shirt", price: 4000 }, 273 | { type: "pants", price: 4532 }, 274 | { type: "socks", price: 243 }, 275 | { type: "shirt", price: 2343 }, 276 | { type: "pants", price: 2343 }, 277 | { type: "socks", price: 542 }, 278 | { type: "pants", price: 123 }, 279 | ]; 280 | ``` 281 | 282 | First thing is check howe many of each items are there, and total value of all the inventory. 283 | 284 | ```js 285 | function inventoryReducer(counter, item) { 286 | console.log(`looping over ${item.type}`); 287 | 288 | //check if the item exist in or create and increment the type by 1 289 | counter[item.type] = counter[item.type] + 1 || 1; 290 | 291 | //return the total, so the next loop can use it 292 | return counter; 293 | } 294 | 295 | const inventoryCounts = inventory.reduce(inventoryReducer, {}); 296 | 297 | console.log(inventoryCounts); 298 | 299 | //price 300 | const totalInventoryPrice = inventory.reduce( 301 | (acc, item) => acc + item.price, 302 | 0 303 | ); 304 | 305 | console.log(totalInventoryPrice); 306 | ``` 307 | 308 |
309 | 310 | 311 | 312 | ## **REDUCE EXERCISE** 313 | 314 | We will count the characters in the page [MDN reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce). 315 | 316 | First we need to convert all the text into an array, then we need to filter the spaces, comas, parenthesis etc. 317 | After that we need to convert the text into lowercase, and start counting. 318 | 319 | > complete exercise [here](https://codepen.io/cgope/pen/JjWYBMp) 320 | 321 |
322 | 323 | 324 | 325 | ## **FOR, FOR IN, FOR OF, WHILE LOOPS** 326 | 327 | - ### **For** 328 | 329 | syntax: 330 | for ([initialExpression]; [condition]; [incrementExpression]){ 331 | statement; 332 | } 333 | 334 | ```js 335 | for (let i = 0; i <= 10; i++) { 336 | console.log(i); 337 | } 338 | ``` 339 | 340 | This code will start at 0 and increment by 1 until it gets to 10. 341 | For loop is helpful to loop over something like array of numbers. 342 | 343 | ```js 344 | const numbers = [2, 34, 3, 23, 42, 3, 1, 65, 364, 5, 645, 6]; 345 | 346 | //this will give us the length of the array which is 12 (12 items) 347 | for (i = 0; i < numbers.length; number++) { 348 | console.log(i); 349 | } 350 | 351 | //to access on each item in the array: 352 | for (i = 0; i < numbers.length; numbers++) { 353 | console.log(numbers[i]); 354 | } 355 | ``` 356 | 357 | Using the last one we will access to the index on each position 358 | 359 | - ### **For in** 360 | 361 | Use for loop over keys of an object 362 | 363 | ```js 364 | const wes = { 365 | name: "wes", 366 | age: 10, 367 | cool: "true", 368 | }; 369 | 370 | for (const prop in wes) { 371 | console.log(prop); 372 | } 373 | ``` 374 | 375 | - ### **For of** 376 | 377 | Useful looping over iterables, iterables is something that has a length (numbers, string, etc), promises and can handle emojis. 378 | 379 | ```js 380 | const name = "Cesar Gomez"; 381 | 382 | for (const letter of name) { 383 | console.log(letter); 384 | } 385 | 386 | //can be done with numbers as well, doesn't give us the index just the raw value 387 | const numbers = [2, 34, 3, 23, 42, 3, 1, 65, 364, 5, 645, 6]; 388 | 389 | for (number of numbers) { 390 | console.log(number); 391 | } 392 | ``` 393 | 394 | - ### **While loop** 395 | 396 | While loop will take a condition and run infinitely until the condition is false. 397 | 398 | ```js 399 | let cool = 'true; 400 | while(cool === true){ 401 | console.log('you are cool'); 402 | } 403 | ``` 404 | 405 | this example can crash tabs since we don't have an exit condition, so it will run infinitely, we can add an exit condition 406 | 407 | ```js 408 | let cool = true; 409 | let i = 1; 410 | 411 | while (cool === true) { 412 | console.log("you are cool"); 413 | i++; 414 | if (i > 10) { 415 | cool = false; 416 | } 417 | } 418 | ``` 419 | 420 | - ### **Do while loop** 421 | 422 | Thew only difference between while and do while, is that in the second the do will run first and then check the condition after the first run 423 | 424 | ```js 425 | let cool = true; 426 | let i = 1; 427 | 428 | do { 429 | console.log("you are cool"); 430 | i++; 431 | } while (i < 10); 432 | { 433 | cool = false; 434 | } 435 | ``` 436 | 437 |
438 | 439 | --- 440 | 441 | back to [Table of Content](tableOfContent.md) 442 | previous [Data Types](08_DataTypes.md) 443 | next [Harder Practice Exercises](10_HarderPracticeExercises.md) 444 | -------------------------------------------------------------------------------- /10_HarderPracticeExercises.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # **Module #10 - Harder practice exercises** 4 | 5 | --- 6 | 7 | All exercises are in [CodePen](https://codepen.io/collection/XjJQYz) 8 | 9 | 10 | 11 | ## **FACE DETECTION AND CENSORSHIP** 12 | 13 | Example [here](https://codepen.io/cgope/pen/poeEBJX) 14 | 15 | 16 | 17 | ## **SARCASTIC TEXT GENERATOR** 18 | 19 | Example [here](https://codepen.io/cgope/pen/LYWBppQ) 20 | 21 | 22 | 23 | ## **SHOPPING FROM WITH CUSTOM EVENTS, DELEGATION AND LOCAL STORAGE** 24 | 25 | Example [here](https://codepen.io/cgope/pen/ExWBwjx) 26 | 27 | 28 | 29 | ## **BUILDING A GALLERY EXERCISE** 30 | 31 | Example [here](https://codepen.io/cgope/pen/yLbNWBO) 32 | 33 | 34 | 35 | ## **BUILDING A SLIDER** 36 | 37 | Example [here](https://codepen.io/cgope/details/KKmVavv) 38 | 39 |
40 | 41 | --- 42 | 43 | back to [Table of Content](tableOfContent.md) 44 | previous [Getting loopy](09_GettingLoopy.md) 45 | next [Prototypes, 'this', 'new', and inheritance](11_Prototype.md) 46 | -------------------------------------------------------------------------------- /11_Prototype.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # **Module #11 - Prototypes, 'this', 'new', and inheritance** 4 | 5 | --- 6 | 7 | 8 | 9 | ## **THE NEW KEYWORD** 10 | 11 | Using the NEW keyword in Javascript, will create a new object that is an instance of whatever function you have made it from 12 | 13 | ```js 14 | const myDate = new Date('August 11, 2025); 15 | 16 | console.log(myDate); 17 | ``` 18 | 19 | myDate is an instance of Date 20 | 21 | ```js 22 | typeof myDate; 23 | // object 24 | 25 | myDate instanceof Date; 26 | // true 27 | ``` 28 | 29 | functions: 30 | 31 | ![newKeyword](img/newKeyword.png) 32 | 33 |
34 | 35 | 36 | 37 | ## **THE THIS KEYWORD** 38 | 39 | The this keyword in Javascript refers to the instance of an object that a function is bound 40 | 41 | > the this keyword is equals the thing to the left of the dot when you're calling a method. 42 | 43 | ```js 44 | function Pizza(toppings = [], customer) { 45 | console.log("making a pizza"); 46 | //save the toppings that were passed in, to this instance of Pizza 47 | this.toppings = toppings; 48 | this.customer = customer; 49 | this.id = Math.floor(Math.random() * 16777215).toString(16); 50 | } 51 | 52 | const pepperoniPizza = new Pizza(["pepperoni"], "Wes Bos"); 53 | const canadianPizza = new Pizza( 54 | ["pepperoni", "mushrooms", "onion"], 55 | "Kait Bos" 56 | ); 57 | ``` 58 | 59 | Heres the result: 60 | 61 | ![thisKeyword](img/thisKeyword.png) 62 | 63 |
64 | 65 | 66 | 67 | ## **PROTOTYPE REFACTOR OF THE GALLERY EXERCISE** 68 | 69 | Example [here](https://codepen.io/cgope/pen/NWjNBBR) 70 | 71 |
72 | 73 | 74 | 75 | ## **PROTOTYPES AND PROTOTYPAL INHERITANCE** 76 | 77 | If we have a function and we use the **NEW** keyword, it will return an object that is an instance of that object: 78 | 79 | ```js 80 | function Pizza(toppings = [], customer) { 81 | console.log("making a pizza"); 82 | //save the toppings that were passed in, to this instance of Pizza 83 | this.toppings = toppings; 84 | this.customer = customer; 85 | this.id = Math.floor(Math.random() * 16777215).toString(16); 86 | } 87 | 88 | const pepperoniPizza = new Pizza(["pepperoni"], "Wes Bos"); 89 | const canadianPizza = new Pizza( 90 | ["pepperoni", "mushrooms", "onion"], 91 | "Kait Bos" 92 | ); 93 | ``` 94 | 95 | In this case Pepperoni pizza and Canadian pizza are instance of Pizza, and we can attach properties to that instance is by using the **THIS** keyword, so each pizza will have her own properties. 96 | 97 | lets count the number of slices on each pizza by adding a slices property: 98 | 99 | ```js 100 | function Pizza(toppings = [], customer) { 101 | console.log("making a pizza"); 102 | this.toppings = toppings; 103 | this.customer = customer; 104 | this.id = Math.floor(Math.random() * 16777215).toString(16); 105 | 106 | //adding slices property to each pizza 107 | this.slices = 10; 108 | } 109 | ``` 110 | 111 | If we want to track how many pizzas are left, we can use a prototype, since every pizza have to had his own toppings, customer, id and slices but the functionality to eat a pizza is the same for every single pizza. 112 | so instead of put a function on every single instance to prevent the memory uses in the computers, we can put it on the prototype. 113 | 114 | ```js 115 | Pizza.prototype.eat = function () { 116 | if (this.slices > 0) { 117 | this.slices = this.slices - 1; 118 | console.log(`you have ${this.slices} left`); 119 | } else { 120 | console.log(`Sorry!, there's no slices left`); 121 | } 122 | }; 123 | ``` 124 | 125 | so we can use the eat function on every single pizza we want to create: 126 | 127 | ![prototype](img/prototype.png) 128 | 129 |
130 | 131 | 132 | 133 | ## **PROTOTYPE REFACTOR OF THE SLIDER EXERCISE** 134 | 135 | Example [here](https://codepen.io/cgope/pen/dyWXEpp) 136 | 137 |
138 | 139 | 140 | ## **BIND, CALL AND APPLY** 141 | 142 | - ### BIND 143 | 144 | Bind, call and apply, are three function that are used to change the scope of what this is equal to inside of a function or inside of a method. 145 | 146 | > Bind, call and apply will change the scope of the 'THIS' keyword inside of a function or method. 147 | 148 | ```js 149 | const person = { 150 | name: "Wes Bos", 151 | sayHi: function () { 152 | return `Hey ${this.name}`; 153 | }, 154 | }; 155 | 156 | person.sayHi(); 157 | // the output is: hey Wes Bos 158 | ``` 159 | 160 | The 'THIS' keyword is referring to what is at the left of the function, in this case the function is **sayHi()** and what is in the left of the dot is **person** 161 | 162 | but if we have the method sayHi() in his own variable, the 'THIS' keyword will change. 163 | 164 | ![bind](img/bind.png) 165 | 166 | when we use the `person.sayHi()` the 'THIS' keyword is referring to the object, in this case Wes Bos, but when we use the `sayHi()` the 'THIS' keyword is referring to the Window. 167 | 168 | > In Javascript 'THIS' keyword is always defined by where the function is being called, and not where is the function being defined 169 | 170 | we can use the **Bind** to change where 'THIS' keyword is defined, this will change what the 'THIS' keyword is equal or what it's bound too. 171 | 172 | this is useful if we want to use a method from an object with some other information, like use the method **sayHi** to another object: 173 | 174 | ![bind2](img/bind2.png) 175 | 176 | - ### CALL AND APPLY 177 | 178 | Have the same use than bind with some differences: 179 | 180 | - Call and Apply will call the function, instead of returning a function they will call the function 181 | - Apply accept a single array of arguments 182 | 183 | ![call and apply image](img/call,apply.png) 184 | 185 |
186 | 187 | --- 188 | 189 | back to [Table of Content](tableOfContent.md) 190 | previous [Harder practice exercises](10_HarderPracticeExercises.md) 191 | next [Advanced flow control](12_AdvanceFlowControl.md) 192 | -------------------------------------------------------------------------------- /12_AdvancedFlowControl.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # **Module #12 - Advanced flow control** 4 | 5 | --- 6 | 7 | 8 | 9 | ## **THE EVENT LOOP AND CALLBACK HELL** 10 | 11 | Javascript is a single threaded language, that means that only one thing can only be run at a time. 12 | Some other languages are multi thread, that means that they can run multiple process at once 13 | 14 | > Javascript can only ever run one thing at once 15 | 16 | ```JS 17 | console.log("starting"); 18 | 19 | setTimeout(function(){ 20 | console.log("running") 21 | },2000); 22 | 23 | console.log("ending"); 24 | ``` 25 | 26 | the output expected should be: 27 | 28 | - starting 29 | - running 30 | - ending 31 | 32 | but doesn't work that way, the way that Javascript works is that it will parse the first line 33 | 34 | - `console.log("starting");`, then parse the next line 35 | - `setTimeout(function(){ console.log("running") },2000);` 36 | (setTimeout function) so it will "pin" in that and come back in 2 seconds, then go ahead and runs the next line 37 | - `console.log("ending");` then 2 seconds later come back to the callback function that's been queued up 38 | 39 | so based on that the result is: 40 | 41 | - starting 42 | - ending 43 | - running 44 | 45 | ![Event loop and callback hell](img/eventLoopCallbackHell.png) 46 | 47 | Javascript is asynchronous that means is not going to stop running the `setTimeout` function, its going to put this in what we call "the Web API" and then when thats has come back after 2 seconds its going to stick in the callback queue, then when the call stack has a free second when its not currently running anything, its going to reach into the call stack queue run the call back for us 48 | 49 | ![callback queue](img/callbackQueue.png) 50 | 51 | there's a page called [loupe from by Philip Roberts](http://latentflip.com/loupe/?code=JC5vbignYnV0dG9uJywgJ2NsaWNrJywgZnVuY3Rpb24gb25DbGljaygpIHsKICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gdGltZXIoKSB7CiAgICAgICAgY29uc29sZS5sb2coJ1lvdSBjbGlja2VkIHRoZSBidXR0b24hJyk7ICAgIAogICAgfSwgMjAwMCk7Cn0pOwoKY29uc29sZS5sb2coIkhpISIpOwoKc2V0VGltZW91dChmdW5jdGlvbiB0aW1lb3V0KCkgewogICAgY29uc29sZS5sb2coIkNsaWNrIHRoZSBidXR0b24hIik7Cn0sIDUwMDApOwoKY29uc29sZS5sb2coIldlbGNvbWUgdG8gbG91cGUuIik7!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D) that can explain that pretty good 52 | 53 | The **CALLBACK HELL** also named as christmas tree code. 54 | if you need to do one thing after another, you must nest the callbacks inside of each other because they all depend on the previous callback to being called before it can then go ahead and run. 55 | Example: 56 | if you have a text and what to do somethings on on that text 57 | 58 | Things to do: 59 | 60 | 1. change the text to go when clicked 61 | 2. make it a circle after 2 seconds 62 | 3. make it red after 0.5 seconds 63 | 4. make it square after 0.25 seconds 64 | 5. make it purple after 0.3 seconds 65 | 6. fade out after 0.5 seconds 66 | 67 | it will look like this: 68 | 69 | ```JS 70 | go.addEventListener("click", function(event){ 71 | const element = event.currentTarget; 72 | element.textContent = 'GO!'; 73 | setTimeout(function(){ 74 | element.classList.add("circle"); 75 | setTimeout(function (){ 76 | element.classList.add("red"); 77 | setTimeout(function(){ 78 | element.classList.remove("circle"); 79 | setTimeout(function(){ 80 | element.classList.remove("red"); 81 | element.classList.add("purple"); 82 | setTimeout(function(){ 83 | element.classList.add("fade"); 84 | },500) 85 | },300) 86 | },250) 87 | },500); 88 | },2000); 89 | }) 90 | ``` 91 | 92 | > CodePen example [here](https://codepen.io/cgope/details/bGrYPrQ) 93 | 94 | the solution to that is the promise land 95 | 96 |
97 | 98 | 99 | ## **PROMISES** 100 | 101 | Promises is the idea of IOU (i owe you) for something that will happen in the future. 102 | The promise take a callback function, and that callback function takes 2 arguments: 103 | 104 | - resolve function 105 | - reject function 106 | then when its ready, you can resolve the promise, and when it fails the promise will be reject 107 | 108 | in order to create a new promise we have to use the "new" keyword: 109 | 110 | ```JS 111 | function makePizza(toppings){ 112 | return new Promise(function(resolve, reject){ 113 | const amountOfTimeToBake = 500 + (toppings.length * 200) 114 | // wait for the pizza to cook 115 | setTimeout(function(){ 116 | // when you are ready, you can resolve this promise 117 | resolve(`Heres your pizza with the toppings ${toppings.join (' ')}`); 118 | }, amountOfTimeToBake) 119 | }); 120 | } 121 | ``` 122 | 123 | now in other to access to the resolve value of the pizza is with `then()` that receive a callback function and you can chain how many `then()` as its needed. 124 | 125 | ```JS 126 | makePizza(['peperoni']) 127 | .then(function(pizza){ 128 | console.log(pizza); 129 | return makePizza(['ham', 'cheese']) 130 | }) 131 | .then(function(pizza){ 132 | console.log(pizza); 133 | return makePizza(['hot pepper', 'onion', 'feta']) 134 | }) 135 | .then(function(pizza){ 136 | console.log(pizza); 137 | return makePizza(['peperoni', 'mushrooms', 'onion']) 138 | }) 139 | .then(function(pizza){ 140 | console.log('All done, heres yor last pizza'); 141 | console.log(pizza); 142 | }) 143 | ``` 144 | 145 | we can use `Promise.all` if you want to know when all promises are done 146 | 147 | ```JS 148 | function makePizza(toppings){ 149 | return new Promise(function(resolve, reject){ 150 | const amountOfTimeToBake = 500 + (toppings.length * 200) 151 | // wait for the pizza to cook 152 | setTimeout(function(){ 153 | // when you are ready, you can resolve this promise 154 | resolve(`Heres your pizza with the toppings ${toppings.join (' ')}`); 155 | }, amountOfTimeToBake) 156 | }); 157 | } 158 | 159 | // run them concurrently 160 | const pizzaPromise1 = makePizza(['ham', 'cheese']); 161 | const pizzaPromise2 = makePizza(['hot pepper', 'onion', 'feta']); 162 | const pizzaPromise3 = makePizza(['peperoni', 'mushrooms', 'onion']); 163 | 164 | const dinnerPromise = Promise.all([pizzaPromise1, pizzaPromise2, pizzaPromise3]); 165 | 166 | dinnerPromise.then(function(['hamAndCheese', 'hottie', 'canadian']){ 167 | console.log(hamAndCheese, hottie, canadian) 168 | }) 169 | ``` 170 | 171 | if you want to know the first promise that gets resolve you can use `Promise.race()` 172 | 173 | ```JS 174 | function makePizza(toppings){ 175 | return new Promise(function(resolve, reject){ 176 | const amountOfTimeToBake = 500 + (toppings.length * 200) 177 | // wait for the pizza to cook 178 | setTimeout(function(){ 179 | // when you are ready, you can resolve this promise 180 | resolve(`Heres your pizza with the toppings ${toppings.join (' ')}`); 181 | }, amountOfTimeToBake) 182 | }); 183 | } 184 | 185 | // run them concurrently 186 | const pizzaPromise1 = makePizza(['ham', 'cheese']); 187 | const pizzaPromise2 = makePizza(['hot pepper', 'onion', 'feta']); 188 | const pizzaPromise3 = makePizza(['peperoni', 'mushrooms', 'onion']); 189 | 190 | const firstPizzaPromise = Promise.race([pizzaPromise1, pizzaPromise2, pizzaPromise3]); 191 | 192 | firstPizzaPromise.then( pizza => { 193 | console.log('the first pizza, its done!'); 194 | console.log(pizza); 195 | }) 196 | ``` 197 | 198 |
199 | 200 | 201 | ## **PROMISES ERROR HANDLING** 202 | 203 | The way that you handle errors is with `catch()` at the end. 204 | 205 | ```JS 206 | function makePizza(toppings){ 207 | return new Promise(function(resolve, reject){ 208 | // reject if ppl try with pineapple 209 | if(toppings.includes('pineapple')){ 210 | reject('Sorry =[, you can not order pizza with pineapple') 211 | } 212 | const amountOfTimeToBake = 500 + (toppings.length * 200) 213 | setTimeout(function(){ 214 | resolve(`Heres your pizza with the toppings ${toppings.join (' ')}`); 215 | }, amountOfTimeToBake) 216 | }); 217 | } 218 | 219 | makePizza(['cheese', 'pineapple']) 220 | .then(pizza => { 221 | console.log(pizza); 222 | }).catch(error => { 223 | console.log(error); 224 | }) 225 | ``` 226 | 227 | we can handle errors in a function: 228 | 229 | ```JS 230 | function handleError(error){ 231 | console.log(error) 232 | } 233 | 234 | makePizza(['ham', 'cheese']) 235 | .then(pizza => { 236 | console.log(pizza); 237 | return makePizza(['pineapple', 'cheese']) 238 | }) 239 | .then(pizza => { 240 | console.log(pizza); 241 | return makePizza(['peperoni', 'mushrooms', 'onion']) 242 | }).catch(handleError) 243 | ``` 244 | 245 | in this case we can not have the last pizza because the previous one have pineapple, in order to fix that we can use `Promise.allSettled()` 246 | 247 | ```JS 248 | function makePizza(toppings){ 249 | return new Promise(function(resolve, reject){ 250 | // reject if ppl try with pineapple 251 | if(toppings.includes('pineapple')){ 252 | reject('Sorry =[, you can not order pizza with pineapple') 253 | } 254 | const amountOfTimeToBake = 500 + (toppings.length * 200) 255 | setTimeout(function(){ 256 | resolve(`Heres your pizza with the toppings ${toppings.join (' ')}`); 257 | }, amountOfTimeToBake) 258 | }); 259 | } 260 | // all settled 261 | const pizzaPromise1 = makePizza(['ham', 'cheese']); 262 | const pizzaPromise2 = makePizza(['pineapple', 'cheese']); 263 | const pizzaPromise3 = makePizza(['peperoni', 'mushrooms', 'onion']); 264 | 265 | const dinnerPromise = Promise.allSettled([pizzaPromise1, pizzaPromise2, pizzaPromise3]).catch(handleError); 266 | 267 | dinnerPromise.then( results => { 268 | console.log('your results!'); 269 | console.log(results); 270 | }) 271 | ``` 272 | 273 |
274 | 275 | 276 | ## **REFACTORING THE EVENT LOOP AND CALLBACK HELL EXERCISE TO PROMISE LAND** 277 | 278 | the exercise is in CodePen: 279 | 280 | > the CodePen example is [here](https://codepen.io/cgope/pen/ExvoeaZ) 281 | 282 |
283 | 284 | ```JS 285 | // function wait in millisecond 286 | const wait = (ms = 0) => new Promise(resolve => setTimeout(resolve, ms)); 287 | 288 | const go = document.querySelector('.go'); 289 | 290 | function animate(event){ 291 | const element = event.currentTarget; 292 | 293 | // 1. change the text to go when clicked 294 | element.textContent = 'GO!'; 295 | wait(2000) 296 | .then(()=>{ 297 | // 2. make it a circle after 2 seconds 298 | element.classList.add("circle"); 299 | return wait(500); 300 | }) 301 | .then(()=>{ 302 | // 3. make it red after 0.5 seconds 303 | element.classList.add("red"); 304 | return wait(250); 305 | }) 306 | .then(()=>{ 307 | // 4. make it square after 0.25 seconds 308 | element.classList.remove("circle"); 309 | return wait(300) 310 | }) 311 | .then(()=>{ 312 | // 5. make it purple after 0.3 seconds 313 | element.classList.remove("red"); 314 | element.classList.add("purple"); 315 | return wait(500) 316 | }) 317 | .then(()=>{ 318 | // 6. fade out after 0.5 seconds 319 | element.classList.add("fade"); 320 | }) 321 | .catch(error => { 322 | console.log(error); 323 | }) 324 | } 325 | 326 | go.addEventListener('click', animate); 327 | ``` 328 | 329 |
330 | 331 | 332 | ## **ASYNC AWAIT** 333 | 334 | Async-Await is a new syntax that will allow us to use the keyword **async** and the keyword **await** for a much nicer/easier to read looking code 335 | 336 | if we want to display une message and after 2 seconds other message, like 337 | 338 | ```JS 339 | // timer function 340 | function wait (ms = 0){ 341 | new Promise(resolve =>{ 342 | setTimeout(resolve, ms) 343 | }) 344 | } 345 | // display message 346 | function go(){ 347 | console.log('starting'); 348 | wait(2000); 349 | console.log('ending') 350 | } 351 | ``` 352 | 353 | it will not work due to the wait function will go to the callback queue, we can use async-await to solve that: 354 | 355 | ```JS 356 | // timer function 357 | function wait (ms = 0){ 358 | new Promise(resolve =>{ 359 | setTimeout(resolve, ms) 360 | }) 361 | } 362 | // display message 363 | async function go(){ 364 | console.log('starting'); 365 | await wait(2000); 366 | console.log('ending') 367 | } 368 | ``` 369 | 370 | this will run the first message `starting` and after 2 seconds will display the second message `ending` 371 | 372 | we can use async in every type of function and objects 373 | 374 | ```JS 375 | // function declaration 376 | async function fd (){ 377 | 378 | } 379 | 380 | // arrow functions 381 | const arrowFd = async ()=>{ 382 | 383 | } 384 | 385 | // call back 386 | window.addEventListener('click', async function(){ 387 | 388 | }) 389 | 390 | // object 391 | const person{ 392 | sayHi: async function(){ 393 | 394 | }, 395 | // method shorthand for object 396 | async sayHi(){ 397 | 398 | }, 399 | // function property 400 | sayHi: async () => { 401 | 402 | } 403 | } 404 | 405 | ``` 406 | 407 | Refactoring the event loop callback hell to async 408 | 409 | > CodePen example [here](https://codepen.io/cgope/pen/QWMaVxy); 410 | 411 | ```JS 412 | // function wait in milisecond 413 | const wait = (ms = 0) => new Promise(resolve => setTimeout(resolve, ms)); 414 | 415 | const go = document.querySelector('.go'); 416 | 417 | async function animate(event){ 418 | const element = event.currentTarget; 419 | 420 | // 1. change the text to go when clicked 421 | element.textContent = 'GO!'; 422 | await wait(2000); 423 | // 2. make it a circle after 2 seconds 424 | element.classList.add("circle"); 425 | await wait(500); 426 | // 3. make it red after 0.5 seconds 427 | element.classList.add("red"); 428 | await wait(250); 429 | // 4. make it square after 0.25 seconds 430 | element.classList.remove("circle"); 431 | await wait(300); 432 | // 5. make it purple after 0.3 seconds 433 | element.classList.remove("red"); 434 | element.classList.add("purple"); 435 | await wait(500); 436 | // 6. fade out after 0.5 seconds 437 | element.classList.add("fade"); 438 | } 439 | 440 | go.addEventListener('click', animate); 441 | ``` 442 | 443 |
444 | 445 | 446 | ## **ASYNC AWAIT ERROR HANDLING** 447 | 448 | There are 4 ways to handle error, the first two are with `try` and `catch`, anything foes wrong inside the **try** it won't break the application it will just fail over the **catch** portion 449 | 450 | we have a function to make pizza: 451 | 452 | ```JS 453 | function makePizza(toppings){ 454 | return new Promise(function(resolve, reject){ 455 | // reject if ppl try with pineapple 456 | if(toppings.includes('pineapple')){ 457 | reject('Sorry =[, you can not order pizza with pineapple') 458 | } 459 | const amountOfTimeToBake = 500 + (toppings.length * 200) 460 | setTimeout(function(){ 461 | resolve(`Heres your pizza with the toppings ${toppings.join (' ')}`); 462 | }, amountOfTimeToBake) 463 | }); 464 | } 465 | ``` 466 | 467 | - lets see how try and catch works: 468 | 469 | ```JS 470 | async function go(){ 471 | try{ 472 | const pizza = await makePizza(['pineapple']); 473 | console.log(pizza); 474 | }catch(error){ 475 | console.log(error); 476 | } 477 | } 478 | ``` 479 | 480 | - try catch promise handling: 481 | 482 | ```JS 483 | function handleError(error){ 484 | console.log(error); 485 | } 486 | 487 | async function go(){ 488 | const pizza = await makePizza(['pineapple']).catch(handleError); 489 | console.log(pizza); 490 | } 491 | ``` 492 | 493 | or you can use catch when you call the function: 494 | 495 | ```JS 496 | function handleError(error){ 497 | console.log(error); 498 | } 499 | 500 | async function go(){ 501 | const pizza = await makePizza(['pineapple']); 502 | console.log(pizza); 503 | } 504 | 505 | go().catch(handleError); 506 | ``` 507 | 508 | - higher order functions: 509 | 510 | ```JS 511 | function handleError(error){ 512 | console.log(error); 513 | } 514 | 515 | //make a safe function with higher order functions 516 | function makeSafe(fn, errorHandler){ 517 | return function (){ 518 | fn().catch(errorHandler) 519 | } 520 | } 521 | 522 | const safeGo = makeSafe(go, handleError); 523 | 524 | safeGo(); 525 | ``` 526 | 527 |
528 | 529 | 530 | ## **ASYNC AWAIT PROMPT UI** 531 | 532 | > CodePen example [here](https://codepen.io/cgope/pen/KKvZbzw) 533 | 534 |
535 | 536 | 537 | ## **ASYNC AWAIT TYPE UI** 538 | 539 | - way one - for of loop 540 | 541 | > CodePen example [here](https://codepen.io/cgope/pen/GRvQJxo) 542 | 543 | - way one - recursion 544 | > CodePen example [here](https://codepen.io/cgope/pen/qBXxdGW) 545 | 546 |
547 | 548 | --- 549 | 550 | back to [Table of Content](tableOfContent.md) 551 | previous [Advanced flow control](11_Prototype.md) 552 | next [Ajax and fetching data](13_AjaxAndFetchingData.md) 553 | -------------------------------------------------------------------------------- /13_AjaxAndFetchingData.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # **Module #13 - Ajax and fetching data** 4 | 5 |
6 | 7 | 8 | ## **AJAX AND API** 9 | 10 | The oder use for async-await and promises is fetching data from what's called an API (Application program interface). 11 | 12 | > API in other words is some way that you can talk to a machine in a somewhat of standardized procedure. 13 | 14 | AJAX stands for: Asynchronous Javascript and XML. 15 | XML is another way to receive data, but now is replaced by JSON (Javascript Object Notation). 16 | 17 | in order to get data from an API we need the **endpoint** which is the URL, for instance GitHub: https://api.github.com/users/wesbos 18 | 19 | so we will do something like: 20 | 21 | ```JS 22 | const endpoint = 'https://api.github.com/users/wesbos' 23 | ``` 24 | 25 | then we need to call `fetch()` API and pass the endpoint, that will return a promise: 26 | 27 | ```JS 28 | const endpoint = 'https://api.github.com/users/wesbos' 29 | 30 | const wesPromise = fetch(endpoint); 31 | console.log(wesPromise); 32 | ``` 33 | 34 | ![ajaxFetch](img/ajaxFetch.png) 35 | this come back with the data, but if you wanna get that data back into javascript, you can use `then()` 36 | 37 | ```JS 38 | // handle error function 39 | function handleError(error){ 40 | console.log(error); 41 | } 42 | const endpoint = 'https://api.github.com/users/wesbos' 43 | 44 | const wesPromise = fetch(endpoint); 45 | // 46 | wesPromise.then(response => { 47 | //in the prototype theres a method called json, we can use it to get data in json format 48 | return response.json(); 49 | //response.json return another promise, so then is needed to catch the data 50 | }) 51 | .then( 52 | data => { 53 | console.log(data); 54 | console.log(data.blog); 55 | console.log(data.name); 56 | console.log(data.location); 57 | }) 58 | .catch(handleError); 59 | ``` 60 | 61 | ![ajax data](img/ajaxData.png) 62 | 63 | its like double promise, se first one gets the response and the second one gets the response and turn into json for us. 64 | 65 | > [here's](https://codepen.io/cgope/pen/JjypKRo) a CodePen with the exercise using async-await with fetch 66 | 67 |
68 | 69 | 70 | ## **CORS AND RECIPES** 71 | 72 | CORS means Cross origin resource sharing. 73 | 74 | Origin means websites: 75 | 76 | wesbos (origin) <-- share data --> github (origin) 77 | 78 | by default you're not allow to share data between origins, meaning that websites cannot talk to each other from one domain to another domain name. 79 | 80 | if you want to get data from github, that page needs to implement something called CORS policy (this happens on the server) 81 | 82 | > in that case github has to say something like "wesbos.com is allowed to ask for data and we will return it, that is safe" 83 | 84 | > [here](https://codepen.io/cgope/pen/oNeEWGO) a CodePen exercise 85 | 86 |
87 | 88 | 89 | ## **DAD JOKES** 90 | 91 | > CodePen example [here](https://codepen.io/cgope/pen/VwzQNgB) 92 | 93 |
94 | 95 | 96 | ## **CURRENCY CONVERTER** 97 | 98 | > CodePen example [here](https://codepen.io/cgope/pen/ZEJxGGe) 99 | 100 |
101 | 102 | --- 103 | 104 | back to [Table of Content](tableOfContent.md) 105 | previous [Advanced flow control](11_Prototype.md) 106 | next [Ajax and fetching data](14_ESModulesAndStructuringLargerApps.md) 107 | -------------------------------------------------------------------------------- /14_ESModulesAndStructuringLargerApps.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # **Module #14 - ES Modules and structuring Larger Apps** 4 | 5 |
6 | 7 | 8 | ## **Modules** 9 | 10 | Modules are a way to structure and organize Javascript to share functionality and data across multiple files and/or projects. 11 | 12 | Characteristics: 13 | 14 | - Modules have their own scope, we don't need to worry about global variables. 15 | > NOTE: variables that you create inside a module it will be available only in that file, nowhere else 16 | - Modules can hold anything (functionality, data, config, etc). 17 | 18 | Supposing that we have the following structure: 19 | 20 | ![Modules structure](img/ModulesStructure.png) 21 | 22 | we can load each javascript file in the body like: 23 | 24 | ```HTML 25 | 26 | 27 | 28 | 29 | 30 | ``` 31 | 32 | but instead of doing that, we can use modules and use the script.js as our entry point and share data, functionality etc with modules by adding the attribute type and set to module: 33 | 34 | ```HTML 35 | 36 | 37 | 38 | ``` 39 | 40 | if we need to use a function that is our `utils.js` we can imported into our `script.js` 41 | 42 | there are two types to export files 43 | 44 | - **named exports:** they have the `export` word in front of the variable declaration/function definition or when they exported there will be curly brackets. 45 | You can have as many named exports as you want. 46 | 47 | ![namedExports](img/namedExport.png) 48 | 49 | - **default exports:** you can have only one per module, you can exports default as follow 50 | 51 | ![namedExports](img/exportDefault.png) 52 | 53 | there are two types to export files 54 | 55 | - **named imports:** you need to use the word `import` then in curly brackets the named exports and the path when you want to import, in this case `util.js` 56 | 57 | ![namedImports](img/namedImport.png) 58 | 59 | - **default imports:** 60 | 61 | ![importDefault](img/importDefault.png) 62 | 63 | you can rename the import as you wanted, for example the `returnHi` function to `sayHi` 64 | 65 | ![renameImports](img/renameImports.png) 66 | 67 | ### **Documentation:** 68 | 69 | [modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) 70 | [imports](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) 71 | [exports](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) 72 | 73 |
74 | 75 | --- 76 | 77 | back to [Table of Content](tableOfContent.md) 78 | previous [Ajax and fetching data](13_AjaxAndFetchingData) 79 | next [Final round exercises](15_FinalRoundExercises.md) 80 | -------------------------------------------------------------------------------- /img/ModulesStructure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/ModulesStructure.png -------------------------------------------------------------------------------- /img/ObkectKeysValuesEntries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/ObkectKeysValuesEntries.png -------------------------------------------------------------------------------- /img/ajaxData.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/ajaxData.png -------------------------------------------------------------------------------- /img/ajaxFetch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/ajaxFetch.png -------------------------------------------------------------------------------- /img/arrayFrom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/arrayFrom.png -------------------------------------------------------------------------------- /img/bind.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/bind.png -------------------------------------------------------------------------------- /img/bind2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/bind2.png -------------------------------------------------------------------------------- /img/bubblingCapture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/bubblingCapture.png -------------------------------------------------------------------------------- /img/call,apply.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/call,apply.png -------------------------------------------------------------------------------- /img/callbackQueue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/callbackQueue.png -------------------------------------------------------------------------------- /img/coercion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/coercion.png -------------------------------------------------------------------------------- /img/eventLoopCallbackHell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/eventLoopCallbackHell.png -------------------------------------------------------------------------------- /img/exportDefault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/exportDefault.png -------------------------------------------------------------------------------- /img/function-definition.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/function-definition.jpg -------------------------------------------------------------------------------- /img/importDefault.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/importDefault.png -------------------------------------------------------------------------------- /img/namedExport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/namedExport.png -------------------------------------------------------------------------------- /img/namedImport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/namedImport.png -------------------------------------------------------------------------------- /img/newKeyword.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/newKeyword.png -------------------------------------------------------------------------------- /img/prototype.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/prototype.png -------------------------------------------------------------------------------- /img/reduceOrderTotals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/reduceOrderTotals.png -------------------------------------------------------------------------------- /img/renameImports.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/renameImports.png -------------------------------------------------------------------------------- /img/thisKeyword.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/thisKeyword.png -------------------------------------------------------------------------------- /img/truthyFalsy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CsarGomez/beginnersJavascriptNotes/014dcb56605b5aa70684a4e8baaa0dc24b0d5edd/img/truthyFalsy.png -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 |

Beginners Javascript notes

2 | 3 |

4 | 5 |

6 |
7 | 8 | ### Course link: [Beginners Javascript](beginnersjavascript.com) 9 | ### GitHub link: [Repository](https://github.com/wesbos/beginner-javascript) 10 | ### Author: [Wes Bos](wesbos.com) 11 | ## [Table of Content](tableOfContent.md) 12 |
13 | 14 | --- 15 | 16 |

17 | This are my personal notes about the Beginners Javascript course from Wes Bos, please feel free to PR, clone, fork or whatever you want to do. 18 |

19 |

20 | Beginners Javascript course notes are not totally updated, i'm updating a soon as im completing the course modules. 21 |

-------------------------------------------------------------------------------- /tableOfContent.md: -------------------------------------------------------------------------------- 1 | # **Table of content:** 2 | 3 | ## **Module #1 [The basics](01_basics.md)** 4 | 5 | - [loading and running javascript](01_basics.md#loading) 6 | - [variables](01_basics.md#variables) 7 | - [Type of variables](01_basics.md#typpeOfVariables) 8 | - [Strings](01_basics.md#strings) 9 | - [Numbers](01_basics.md#numbers) 10 | - [Objects](01_basics.md#objects) 11 | - [Null and Undefined](01_basics.md#null_undefined) 12 | - [Booleans and equality](01_basics.md#booleans) 13 | 14 | ## **Module #2 [Functions](02_functions.md)** 15 | 16 | - [Build functions](02_functions.md#buildFunctions) 17 | - [Parameters and arguments](02_functions.md#parametersArguments) 18 | - [Different ways to declare a function](02_functions.md#waysFunctions) 19 | - [Regular function declaration](02_functions.md#regular) 20 | - [anonymous](02_functions.md#anon) 21 | - [Function expression](02_functions.md#expression) 22 | - [Arrow function](02_functions.md#arrow) 23 | - [Returning an Object](02_functions.md#returnObject) 24 | - [IIFE - Immediately Invoked Function Expression](02_functions.md#iife) 25 | - [Mothods](02_functions.md#methods) 26 | - [Callback Functions](02_functions.md#callback) 27 | 28 | ## **Module #3 [The tricky bits](03_bits.md)** 29 | 30 | - [Scope](03_bits.md#scope) 31 | - [Global variables](03_bits.md#globalVariables) 32 | - [Function scope](03_bits.md#functionScope) 33 | - [Block scope](03_bits.md#blockScope) 34 | - [Hoisting](03_bits.md#hoisting) 35 | - [Closures](03_bits.md#closures) 36 | 37 | ## **Module #4 [The DOM](04_dom.md)** 38 | 39 | - [Selecting elements](04_dom.md#selectElements) 40 | - [Elements properties and methods](04_dom.md#elementPropertiesAndMethods) 41 | - [Working with classes](04_dom.md#workingWithClasses) 42 | - [Build in and custom data attributes](04_dom.md#BuildInAndCustomDataAttributes) 43 | - [Creating HTML](04_dom.md#CreatingHTML) 44 | - [HTML from strings and XSS](04_dom.md#HTMLFromStringsAndXSS) 45 | - [Traversing and removing nodes](04_dom.md#TraversingAndRemovingNodes) 46 | 47 | ## **Module #5 [Events](04_events.md)** 48 | 49 | - [Event listener](05_events.md#eventListener) 50 | - [Targets, bubbling, propagation and capture](05_events.md#TargetsBubblingPropagationCapture) 51 | - [Prevent default and form events](05_events.md#PreventDefaultAndFormEvents) 52 | - [Accessibility gotchas and keyboard codes](05_events.md#AccessibilityGotchasAndKeyboardCodes) 53 | 54 | ## **Module #6 [Serious practice exercises](06_SeriousPractice.md)** 55 | 56 | - [Etch-a-sketch](06_SeriousPractice.md#Etch-a-sketch) 57 | - [Click Outside Modal](06_SeriousPractice.md#Click-Outside-Modal) 58 | - [Scroll Events and Intersection Observer](06_SeriousPractice.md#ScrollEvents-IntersectionObserver) 59 | - [Tabs](06_SeriousPractice.md#tabs) 60 | 61 | ## **Module #7 [Logic and flow control](07_LogicAndFlowControl.md)** 62 | 63 | - [BEDMAS](07_LogicAndFlowControl.md#bedmas) 64 | - [Flow control - if statements, function, returns, truthy, falsy](07_LogicAndFlowControl.md#flowControlIfFunctionReturnsTruthyFalsy) 65 | - [Statements](07_LogicAndFlowControl.md#statement) 66 | - [If statements inside a function](07_LogicAndFlowControl.md#ifStatement) 67 | - [Operators](07_LogicAndFlowControl.md#operators) 68 | - [Truthy Falsy](07_LogicAndFlowControl.md#truthyFalsy) 69 | - [Coercion, ternaries and conditional abuse](07_LogicAndFlowControl.md#coercionTernariesAndConditionAbuse) 70 | - [Coercion](07_LogicAndFlowControl.md#coercion) 71 | - [Ternaries](07_LogicAndFlowControl.md#ternaries) 72 | - [Conditional Abuse](07_LogicAndFlowControl.md#conditionalAbuse) 73 | - [Blockless if statements](07_LogicAndFlowControl.md#blockless) 74 | - [Case switch and animating a turtle with CSS variables](07_LogicAndFlowControl.md#switchTurtleWithCSS) 75 | - [Intervals and timers](07_LogicAndFlowControl.md#intervalsTimers) 76 | - [Timers](07_LogicAndFlowControl.md#timeout) 77 | - [Intervals](07_LogicAndFlowControl.md#intervals) 78 | - [Clear Timers and Intervals](07_LogicAndFlowControl.md#clearTimersAndIntervals) 79 | 80 | ## **Module #8 [Data types](08_DataTypes.md)** 81 | 82 | - [Objects](08_DataTypes.md#objects) 83 | - [Cerate objects](08_DataTypes.md#createObject) 84 | - [Adding/modify objects properties](08_DataTypes.md#add/modObject) 85 | - [Frozen Object](08_DataTypes.md#frozenObject) 86 | - [Delete Object properties](08_DataTypes.md#deleteObject) 87 | - [Function inside object](08_DataTypes.md#functionObject) 88 | - [Object reference vs values](08_DataTypes.md#objectRefVal) 89 | - [Compare objects](08_DataTypes.md#objectCompare) 90 | - [Copy objects](08_DataTypes.md#objectCopy) 91 | - [Merge objects](08_DataTypes.md#objectMerge) 92 | - [Maps](08_DataTypes.md#maps) 93 | - [Set](08_DataTypes.md#setMap) 94 | - [Has](08_DataTypes.md#hasMap) 95 | - [Delete](08_DataTypes.md#deleteMap) 96 | - [Arrays](08_DataTypes.md#arrays) 97 | - [Access to index](08_DataTypes.md#access2Index) 98 | - [Mutable and immutable](08_DataTypes.md#mutableImmutable) 99 | - [Add items](08_DataTypes.md#addItems) 100 | - [Find and remove items](08_DataTypes.md#findRemove) 101 | - [Array cardio - static methods](08_DataTypes.md#staticMethods) 102 | - [Array cardio - instance methods](08_DataTypes.md#instanceMethods) 103 | - [Array cardio - callback methods](08_DataTypes.md#instanceMethods) 104 | 105 | ## **Module #9 [Getting Loopy](09_GettingLoopy.md)** 106 | 107 | - [Array .forEach](09_GettingLoopy.md#forEach) 108 | - [Mapping](09_GettingLoopy.md#mapping) 109 | - [Filter, find and higher order functions](09_GettingLoopy.md#filterFindHigherOrderFunctions) 110 | - [Reduce](09_GettingLoopy.md#reduce) 111 | - [Reduce exercise](09_GettingLoopy.md#reduceExercise) 112 | - [For, for in, for of and while loops](09_GettingLoopy.md#forForInForOfWhileLoops) 113 | 114 | ## **Module #10 [Harder practice exercises](10_HarderPracticeExercises.md)** 115 | 116 | - [Face detection and censorship](10_HarderPracticeExercises.md#FaceDetectionAndCensorship) 117 | - [Sarcastic text generator](10_HarderPracticeExercises.md#SarcasticTextGenerator) 118 | - [Shopping from with custom events, delegation and local storage](10_HarderPracticeExercises.md#ShoppingFromCustomEventsDelegationLocalStorage) 119 | - [Building a gallery exercise](10_HarderPracticeExercises.md#BuildingGalleryExercise) 120 | - [Building a slider](10_HarderPracticeExercises.md#BuildingSlider) 121 | 122 | ## **Module #11 [Prototypes, 'this', 'new', and inheritance](11_Prototype.md)** 123 | 124 | - [The new keyword](11_Prototype.md#TheNewKeyword) 125 | - [The this keyword](11_Prototype.md#TheThisKeyword) 126 | - [Prototype refactor of the gallery exercise](11_Prototype.md#PrototypeRefactorOfTheGalleryExercise) 127 | - [Prototypes and prototypal inheritance](11_Prototype.md#PrototypesAndPrototypalInheritance) 128 | - [Prototype refactor of the slider exercise](11_Prototype.md#PrototypeRefactorOfTheSliderExercise) 129 | - [Bind, call and apply](11_Prototype.md#BindCallAndApply) 130 | 131 | ## **Module #12 [Advanced flow control](12_AdvancedFlowControl.md)** 132 | 133 | - [The event loop and callback hell](12_AdvancedFlowControl.md#TheEventLoopAndCallbackHell) 134 | - [Promises](12_AdvancedFlowControl.md#Promises) 135 | - [Promises Error Handling](12_AdvancedFlowControl.md#PromisesErrorHandling) 136 | - [Refactoring callback hell to promise](12_AdvancedFlowControl.md#EventLoopCallbackHellRefactor) 137 | - [Async Await](12_AdvancedFlowControl.md#AsyncAwait) 138 | - [Async Await Error Handling](12_AdvancedFlowControl.md#AsyncAwaitErrorHandling) 139 | - [Async Await Prompt UI](12_AdvancedFlowControl.md#AsyncAwaitPromptUI) 140 | - [Async Await Typer UI](12_AdvancedFlowControl.md#AsyncAwaitTypeUI) 141 | 142 | ## **Module #13 [Ajax and fetching data](13_AjaxAndFetchingData.md)** 143 | 144 | - [Ajax and API](13_AjaxAndFetchingData.md#AjaxAndAPI) 145 | - [CORS and recipes](13_AjaxAndFetchingData.md#CorsAndRecipes) 146 | - [Dad jokes](13_AjaxAndFetchingData.md#dadJokes) 147 | - [Currency converter](13_AjaxAndFetchingData.md#CurrencyConverter) 148 | 149 | ## **Module #14 [ES Modules and structuring Larger Apps](14_ESModulesAndStructuringLargerApps.md)** 150 | 151 | - [Modules](14_ESModulesAndStructuringLargerApps.md#Modules) 152 | - [UsingOpenSourceNPMPackages](14_ESModulesAndStructuringLargerApps.md#UsingOpenSourceNPMPackages) 153 | - [Security](14_ESModulesAndStructuringLargerApps.md#security) 154 | --------------------------------------------------------------------------------