└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # Notes on "Javascript: Understanding the weird parts" 2 | 3 | That document is what I wrote during following that amazing course by Anthony P.Alicea. You can find the [course](http://learnwebdev.net/) and the [first 3.5 hours](https://www.youtube.com/watch?v=Bv_5Zv5c-Ts). 4 | This course is kinda old and isn't using ES6 stuff but it is the most interesting piece of JS knowledge I found to that date. 5 | 6 | These notes won't replace watching the course, they more of a personal reminder, for me and whoever watch the course. 7 | 8 | ## Things to know 9 | 10 | - javascript is synchronous and single-threaded. 11 | - objects and functions are closely related. 12 | - javascript doesn't care if arguments are not passed to function, they will just be setted to `undefined` 13 | - everything is an object or a primitive 14 | 15 | ### Execution context 16 | 17 | The execution context is created in 2 phases: 18 | - **creation phase**: Global object (variable environment), `this` and **outer environment** is setup in memory. Also setup the memory space for variables and functions (that step is called **hoisting**). An `argument` variable is also created for functions. 19 | - **execution phase**: We here have everything setup and it will run the code line by line. 20 | 21 | 22 | ### The scope chain 23 | When a variable is called, javascript will does more than check the current **execution context**. An **execution context** have a reference to its outer environment. So in a **execution stack**, the **outer environment** is not necessarily the **execution context** below itself. It will instead depends on the **lexical environment**. So if my function is at the global level, the **outer environment** will be `global`. 24 | 25 | ``` javascript 26 | function a(){ 27 | console.log(example) 28 | } 29 | function b(){ 30 | var example = 1 31 | a() 32 | } 33 | var example = 2 34 | b() 35 | 36 | // => will return "2" because outer environment of a() is global even thought it's called in b() 37 | 38 | function b(){ 39 | function a(){ 40 | console.log(example) 41 | } 42 | var example = 1 43 | a() 44 | } 45 | var example = 2 46 | b() 47 | // => will return '1' because outer environment of a() is b() as a() sits in b() 48 | ``` 49 | 50 | The fact of going down through these **outer environment** is called the **scope chain**. 51 | 52 | Another point of interest when speaking about scope chain is the difference between normal functions and arrow functions. 53 | 54 | ``` javascript 55 | document.addEventListener('click', function() { console.log(this) }); 56 | // => will return the document object as functions are inheriting the execution scope 57 | 58 | document.addEventListener('click', () => console.log(this)); 59 | // => will return the window object as arrow functions are inheriting the declaration scope 60 | ``` 61 | 62 | ### Functions are objects 63 | A function is a special type of object. You can assign it a primitive, an object or a function as property. 64 | In a function there is also two important property: _name_ and _code_. A function without a name is called an anonymous function. 65 | 66 | ### By value vs By reference 67 | When passing a primitive to a variable, javascript will create a copy of that **value**, stored in its own memory. 68 | ``` javascript 69 | a = 3 70 | b = a 71 | b 72 | // => returns 3 73 | a = 2 74 | b 75 | // => still returns 3 76 | ``` 77 | 78 | When passing an object (or a function as a function is an object), javascript will just **reference** to the object. 79 | ``` javascript 80 | a = {name: "Tom"} 81 | b = a 82 | b 83 | // => returns {name: "Tom"} 84 | a.name = "Margaux" 85 | b 86 | // => returns {name: "Margaux"} 87 | ``` 88 | 89 | ### `this` 90 | `this` is setup during the creation phase of the **execution context**. 91 | 92 | ``` javascript 93 | console.log(this) 94 | // => returns the window object 95 | 96 | function test(){ 97 | console.log(this) 98 | } 99 | test() 100 | // => returns the window object 101 | 102 | var test = function(){ 103 | console.log(this) 104 | } 105 | test() 106 | // => returns the window object 107 | 108 | var object = { 109 | name: "Tom", 110 | test: function(){ 111 | console.log(this) 112 | } 113 | } 114 | object.test() 115 | // => returns the object 116 | 117 | var object = { 118 | name: "Tom", 119 | test: function(){ 120 | function test(){ 121 | console.log(this) 122 | } 123 | test() 124 | } 125 | } 126 | object.test() 127 | // => returns the window object !!! 128 | // for this case we usually need a self = this 129 | ``` 130 | 131 | ### Functional programming 132 | Since javascript have **first class functions**, we are open to a lot of functional programming approaches. 133 | Let's have an example: 134 | ``` javascript 135 | var arr = [1,2,3] 136 | function mapForEach(arr, fn){ 137 | var newArr = [] 138 | for(var i=0; i < arr.length; i++){ 139 | newArr.push(fn(arr[i])) 140 | } 141 | return newArr 142 | } 143 | 144 | arr2 = mapForEach(arr, function(item){ 145 | return item*10 146 | }) 147 | console.log(arr2) 148 | // => return [10,20,30] 149 | ``` 150 | 151 | ### `undefined` 152 | `undefined` is an internal value of javascript. It will be returned when a variable is initialized(via `var` or something). Different from `not defined` error that happen when the variable isn't in memory at all. 153 | 154 | _Never set yourself a value to `undefined` yourself._ That would be valid but it's make the debugging flawy. 155 | 156 | ### Coercion 157 | The fact of changing a value to another type. The coercion is used when the equality operator is called. The coercion can act weird sometimes and that's why we will use triple equal `===` for a most "defined" behavior. 158 | 159 | ### Arguments 160 | In a function javascript creates for us a variable called `arguments`. It's an array-like variable that we can use to access parameters like `arguments[0]`. 161 | 162 | ### Spread 163 | An spread argument can be used for specify an undefined numbers of arguments. 164 | ``` javascript 165 | function test(arg1,arg2,...arg3){ 166 | console.log(arg3) 167 | } 168 | test("Tom", "Quinonero") 169 | // => will return [] 170 | test("Tom", "Quinonero", "Berlin", "JS Expert") 171 | // => will return ["Berlin", "JS Expert"] 172 | ``` 173 | 174 | ### Statement vs Expression 175 | ``` javascript 176 | function test(){ 177 | console.log("I'm a statement") 178 | } 179 | 180 | var test = function(){ 181 | console.log("I'm an expression") 182 | } 183 | ``` 184 | 185 | ### IIFE: Immediate Invoked Functions Expressions 186 | When calling an expression just after it been defined. 187 | ``` javascript 188 | var test = function(){ 189 | console.log("test") 190 | }() 191 | 192 | (function(){ 193 | console.log("test") 194 | })() 195 | ``` 196 | 197 | ### Closures 198 | A feature of javascript. It's a combination of a function and it's lexical environment. The function will "remember" it's outer environment. 199 | 200 | ``` javascript 201 | function buildFunction(){ 202 | var arr = [] 203 | for (var i = 0; i < 3; i++){ 204 | arr.push( 205 | function() { 206 | console.log(i) 207 | } 208 | ) 209 | } 210 | return arr 211 | } 212 | 213 | var fs = buildFunction() 214 | 215 | fs[0]() 216 | fs[1]() 217 | fs[2]() 218 | // => Return 3 3 3 219 | // Because for doesn't create it's own execution environment 220 | // The outer environment will be the buildFunction and i is 3 in there 221 | ``` 222 | 223 | ### `call()`, `apply()` and `bind()` 224 | All functions have access to a `call()`, `apply()` and `bind()` function. 225 | When creating an expression function, I can change what `this` is referring to using bind: 226 | ``` javascript 227 | var person = { 228 | firstname: "Tom" 229 | } 230 | var test = function(salutation){ 231 | console.log(salutation + ' ' + this.firstname) 232 | } 233 | 234 | test() 235 | // => Will return undefined 236 | var testBinded = test.bind(person) 237 | testBinded() 238 | // => Will return "tom" 239 | ``` 240 | I can also keep the same function using call: 241 | ``` javascript 242 | test.call(person, "hi") 243 | // => Will return "hi tom" 244 | ``` 245 | Apply can be used, the difference is that the arguments have to be wrapped into an array: 246 | ``` javascript 247 | test.apply(person, ["hi"]) 248 | // => Will return "hi tom" 249 | ``` 250 | Cool patterns using these functions: 251 | ``` javascript 252 | // Borowing a method 253 | var post = { 254 | title: "How to be the best js person in the world", 255 | author: "Tom", 256 | getPostName: function(){ 257 | return this.title + " by: " + this.author 258 | } 259 | } 260 | 261 | var post2 = { 262 | title: "How to be a bad js person", 263 | author: "Jack" 264 | } 265 | 266 | post.getPostName.bind(post2)() 267 | // => Will return "How to be a bad js person by: Jack" 268 | ``` 269 | ``` javascript 270 | // function currying 271 | function multiply(a,b){ 272 | return a*b 273 | } 274 | 275 | // we set the function to be a copy of multiply with 2 as the first argument 276 | var multiplyByTwo = multiply.bind(this, 2) 277 | 278 | multiplyByTwo(4) 279 | // => will return "8" 280 | ``` 281 | 282 | ### Prototypal inheritance 283 | 284 | In javascript the inheritance is prototypal. 285 | Each object have a `proto` property. If a property is not found on the object itself, it will look for it in the prototype of it. And that goes on. That is called the **prototype chain**. 286 | All object inherits by default from the base object. That object is the base of every object. 287 | All function inherits from the function base object. This object define property as arguments, bind, call, apply ... That's why every function can access these. 288 | Same with arrays. 289 | 290 | ### The function constructor 291 | We can build a object with a function constructor using `new` operator: 292 | ``` javascript 293 | function Post(){ 294 | this.title = "How to construct js objects" 295 | this.author = "Tom" 296 | } 297 | 298 | var post = new Post() 299 | console.log(post) 300 | // => Will return Post {title: "How to construct js objects", author: "Tom"}author: "Tom"title: "How to construct js objects"__proto__: Object 301 | ``` 302 | If the function doesn't specify a `return`, it's acting like we returned `this`. 303 | A downside is that if we forgot to use the `new` keyword, it will not set the properties at the object level. 304 | A convention for helping avoiding this issue is to start functions constructors name with a capital letter. 305 | 306 | ### Pure prototypal inheritance 307 | 308 | ``` javascript 309 | var person = { 310 | firstname: "default", 311 | lastname: "default", 312 | greet: function(){ 313 | return "Hi " + this.firstname + " " + this.lastname 314 | } 315 | } 316 | 317 | var tom = Object.create(person) 318 | tom.greet() 319 | // => will return "Hi default default" 320 | tom.firstname = "Tom" 321 | tom.greet() 322 | // => will return "Hi Tom default" 323 | ``` 324 | 325 | ### `class` operator 326 | In javascript, since ES6, you can use `class` for for creating an object. 327 | That works like a syntaxic sugar for constructing objects. 328 | It has an `extends` possibility for using a prototype. 329 | 330 | 331 | ## Glossary 332 | 333 | - **asynchronous**: Means more than one at a time. Since javascript is **synchronous**, the **event queue** is used to handle asynchronous stuff. The asynchronous part will not happen in the javascript engine, it will mostly happens on the render engine of the browser or the HTTP engine. 334 | - **block**: A portion of code generally delimited by curly brackets `{}`. 335 | - **callback function**: A function you give to another function to be executed when the other function is finished. 336 | - **coercion**: Converting a value to another type. 337 | - **dynamic typing**: Type is not defined explicitly, it's figured out when the code is running. It's the opposite of _static typing_. 338 | - **Event queue**: When an event happens, it's placed on the event queue. When the execution is finished (read the **execution stack** is empty), javascript will check periodically the event queue and check if something should be run in that case (eg: if an event is listened). If an event happens before the execution is done, javascript will only process this event when the execution is done. 339 | - **execution contexts**: A wrapper to help manage the code that is running. The default execution context is the global execution context. In a browser, the global object is the `window` object. `this` at the global level is the `window` object. _execution context != scope_ 340 | - **execution stack**: A stack of **execution contexts**. When the script on the page is done, the stack is empty. 341 | - **expression**: A unit of code that results in a value. 342 | - **first class function**: Anything you can do with other types (assign to var, create them on the fly) can be done with functions. Functions in javascript are first-class functions. 343 | - **function currying**: Creating a copy of a function but with some preset parameters 344 | - **function constructor**: A function that is used to construct an object. 345 | - **hoisting**: Phenomenon that happens during the _creation phase_ of the **execution context**. It's setting up space for variables and functions into the memory. During this process, _all variables_ are initially set to `undefined` and functions are entirely wrote to the memory. So you can call a function that is defined later in the code event thought it's should not be done. 346 | - **inheritance**: One object gets access to the properties and methods of another object. Javascript uses prototypal inheritance. 347 | - **invocation**: Running a function. Invocation will create a new **execution context** and put it at the top of the **execution stack**. When the invocation is done, the **execution context** is removed form the **execution stack**. 348 | - **lexical environment**: Where something sits physically in the code you write 349 | - **literal syntax**: A short syntax eg: `[]` for `new Array()`. 350 | - **mutation**: Changing something 351 | - **name/value pair**: A name which maps to a unique value. A name can only have one value in a given **execution context**. 352 | - **namespace**: A container for variables and functions. 353 | - **object**: A collection of **name/value** pair. An object can contains a primitive (called a property), another object (called also a property) or a function (called a method). 354 | - **operator**: An operator is a special function in javascript that use a different syntax. Its usually have two parameters and one result. The double equal comparator `==` is an operator. The plus `+` is an operator. The `.` is also an operator ! 355 | - **operator associativity**: What order **operator** functions get called first when the operators have the same **precedence**. Left-to-right associativity or Right-to-left associativity. 356 | - **operator precedence**: Define which **operator** function is called first. The _higher precedence win_. For example `*` has a higher precedence than `+`. 357 | - **outer environment**: A reference to the environment where a function or a variable sits, it's **lexical environment**. By default (read "when declared at the root"), the outer environment is `global`. 358 | - **primitives types**: The "default" types of javascript. Primitive type mean a single value, _not an object_. The six primitives types are: `undefined`, `null`, `boolean`, `number`, `string` and `symbol`(that is a ES6 type) 359 | - **reflection**: An object can look at itself, listing and changing its properties and methods. 360 | - **scope**: Where a variable is available in your code and if it's the truly same variable. 361 | - **scope chain**: The fact that a function or variable call not defined in the current **execution context** goes down to the **outer environment** for finding it. 362 | - **single threaded**: Mean that one command happen at a time. 363 | - **synchronous**: Mean that the code is happening one line at the time. Similar to **single threaded**. 364 | - **syntax parsers**: Program that reads the code and determinate what it does and if its syntax is valid. 365 | - **variable environment**: Where the variable is. Since every function has it's own **execution context** a variable with the same name will have _no interactions_ between them. 366 | - **whitespace**: Invisible character that create space in the code (spaces, tabs, returns). 367 | 368 | 369 | ## Resources 370 | 371 | - [Operator precedence on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence) 372 | - [Equality comparison and sameness on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness) 373 | - [Annotated underscore.js source code](https://underscorejs.org/docs/underscore.html) 374 | --------------------------------------------------------------------------------