├── README.md ├── answers ├── answers-2.js ├── answers-3.js ├── answers-4.js ├── answers-5.md └── answers-6.js ├── lesson-1 └── notes.md ├── lesson-2 ├── exercise.js ├── exercise.md └── notes.md ├── lesson-3 └── notes.md ├── lesson-4 ├── exercise.js ├── exercise.md └── notes.md ├── lesson-5 ├── exercise.js ├── exercise.md └── notes.md ├── lesson-6 ├── exercise.js ├── exercise.md └── notes.md ├── lesson-7 └── notes.md ├── lesson-8 └── notes.md └── package.json /README.md: -------------------------------------------------------------------------------- 1 | # Advanced Javascript Fundamentals 2 | 3 | ✌️Hello! My name is Tyler Clark and this is the 4 | source material for my Advanced JS Fundamentals workshop 5 | 6 | ## Why Should You Care About this Workshop? 7 | 8 | Many of the topics I will go over are not required for someone to know in order to be a "web developer". In fact, I know people that have worked in JavaScript for 10 years that have little to no idea of these concepts. So why should you care? I believe that understanding the foundations of JavaScript will take your career to the next level. I really mean it. 9 | 10 | Here are some of the real world takeaways from this workshop: 11 | 12 | 1. You will be able to learn new frameworks more quickly. 13 | 2. Not only will you avoid writing exceptions but will recognize errors quicker. 14 | 3. It could be the difference between getting a job or even being able to give yourself the infamous "senior" title. 15 | 4. You will see an overall improvement in your code quality. 16 | 17 | --- 18 | 19 | ## Pre-Workshop Instructions/Requirements 20 | 21 | This workshop is helpful for developers at any level of their career. Though it assumes that you have at a minimum a basic knowledge of JavaScript such as its syntax 22 | 23 | - [ ] Setup the project (follow the setup instructions below) 24 | - [ ] Install and setup [Zoom](https://zoom.us) on the computer you will be using 25 | 26 | ## Workshop Outline 27 | 28 | While there are similarities between each lesson, we will work through each exercise independent of each other. 29 | 30 | 1. Primitive Types, the what, how, and why 31 | 2. How prototypal inheritance works in JS & Create objects with the `new` keyword 32 | 3. Understanding implicit vs explicit coercion 33 | 4. Reference execution with the `this` keyword 34 | 5. Understand lexical vs. dynamic scope & Hoisting variables with const, let, var & Immediately invoked function (IIFE) 35 | 6. Use the ES6 class keyword 36 | 7. Hide variables with closures 37 | 8. Understanding strict mode 38 | 39 | ## System Requirements 40 | 41 | - [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) v2 or greater 42 | 43 | Git must be available in your `PATH`. To verify things are set up 44 | properly, you can run this: 45 | 46 | ```shell 47 | git --version 48 | ``` 49 | 50 | If you have trouble with any of these, learn more about the PATH environment 51 | variable and how to fix it here for [windows][win-path] or 52 | [mac/linux][mac-path] 53 | 54 | ## Setup 55 | 56 | You can work through these exercises through the browser if you want. This is nice because you do not need to clone the repo and set it up on your machine. 57 | 58 | To work in the browser, go to 59 | [this codesandbox](https://codesandbox.io/s/github/twclark0/advanced-javascript-fundamentals) 60 | 61 | [![Edit advanced-javascript-fundamentals](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/twclark0/advanced-javascript-fundamentals) 62 | 63 | If you'd rather be able to work through the workshop on your own computer clone this repo to your machine. 64 | 65 | ```shell 66 | git clone https://github.com/twclark0/advanced-javascript-fundamentals.git 67 | 68 | cd advanced-javascript-fundamentals 69 | 70 | ``` 71 | 72 | ## Working through it 73 | 74 | I will have at least one exercise for each lesson. All of the exercises will be in the `exercises` directory. At the top of each exercise is a description of what the current state of the code is in and what the goal state is supposed to look like. So before you have any questions please make sure you have read the description at the top of the file thoroughly. 75 | 76 | As you will see, there is a directory called `exercises-completed` that shows the final "answer" to each exercise question. 77 | 78 | ## License 79 | 80 | This material is available for private, non-commercial use under the 81 | [GPL version 3](http://www.gnu.org/licenses/gpl-3.0-standalone.html). If you have questions about using this workshop material in anyway, please contact me 82 | at `tyler@tylerclark.dev` 83 | -------------------------------------------------------------------------------- /answers/answers-2.js: -------------------------------------------------------------------------------- 1 | const arm = { 2 | hasArm() { 3 | return true 4 | } 5 | } 6 | 7 | const leg = { 8 | hasLeg() { 9 | return false 10 | } 11 | } 12 | 13 | const head = { 14 | hasHead() { 15 | return 'yes' 16 | } 17 | } 18 | 19 | Object.setPrototypeOf(arm, leg) 20 | Object.setPrototypeOf(leg, head) 21 | 22 | const person = Object.create(arm) 23 | 24 | person.hasArm() // true 25 | 26 | person.hasLeg() // false 27 | 28 | person.hasHead() // 'yes' 29 | -------------------------------------------------------------------------------- /answers/answers-3.js: -------------------------------------------------------------------------------- 1 | const a = { val: 0 } 2 | 3 | a.valueOf = function() { 4 | return ++this.val 5 | } 6 | 7 | console.log(a == 1 && a == 2 && a == 3) //true 8 | -------------------------------------------------------------------------------- /answers/answers-4.js: -------------------------------------------------------------------------------- 1 | function Foo(name) { 2 | this.name = name 3 | } 4 | 5 | Foo.prototype.myName = function() { 6 | return this.name 7 | } 8 | 9 | function Bar(name) { 10 | Foo.call(this, name) // Answer to step 1 11 | } 12 | 13 | Bar.prototype = Foo.prototype // Answer to step 2 14 | 15 | const a = new Bar('tyler') 16 | 17 | console.log(a.myName()) 18 | -------------------------------------------------------------------------------- /answers/answers-5.md: -------------------------------------------------------------------------------- 1 | ### We'll do it together! 2 | 3 | Question 1: What is the first `console.log` value within `foo()`. **ANSWER: `undefined`** 4 | 5 | 6 | ```js 7 | var a = 'tyler' 8 | 9 | function foo() { 10 | console.log(a) 11 | var a = 'clark' 12 | } 13 | 14 | foo() 15 | 16 | ``` 17 | 18 | --- 19 | 20 | Question 2: What is the `console.log` value within `foo()`. **ANSWER: "Cannot access 'a' before initialization"** 21 | 22 | ```js 23 | let a = 'tyler' 24 | 25 | function foo() { 26 | console.log(a) 27 | let a = 'clark' 28 | } 29 | 30 | foo() 31 | 32 | ``` 33 | 34 | --- 35 | 36 | Question 3: What is the `console.log` value within `foo()`. **ANSWER: "tyler"** 37 | 38 | 39 | ```js 40 | var a = 'tyler' 41 | 42 | function foo() { 43 | console.log(a) 44 | a = 'clark' 45 | } 46 | 47 | foo() 48 | ``` 49 | 50 | --- 51 | 52 | Question 4: What happens when we run the following code? **ANSWER: "myFunction is not a function"** 53 | 54 | ```js 55 | myFunction() 56 | 57 | var myFunction = function() { 58 | console.log('hello world'); 59 | } 60 | 61 | ``` -------------------------------------------------------------------------------- /answers/answers-6.js: -------------------------------------------------------------------------------- 1 | /***************************** Exercise 1 ********************************************** */ 2 | 3 | class Triple { 4 | static triple(n) { 5 | if (n === undefined) { 6 | n = 1 7 | } 8 | return n * 3 9 | } 10 | } 11 | 12 | class DoubleTheTriple extends Triple { 13 | static double(n) { 14 | return super.triple(n) * super.triple(n) 15 | } 16 | } 17 | 18 | console.log(Triple.triple()) // 3 19 | console.log(Triple.triple(6)) // 18 20 | console.log(DoubleTheTriple.double(2)) // 36 21 | console.log(DoubleTheTriple.double(3)) // 81 22 | 23 | /***************************** Exercise 2 ********************************************** */ 24 | 25 | function Animal() {} 26 | 27 | Animal.prototype.speak = function() { 28 | console.log(`${this.name} makes a noise.`) 29 | } 30 | 31 | function Dog(name) { 32 | this.name = name 33 | } 34 | 35 | Object.setPrototypeOf(Dog.prototype, Animal.prototype) 36 | 37 | const a = new Dog('Duke') 38 | 39 | a.speak() // Duke makes a noise. 40 | 41 | /***************************** Another Exercise 2 Answer ********************************************** */ 42 | 43 | const Animal = { 44 | speak() { 45 | console.log(`${this.name} makes a noise.`) 46 | } 47 | } 48 | 49 | function Dog(name) { 50 | this.name = name 51 | } 52 | 53 | Object.setPrototypeOf(Dog.prototype, Animal) 54 | 55 | const a = new Dog('Duke') 56 | 57 | a.speak() // Duke makes a noise. 58 | -------------------------------------------------------------------------------- /lesson-1/notes.md: -------------------------------------------------------------------------------- 1 | ## Intro 2 | 3 | Primitive types: is data that is not an object, has no methods and cannot be mutated. 4 | 5 | Everything in JavaScript is _Not_ actually an object 6 | 7 | ##### The latest primitive types are : string, number, bigint, boolean, null, undefined, and symbol 8 | 9 | ```js 10 | typeof 'hello world' // "string" 11 | typeof 1 // "number" 12 | typeof false // "boolean" 13 | typeof 42n // "bigint" 14 | typeof Symbol() // "symbol" 15 | typeof null // "object" 16 | typeof undefined // "undefined" 17 | 18 | // Not a primitive 19 | typeof NaN // "number" 20 | 21 | // Data type, not a primitive 22 | typeof {} // "object" 23 | ``` 24 | 25 | - BigInts can use all operators that numbers can use though it is not strictly equal to a `Number`, but "loosely so". 26 | 27 | --- 28 | 29 | ### Code example 30 | 31 | Example: 32 | 33 | ```js 34 | let obj = { a: 1 } 35 | 36 | function addTwo(obj) { 37 | obj.a = 2 38 | } 39 | 40 | addTwo(obj) 41 | 42 | // obj is now {a: 2} 43 | ``` 44 | 45 | Example 2: 46 | 47 | ```js 48 | let num = 1 49 | 50 | function addTwo(num) { 51 | num = num + 2 52 | console.log(num) 53 | } 54 | 55 | addTwo(num) 56 | 57 | // console.log(num) 58 | ``` 59 | 60 | --- 61 | 62 | ### Wrapper objects 63 | 64 | - _But I can dot into prototype methods on strings??_ 65 | - Answer: Auto-boxing. This is the boxing, or wrapping, of value types in objects when they are treated like objects. Behind the scenes, a temporary object is created for the duration of the use of the value type instance. 66 | 67 | Primitive wrapper objects in JavaScript (Natives, Constructors, Fundamental Object) 68 | 69 | ```js 70 | const str = 'foo' 71 | console.log(typeof str) 72 | console.log(str.length) 73 | ``` 74 | 75 | vs 76 | 77 | ```js 78 | const wrapperString = new String('foo') 79 | 80 | console.log(typeof wrapperString) 81 | 82 | console.log(wrapperString) 83 | 84 | console.log(wrapperString[0]) 85 | 86 | console.log(Object.getPrototypeOf(wrapperString) === String.prototype) 87 | ``` 88 | 89 | - Should try to use the literal syntax for everything.. You can use it on RegExp, Error.. and Date (no literal) 90 | 91 | #### Gotchas 92 | 93 | ```js 94 | const foo = false 95 | const bar = new Boolean(false) 96 | 97 | foo === bar // false 98 | 99 | typeof bar // "object" 100 | ``` 101 | 102 | vs. 103 | 104 | ```js 105 | const baz = false 106 | const buzz = Boolean(false) 107 | 108 | baz === buzz // true 109 | 110 | typeof buzz // "boolean" 111 | ``` 112 | -------------------------------------------------------------------------------- /lesson-2/exercise.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twclark0/advanced-javascript-fundamentals/54599bd5a57911527578b3822d9fadc0f012cb22/lesson-2/exercise.js -------------------------------------------------------------------------------- /lesson-2/exercise.md: -------------------------------------------------------------------------------- 1 | # Prototypes: 2 | 3 | The following code snippet shows three functions that all return something different. Our goal is to put all of the functions into their own object, then link each object (with their one property) together through the prototype chain: 4 | 5 | ```js 6 | function hasArm() { 7 | return true 8 | } 9 | 10 | function hasLeg() { 11 | return false 12 | } 13 | 14 | function hasHead() { 15 | return 'yes' 16 | } 17 | ``` 18 | 19 | --- 20 | 21 | Outcome: 22 | 23 | - Three objects with one property that have one of the functions listed above 24 | - Connect each object together through the prototype chain 25 | - A fourth object without any properties but has access to all three functions through the prototype chain. 26 | - You'll know you did it right when you can invoke each function from the final object and receive the return values 27 | -------------------------------------------------------------------------------- /lesson-2/notes.md: -------------------------------------------------------------------------------- 1 | ## Prototypes 2 | 3 | ##### What the prototype? 4 | 5 | - The fundamental way inheritance works in JavaScript. 6 | - Prototypes are objects. It is the linking of objects 7 | - OO languages work through classes, a parent to child relationship. Typically with classes you use the `new` keyword to create a copy of that blueprint code (class) 8 | - Prototypes is the linkeage between objects through properties. Or commonly called the prototype chain. 9 | - When accessing a property, it looks at each object level one at a time until it finds it or returns `null`. So you can "replace" the `.toString()` found on the global `Object.prototype.toString` by giving your object the same property name. 10 | 11 | Type in a browser console the following: 12 | 13 | ```js 14 | const a = {}; 15 | 16 | console.log(a); 17 | ``` 18 | 19 | --- 20 | 21 | ### Connection between `.prototype` and `__proto__` 22 | 23 | - Functions have a `.prototype` property that points to an object with a constructor property, and a `__proto__` property. 24 | 25 | ```js 26 | function a() { 27 | return "hello"; 28 | } 29 | 30 | console.log(a.prototype); 31 | ``` 32 | 33 | --- 34 | 35 | ### Working with Built in Objects: 36 | 37 | - First step is understanding what the global Functions and Prototypes are, i.e: 38 | - Some are: `Array`, `Object`, `Number`, `String` 39 | - `Object` vs. `Object.prototype` 40 | 41 | - `Object.prototype.toString()` vs. `Object.values()` 42 | 43 | ```js 44 | const b = { name: "tyler", lastName: "clark" }; 45 | 46 | b.toString(); // "[object Object]" 47 | 48 | b.values(); // error, not a function 49 | 50 | Object.values(b); // ["tyler", "clark"] 51 | ``` 52 | 53 | --- 54 | 55 | ### Understanding the `new` keyword 56 | 57 | - Does three main things: Creates a new object, connects new object's `__proto__` to function's `.prototype`, `this` used within called function points to new object created. (Fourth is it returns `this` which is that new object) 58 | 59 | 1. Creates new object: 60 | 61 | ```js 62 | function a() { 63 | return "hello"; 64 | } 65 | 66 | const b = new a(); 67 | 68 | console.log(b); // { } 69 | ``` 70 | 71 | 2. Connects new object's `__proto__` to function's `.prototype` 72 | 73 | ```js 74 | function A() { 75 | return "hello"; 76 | } 77 | 78 | A.prototype.name = "world"; 79 | 80 | const b = new A(); 81 | 82 | console.log(b); 83 | 84 | console.log(b.name); 85 | ``` 86 | 87 | 3. `this` used within called function points to new object created 88 | 89 | ```js 90 | function A() { 91 | this.name = "hello"; 92 | } 93 | 94 | const b = new A(); 95 | 96 | console.log(b); 97 | 98 | console.log(b.name); 99 | ``` 100 | 101 | ###### Just for fun: 102 | 103 | ```js 104 | function A() { 105 | this.name = "hello"; 106 | } 107 | 108 | A.prototype.name = "world"; 109 | 110 | const b = new A(); 111 | 112 | // console.log(b) 113 | 114 | // console.log(b.name) 115 | ``` 116 | 117 | --- 118 | 119 | ### Loops with Prototypes 120 | 121 | - Loops can behave differently when objects have chained prototype objects. 122 | - The for...in statement iterates over all non-Symbol, enumerable properties of an object. 123 | 124 | ```js 125 | const obj = { 126 | firstName: "Tyler", 127 | lastName: "Clark", 128 | }; 129 | 130 | let n = 0; 131 | for (let property in obj) { 132 | n++; 133 | } 134 | console.log(n); // 2 135 | ``` 136 | 137 | vs. 138 | 139 | ```js 140 | const obj = { 141 | firstName: "Tyler", 142 | lastName: "Clark", 143 | }; 144 | 145 | const protoObj = { 146 | hair: "Brown", 147 | }; 148 | 149 | Object.setPrototypeOf(obj, protoObj); 150 | 151 | let n = 0; 152 | for (let property in obj) { 153 | n++; 154 | } 155 | console.log(n); // 3 156 | ``` 157 | 158 | - In order to avoid this situation, you need to add a check 159 | 160 | ```js 161 | const obj = { 162 | firstName: "Tyler", 163 | lastName: "Clark", 164 | }; 165 | 166 | const protoObj = { 167 | lastName: "Brown", 168 | }; 169 | 170 | Object.setPrototypeOf(obj, protoObj); 171 | 172 | let n = 0; 173 | for (let property in obj) { 174 | if (obj.hasOwnProperty(property)) { 175 | n++; 176 | } 177 | } 178 | console.log(n); // 2 179 | ``` 180 | 181 | - Does not map over the nested Object.prototype properties because those are not Enumerable 182 | - Same reason why loops don't iterate on the `.length` property in arrays 183 | 184 | --- 185 | 186 | ### `Object.create` 187 | 188 | - `Object.create` creates a object and gives the ability to point another object to be the new object's prototype. 189 | 190 | ```js 191 | const house = { 192 | houseColor(color) { 193 | console.log(`${color} is a good color`); 194 | }, 195 | }; 196 | 197 | const myHouse = Object.create(house); // { } 198 | 199 | myHouse.houseColor("blue"); // blue is a good color 200 | ``` 201 | -------------------------------------------------------------------------------- /lesson-3/notes.md: -------------------------------------------------------------------------------- 1 | ## Coercion 2 | 3 | - Think of it as "Conversion". Changing types from primitive to primitive or object to primitive. 4 | - To understand your code, you have to learn to interpret code like JS 5 | - Coercion happens more than you probably think. It is unavoidable... But doesn't have to be a black box... See below... 6 | - A couple prototypes have a `.toString()` for converting it to a string primitive. 7 | - Work around for string to object is `JSON.parse` and `JSON.stringify`. 8 | 9 | --- 10 | 11 | #### Implicit Coercion 12 | 13 | - Abstracts away the lower details to provide more focus for the developer. Are the explicit coercion distracting to the reader? Example: Template strings 14 | 15 | ```js 16 | const someNumber = 2 17 | const str = `Hello, I have ${someNumber} eyes` 18 | ``` 19 | 20 | - _First_ JS will do is call the .valueOf function on the wrapper object prototype chain to determine it's primitive value. 21 | - Afterwards it will coerce the type into the similar type to complete the operation. 22 | 23 | * Using prototype methods on primitive... Boxing is implicit coercion 24 | * Overload operators like the `+` 25 | * Truthy & Falsy checks 26 | 27 | ```js 28 | if (arr.length) { 29 | // do something while arr.length is truthy? 30 | // vs. do something while arr.length > 0? 31 | } 32 | ``` 33 | 34 | - `==` (Using valueOf on prototype to determine what type it is. Then calls needed method to coerce into right type for comparison.. which then runs same algorithm as `===`) 35 | 36 | --- 37 | 38 | #### Explicit Coercion 39 | 40 | - Using the native functions (`String`, `Boolean`, `Number`) 41 | 42 | ```js 43 | const someNumber = 2 44 | const str = `Hello, I have ${String(someNumber)} eyes` 45 | ``` 46 | 47 | --- 48 | 49 | ##### to-string coercion 50 | 51 | - String(val) 52 | - .toString() 53 | - Using the `+` operator 54 | 55 | ```js 56 | const num = (1).toString() 57 | // "1" 58 | 59 | const arr = [1, 2, 3].toString() 60 | 61 | // "1, 2, 3" 62 | 63 | const obj = { a: 1 }.toString() 64 | 65 | // "[object Object]" 66 | 67 | const stringNumber = 2 + '' 68 | 69 | // '2' 70 | ``` 71 | 72 | - Common gotchas: 73 | 74 | ```js 75 | const nestedArr = [[], [], []].toString() 76 | 77 | // ",," 78 | 79 | const arrEmpty = [null, undefined].toString() 80 | 81 | // "," 82 | ``` 83 | 84 | ##### to-number() 85 | 86 | - `Number(val)` 87 | - `parseInt(val)` 88 | - `parseFloat(val)` 89 | 90 | ```js 91 | const empty = Number('') // 0 92 | 93 | const notANumber = Number('.') // NaN 94 | ``` 95 | 96 | - Why??: 97 | 98 | ```js 99 | const zeroDot = Number('0.') // 0 100 | 101 | const falses = Number(false) // 0 102 | 103 | const trues = Number(true) // 1 104 | 105 | const nulls = Number(null) // 0 106 | 107 | const undef = Number(undefined) // NaN 108 | 109 | const arr = Number(['']) // 0 110 | 111 | const arrValue = Number([1, 2]) // NaN 112 | ``` 113 | 114 | ##### to-boolean 115 | 116 | - Looks to see if value is falsy or truthy 117 | - `Boolean(val)` 118 | - Comparing the value `==` or `===` 119 | 120 | Falsy: `""`, `0`, `-0`, `null`, `NaN`, `false`, `undefined` 121 | Truthy: ....everything else. 122 | -------------------------------------------------------------------------------- /lesson-4/exercise.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twclark0/advanced-javascript-fundamentals/54599bd5a57911527578b3822d9fadc0f012cb22/lesson-4/exercise.js -------------------------------------------------------------------------------- /lesson-4/exercise.md: -------------------------------------------------------------------------------- 1 | ## HELP! We are having problems with `this`! 2 | 3 | #### Step #1: 4 | 5 | - When we `new` up `Bar('tyler')` it looks like we are intending to actually have `Foo` create the `name` property on the new object (`a`) through the `new keyword. Though this is not actually happening...? What can we do to make the invocation of`Foo(name)`set the property of`name`on the`a` object? 6 | 7 | ```js 8 | function Foo(name) { 9 | this.firstName = name 10 | } 11 | 12 | function Bar(name) { 13 | Foo(name) 14 | } 15 | 16 | const a = new Bar('tyler') 17 | 18 | console.log(a.firstName) // undefined.. but we want it to return 'tyler' 19 | ``` 20 | 21 | Hints: 22 | 23 | - What is `this` within `Foo`? We want `this` to ultimately point to the `a` object so that it will create that the `firstName` property 24 | 25 | #### Step #2: 26 | 27 | - Once you get step 1 working, where the `console.log` is returning `'tyler'`, see if you can get this function on the `Bar.prototype` object to correctly return the `firstName` property on the `a` object. 28 | 29 | ```js 30 | function Foo(name) { 31 | this.firstName = name 32 | } 33 | 34 | Foo.prototype.myName = function() { 35 | return this.firstName 36 | } 37 | 38 | /* Bar function code goes here from step 1 */ 39 | 40 | const a = new Bar('tyler') 41 | 42 | console.log(a.myName()) // a.myName is not a function... but we want it to return 'tyler' 43 | ``` 44 | 45 | Hints: 46 | 47 | - Right now `Foo` and `Bar` have no prototype connection. How can we get `Foo`'s prototype object in the same chain as `Bar`'s prototype so that `a` with have both object's on it's prototype chain. All this while still keeping `this` working as intended. 48 | -------------------------------------------------------------------------------- /lesson-4/notes.md: -------------------------------------------------------------------------------- 1 | ## `this` 2 | 3 | - Simply put, `this` references the execution context of a function's call. Which is determined how the function was called and in non–strict mode, is always a reference to an object. 4 | - Can be different depending on how the function is called... In other words you cannot look at a function and know what the `this` context will be. You have to see how the function is called at runtime. 5 | - Important to understand how functions are invoked... Functions can be invoked with `()` individually (implicit binding), methods like `call` (explicit binding), or the `new` keyword. 6 | 7 | --- 8 | 9 | #### Implicit binding 10 | 11 | -Option 1: _Context object_: where `this` is probably intended to be the object the function lives on: 12 | 13 | - From mdn: "When a function is called as a method of an object, its this is set to the object the method is called on." 14 | 15 | ```js 16 | const person = { 17 | firstName: "tyler", 18 | getName() { 19 | return `${this.firstName} is my first name`; 20 | }, 21 | }; 22 | 23 | person.getName(); // 'tyler is my first name' 24 | ``` 25 | 26 | ```js 27 | const person = { 28 | value: { 29 | firstName: "tyler", 30 | getName() { 31 | return `${this.firstName} is my first name`; 32 | }, 33 | }, 34 | }; 35 | 36 | person.value.getName(); // 'tyler is my first name' 37 | ``` 38 | 39 | - Invoking `()` individually: _Default binding_ where it is called with a context and `this` defaults to the global 40 | - Behaves differently depending on `strict mode` or `non-strict mode` 41 | 42 | ```js 43 | var firstName = "tyler"; 44 | 45 | function getName() { 46 | return `${this.firstName} is my first name`; 47 | } 48 | 49 | getName(); // 'tyler is my first name' 50 | ``` 51 | 52 | - This example only works with `var` because it puts it on the window / global space 53 | 54 | - Look at call site of function, where is it actually called? 55 | 56 | ```js 57 | const person = { 58 | firstName: "tyler", 59 | getName() { 60 | console.log(`${this.firstName} is my first name`); 61 | }, 62 | }; 63 | 64 | window.setInterval(person.getName, 3000); // "undefined is my first name" 65 | ``` 66 | 67 | Still confused? Here's another example 68 | 69 | ```js 70 | const person = { 71 | firstName: "tyler", 72 | getName() { 73 | return `${this.firstName} is my first name`; 74 | }, 75 | }; 76 | 77 | const anotherPerson = {}; 78 | 79 | anotherPerson.getName = person.getName; 80 | 81 | anotherPerson.getName(); // "undefined is my first name" 82 | ``` 83 | 84 | #### Explicit binding 85 | 86 | - `apply`, `call`, `bind`: Takes a parameter which assigns the `this` context explicitly. 87 | 88 | ```js 89 | const person = { 90 | firstName: "tyler", 91 | }; 92 | 93 | function getName() { 94 | return `${this.firstName} is my first name`; 95 | } 96 | 97 | getName.call(person); // 'tyler is my first name' 98 | ``` 99 | 100 | ```js 101 | const person = { 102 | firstName: "tyler", 103 | }; 104 | 105 | function getName() { 106 | return `${this.firstName} is my first name`; 107 | } 108 | 109 | getName.apply(person); // 'tyler is my first name' 110 | ``` 111 | 112 | - `new` keyword: Does three main things. Creates a new object, points `this` to new object, link's `.prototype` to new object `__proto__`, and returns `this` (which is that new object) 113 | 114 | ```js 115 | function a() { 116 | this.firstName = "hello"; 117 | } 118 | 119 | const b = new a(); // {firstName: "hello"} 120 | 121 | console.log(b.firstName); // 'hello' 122 | ``` 123 | 124 | --- 125 | 126 | ###### Arrow functions 127 | 128 | - Arrow functions have no concept of `this`. If you use a `this` inside of a arrow function it will act like any other variable. It will lexically resolve to the enclosing scope looking for a this. 129 | - It's not a fix all solution for our troubles with `this` 130 | 131 | ```js 132 | const person = { 133 | firstName: "tyler", 134 | getName: () => { 135 | console.log(`${this.firstName} is my first name`); 136 | }, 137 | }; 138 | 139 | window.setInterval(person.getName, 3000); // "undefined is my first name" 140 | 141 | person.getName(); // "undefined is my first name" 142 | ``` 143 | 144 | - First need to understand our lexical scope. Our `this` lexical scope references the next parent _function_ context / scope. This is the enclosing function or the window. Object curly bracket's do not represent "scope". We are looking for function curlys for scope. 145 | 146 | ```js 147 | const person = { 148 | firstName: "tyler", 149 | getName: () => { 150 | return function () { 151 | console.log(`${this.firstName} is my first name`); 152 | }; 153 | }, 154 | }; 155 | 156 | window.setInterval(person.getName(), 3000); // "undefined is my first name" 157 | ``` 158 | 159 | **wrong** 160 | 161 | ```js 162 | const person = { 163 | firstName: "tyler", 164 | getName() { 165 | window.setInterval(function () { 166 | console.log(`${this.firstName} is my first name`); 167 | }, 3000); 168 | }, 169 | }; 170 | 171 | person.getName(); // "undefined is my first name" 172 | ``` 173 | 174 | **wrong** 175 | 176 | ```js 177 | const person = { 178 | firstName: "tyler", 179 | getName: () => { 180 | window.setInterval(function () { 181 | console.log(`${this.firstName} is my first name`); 182 | }, 3000); 183 | }, 184 | }; 185 | 186 | person.getName(); // "undefined is my first name" 187 | ``` 188 | 189 | **answer** 190 | 191 | ```js 192 | const person = { 193 | firstName: "tyler", 194 | getName() { 195 | window.setInterval(() => { 196 | console.log(`${this.firstName} is my first name`); 197 | }, 3000); 198 | }, 199 | }; 200 | 201 | person.getName(); // "tyler is my first name" 202 | ``` 203 | 204 | ###### Arrow function gotchas 205 | 206 | - Cannot self reference with recursion. 207 | - Do not have a name, it is anonymous (unless assigned to a variable) 208 | - Cannot be used with the `new` keyword 209 | - `call` or `apply` first param for `this` is ignored 210 | 211 | --- 212 | 213 | #### `this` and prototypes 214 | 215 | - Works similar to looking up properties on an context object. `this` will step through the prototype chain looking for a property... because prototypes are just objects. 216 | - getters and setters 217 | 218 | ```js 219 | const proto = { 220 | get myName() { 221 | return this.firstName; 222 | }, 223 | }; 224 | 225 | const person = Object.create(proto); // { } 226 | 227 | person.firstName = "tyler"; // { firstName: 'tyler' } 228 | 229 | console.log(person.myName); // 'tyler' 230 | ``` 231 | 232 | - Arrow functions rules still apply 233 | 234 | ```js 235 | const proto = { 236 | myName: () => { 237 | return this.firstName; 238 | }, 239 | }; 240 | 241 | const person = Object.create(proto); // { } 242 | 243 | person.firstName = "tyler"; // { firstName: 'tyler' } 244 | 245 | person.myName(); // 'undefined' 246 | ``` 247 | 248 | --- 249 | -------------------------------------------------------------------------------- /lesson-5/exercise.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/twclark0/advanced-javascript-fundamentals/54599bd5a57911527578b3822d9fadc0f012cb22/lesson-5/exercise.js -------------------------------------------------------------------------------- /lesson-5/exercise.md: -------------------------------------------------------------------------------- 1 | ### We'll do it together! 2 | 3 | **Question 1:** What is the first `console.log` value within `foo()`. 4 | 5 | ```js 6 | var a = 'tyler' 7 | 8 | function foo() { 9 | console.log(a) 10 | var a = 'clark' 11 | } 12 | 13 | foo() 14 | ``` 15 | 16 | --- 17 | 18 | **Question 2:** What is the `console.log` value within `foo()`. 19 | 20 | ```js 21 | let a = 'tyler' 22 | 23 | function foo() { 24 | console.log(a) 25 | let a = 'clark' 26 | } 27 | 28 | foo() 29 | ``` 30 | 31 | --- 32 | 33 | Question 3: What is the `console.log` value within `foo()`. 34 | 35 | ```js 36 | var a = 'tyler' 37 | 38 | function foo() { 39 | console.log(a) 40 | a = 'clark' 41 | } 42 | 43 | foo() 44 | ``` 45 | 46 | Another look at this example: 47 | 48 | ```js 49 | function foo() { 50 | console.log(a) // ReferenceError: a is not defined 51 | a = 'clark' 52 | } 53 | 54 | foo() 55 | ``` 56 | 57 | --- 58 | 59 | Question 4: What happens when we run the following code? 60 | 61 | ```js 62 | myFunction() 63 | 64 | var myFunction = function() { 65 | console.log('hello world') 66 | } 67 | ``` 68 | -------------------------------------------------------------------------------- /lesson-5/notes.md: -------------------------------------------------------------------------------- 1 | # Scope & Hoisting 2 | 3 | - Contains any assignments of variables and functions. Cannot access "buckets" inward, just outward. 4 | - Many will say "best practice" is to make private as much as you can. This mediates naming collisions and it is prevented from being used elsewhere. Lots of public variables couples functionality and makes it difficult to refactor. 5 | 6 | #### Lexical Scope 7 | 8 | - Think of lexical related to "author" time or at "compile time" or "fixed". It is not decided on when or how the code is executed ("runtime"). 9 | - Other languages have dynamic scoping. Think the opposite of lexical, it's at "runtime". A function references scoped variables at execution. This does not work in JS, however we have the `this` keyword that gives us that dynamic scoping. 10 | 11 | ```js 12 | var name = "tyler"; 13 | 14 | function findName() { 15 | var name = "clark"; 16 | return name; 17 | } 18 | 19 | console.log(findName()); //'clark' 20 | ``` 21 | 22 | dynamic scope example: 23 | 24 | ```js 25 | var name = "tyler"; 26 | 27 | function findName() { 28 | return name; 29 | } 30 | 31 | function findAnotherName() { 32 | var name = "clark"; 33 | return findName(); 34 | } 35 | 36 | console.log(findAnotherName()); //'tyler' but if it was dynamic scope it would print 'clark' 37 | ``` 38 | 39 | #### IIFE pattern 40 | 41 | - Means the function is executed immediately after the completion of the definition. 42 | - This does not put the function on the global space. Meaning the function cannot be access anywhere else 43 | - Magic behind it is the initial wrapping of the function with `()`, which is called the `grouping operator`.. this makes it an expression because it is returning something. 44 | 45 | ```js 46 | (function findName() { 47 | return "hello"; 48 | })(); 49 | ``` 50 | 51 | arrow function example: 52 | 53 | ```js 54 | (() => "hello")(); 55 | ``` 56 | 57 | #### Block scoping 58 | 59 | - Defined with opening and closing `{}`. It is not scoped until there is an assignment created inside of it. It is overloaded with the object literal. 60 | - Objects are not scoped so you cannot go by the global rule that all `{}` means a scope. 61 | 62 | ```js 63 | var firstName = "tyler"; 64 | 65 | { 66 | var firstName = "clark"; 67 | console.log(firstName); // clark 68 | } 69 | 70 | console.log(firstName); // clark 71 | ``` 72 | 73 | #### `var`, `let`, `const` 74 | 75 | - `var` declarations are processed before any code is executed. It's scope is its **current execution context**. 76 | - Re-declaring it without a value, will not lose it's initial value. 77 | - It's declaration is equal to `undefined` and hoisted to the top of it's execution context. 78 | 79 | ```js 80 | var firstName = "tyler"; 81 | 82 | function x() { 83 | var firstName = "clark"; 84 | console.log(firstName); // 'clark' 85 | } 86 | 87 | console.log(firstName); // 'tyler' 88 | ``` 89 | 90 | - Any assignment without a variable statement puts it on the global object, regardless of it's execution context 91 | 92 | ```js 93 | function x() { 94 | firstName = "clark"; 95 | console.log(firstName); // 'clark' 96 | } 97 | x(); 98 | 99 | console.log(firstName); // 'clark' 100 | ``` 101 | 102 | --- 103 | 104 | - `let` is different from `var` as it's scope is blocked (statement or expression). 105 | - `let` does not create properties on the window object like `var`. 106 | - `let` is only initialized to value when the parser evaluates it. In other words it is not hoisted to top of scope with initial value of `undefined` like `var`. 107 | - Re-declartion of `let` throws an SyntaxError, unlike `var` 108 | 109 | ```js 110 | var firstName = "tyler"; 111 | 112 | { 113 | var firstName = "clark"; 114 | console.log(firstName); // clark 115 | } 116 | 117 | console.log(firstName); // clark 118 | ``` 119 | 120 | vs. 121 | 122 | ```js 123 | let firstName = "tyler"; 124 | 125 | { 126 | let firstName = "clark"; 127 | console.log(firstName); // clark 128 | } 129 | 130 | console.log(firstName); // tyler 131 | ``` 132 | 133 | --- 134 | 135 | - `const` very similar to `let`. 136 | - Blocked scoped as well 137 | - Major difference between it and `let` is as mdn states: `The value of a constant can't be changed through reassignment, and it can't be redeclared` 138 | - Gotcha: Does not do deep equals on object types. Like mutating values in an array or object 139 | 140 | Scope example: 141 | 142 | ```js 143 | const firstName = "tyler"; 144 | 145 | { 146 | const firstName = "clark"; 147 | console.log(firstName); // clark 148 | } 149 | 150 | console.log(firstName); // tyler 151 | ``` 152 | 153 | Renaming error example: 154 | 155 | ```js 156 | const firstName = "tyler"; 157 | firstName = "clark"; // TypeError: Assignment to constant variable. 158 | 159 | console.log(firstName); 160 | ``` 161 | 162 | ```js 163 | const firstName = ["tyler"]; 164 | firstName.length = 0; 165 | 166 | console.log(firstName); // [] 167 | ``` 168 | 169 | #### Let and Const gotcha: Temporal dead zone 170 | 171 | - Because let and const do not start with an initial value hoisted to the top, if you trying to access it before it is initialized with result in a reference error. 172 | - From MDN: "The variable is in a "temporal dead zone" from the start of the block until the initialization is processed." 173 | -------------------------------------------------------------------------------- /lesson-6/exercise.js: -------------------------------------------------------------------------------- 1 | /***************************** Exercise 1 ********************************************** */ 2 | 3 | class Triple { 4 | static triple(n) { 5 | // need code here 6 | } 7 | } 8 | 9 | class DoubleTheTriple extends Triple { 10 | static double(n) { 11 | // need code here.. make sure to use the triple function on the Triple class 12 | } 13 | } 14 | 15 | console.log(Triple.triple(1)) // 3 16 | console.log(Triple.triple(6)) // 18 17 | console.log(DoubleTheTriple.double(2)) // 36 18 | console.log(DoubleTheTriple.double(3)) // 81 19 | 20 | /***************************** Exercise 2 ********************************************** */ 21 | 22 | class Animal { 23 | speak() { 24 | console.log(`${this.name} makes a noise.`) 25 | } 26 | } 27 | 28 | class Dog extends Animal { 29 | constructor(name) { 30 | super() 31 | this.name = name 32 | } 33 | } 34 | 35 | const a = new Dog('Duke') 36 | 37 | a.speak() // Duke makes a noise. 38 | -------------------------------------------------------------------------------- /lesson-6/exercise.md: -------------------------------------------------------------------------------- 1 | ## Exercise #1 2 | 3 | - The first problem you are tasked is to simply "make it work". You'll notice a couple of `console.log`s at the bottom of the exercise code that print out the desired results. Using the bare-bones implementation of the code, try to figure out how to make the `console.log`s actually print out what they say they should print out. 4 | 5 | - Make sure that the second class `DoubleTheTriple`'s double function utilizes the triple function of `Triple` 6 | 7 | ## Exercise #2 8 | 9 | - The second exercise is a working code snippet involving two classes. You tasked to have the code return the same `console.log` result by "de-sugaring" the class into functions and prototypes. I taught that classes were simply sugar over functions and things like the `extends` keyword was setting prototypes equal to other functions / objects. So take a look at the code and convert it to functions, objects, etc. Make the `console.log` at the bottom of the code snippet return the same result. 10 | -------------------------------------------------------------------------------- /lesson-6/notes.md: -------------------------------------------------------------------------------- 1 | # ES6 Classes 2 | 3 | - Simply just syntactic sugar over functions and the prototype chain. 4 | - Can be a class declaration and class expression like functions. 5 | - Unlike functions, classes are not hoisted 6 | - Has many keywords specific to `class`, however it is still just sugar over functions and prototypes. 7 | 8 | ```js 9 | class Workshop {} 10 | 11 | typeof Workshop // "function" 12 | ``` 13 | 14 | ```js 15 | class WorkShop {} 16 | ``` 17 | 18 | Babel turns this into: 19 | 20 | ```js 21 | // ... 22 | // ... 23 | 24 | var WorkShop = function WorkShop() { 25 | _classCallCheck(this, WorkShop) 26 | } 27 | ``` 28 | 29 | #### `extends` 30 | 31 | - It subclasses custom classes as well as built-in objects (functions). 32 | - Would be the equivalent of using `Object.setPrototypeOf` with two functions **Before using the `new` keyword** 33 | 34 | ```js 35 | class Rectangle {} 36 | 37 | class Square extends Rectangle {} 38 | 39 | Object.getPrototypeOf(Square) // class Rectangle {} 40 | ``` 41 | 42 | - roughly translated to: 43 | 44 | ```js 45 | function Rectangle() {} 46 | 47 | function Square() {} 48 | 49 | Object.setPrototypeOf(Square, Rectangle) 50 | 51 | Object.getPrototypeOf(Square) // ƒ Rectangle() {} 52 | ``` 53 | 54 | - new keyword: 55 | 56 | ```js 57 | class Rectangle {} 58 | 59 | class Square extends Rectangle {} 60 | 61 | const shape = new Square() // {} 62 | 63 | Object.getPrototypeOf(shape) // { constructor: class Square} 64 | 65 | Object.getPrototypeOf(Object.getPrototypeOf(shape)) // { constructor: class Rectangle} 66 | ``` 67 | 68 | vs. 69 | 70 | ```js 71 | function Rectangle() {} 72 | 73 | function Square() {} 74 | 75 | Object.setPrototypeOf(Square, Rectangle) 76 | 77 | const shape = new Square() // {} 78 | 79 | Object.getPrototypeOf(shape) // { constructor: ƒ Square() } 80 | 81 | Object.getPrototypeOf(Object.getPrototypeOf(shape)) // Native Object.prototype ?? 82 | ``` 83 | 84 | #### `constructor` 85 | 86 | - Special method specific to `class` and is what is called when the `new` keyword is used against the `class`. 87 | - There can only be one `constructor` per class. 88 | - `constructors` can use the word `super`. 89 | 90 | ```js 91 | class Workshop { 92 | constructor(name) { 93 | this.firstName = name 94 | } 95 | } 96 | 97 | const me = new Workshop('tyler') 98 | 99 | // { firstName: 'tyler' } 100 | ``` 101 | 102 | #### `static` 103 | 104 | - Sets the property to the class / function itself. Does not go on `.prototype` property but on the function (because it is also an object). 105 | - They cannot be called on instances of the class (or function)... At least they are not meant to be, however there is still a way to do it by `.constructor.` and then the static method 106 | 107 | ```js 108 | class Rectangle { 109 | static callRectangle() { 110 | return 'inheriting from Rectangle' 111 | } 112 | } 113 | 114 | Rectangle.callRectangle() // "inheriting from Rectangle" 115 | ``` 116 | 117 | - Is the same thing as: 118 | 119 | ```js 120 | function Rectangle() {} 121 | 122 | Rectangle.callRectangle = function() { 123 | return 'inheriting from Rectangle' 124 | } 125 | 126 | Rectangle.callRectangle() // "inheriting from Rectangle" 127 | ``` 128 | 129 | - Another example: 130 | 131 | ```js 132 | class Rectangle { 133 | callRectangle() { 134 | return 'inheriting from Rectangle' 135 | } 136 | } 137 | 138 | Rectangle.callRectangle() // Rectangle.callRectangle is not a function 139 | ``` 140 | 141 | - That is similar to: 142 | 143 | ```js 144 | function Rectangle() {} 145 | 146 | Rectangle.prototype.callRectangle = function() { 147 | return 'inheriting from Rectangle' 148 | } 149 | 150 | Rectangle.callRectangle() // Rectangle.callRectangle is not a function 151 | ``` 152 | 153 | #### `super` 154 | 155 | - From `MDN` "The super keyword is used to access and call functions on an object's parent." 156 | - When `super` is used, it needs to be used before `this` can be used. 157 | - Can be used to call the constructor or other (static or not) methods found on parent class (function) 158 | - Can be used on object literals! 159 | 160 | ```js 161 | class Rectangle { 162 | constructor(height, width) { 163 | this.name = 'Rectangle' 164 | this.height = height 165 | this.width = width 166 | } 167 | } 168 | 169 | class Square extends Rectangle { 170 | constructor(length) { 171 | super(length, length) 172 | this.name = 'Square' 173 | } 174 | } 175 | 176 | const myShape = new Square(1) 177 | 178 | // {name: "Square", height: 1, width: 1} 179 | ``` 180 | 181 | - `super` to access other methods 182 | 183 | ```js 184 | class Rectangle { 185 | static callRectangle() { 186 | return 'inheriting from Rectangle' 187 | } 188 | } 189 | 190 | class Square extends Rectangle { 191 | static whoAmI() { 192 | return "I'm a square and " + super.callRectangle() 193 | } 194 | } 195 | 196 | Square.whoAmI() // "I'm a square and inheriting from Rectangle" 197 | ``` 198 | 199 | - When the `new` keyword is used, it's important understand how constructors play a role. i.e: 200 | 201 | ```js 202 | class Animal { 203 | constructor(name) { 204 | this.test = name 205 | } 206 | } 207 | 208 | class Cat extends Animal { 209 | constructor(name) { 210 | this.name = name 211 | } 212 | } 213 | 214 | const a = new Cat('Fuzzy') 215 | 216 | // Error Must call super constructor in derived class before accessing 'this' or returning from derived constructor 217 | ``` 218 | 219 | - `new` goes through classes on extends looking at constructors. In order to complete the chain `super` is required in child constructors. Begins at highest parent classes constructors. 220 | - Simply put, if you use a constructor method on a class that is extending another class, it has to call super. 221 | 222 | This does not throw an error: 223 | 224 | ```js 225 | class Animal {} 226 | 227 | class Cat extends Animal {} 228 | 229 | const a = new Cat('Fuzzy') // { } 230 | ``` 231 | 232 | This throws an error: 233 | 234 | ```js 235 | class Animal {} 236 | 237 | class Cat extends Animal { 238 | constructor(name) { 239 | this.test = name 240 | } 241 | } 242 | 243 | const a = new Cat('Fuzzy') // Must call super constructor in derived class before accessing 'this' or returning from derived constructor 244 | ``` 245 | 246 | This does not throw error: 247 | 248 | ```js 249 | class Animal { 250 | constructor(name) { 251 | this.test = name 252 | } 253 | } 254 | 255 | class Cat extends Animal {} 256 | 257 | const a = new Cat('Fuzzy') // {test: "Fuzzy"} 258 | ``` 259 | 260 | This also does not throw an error because of `super`: 261 | 262 | ```js 263 | class Animal { 264 | constructor(name) { 265 | this.test = name 266 | } 267 | } 268 | 269 | class Cat extends Animal { 270 | constructor(name) { 271 | super(name) 272 | this.name = name 273 | } 274 | } 275 | 276 | const a = new Cat('Fuzzy') // {test: "Fuzzy", name: "Fuzzy"} 277 | ``` 278 | 279 | Object literal example: 280 | 281 | ```js 282 | const Animal = { 283 | method1() { 284 | console.log('method 1') 285 | } 286 | } 287 | 288 | const Cat = { 289 | method2() { 290 | super.method1() 291 | } 292 | } 293 | 294 | Object.setPrototypeOf(Cat, Animal) 295 | 296 | Cat.method2() // "method 1" 297 | ``` 298 | -------------------------------------------------------------------------------- /lesson-7/notes.md: -------------------------------------------------------------------------------- 1 | # Closure 2 | 3 | - An inner function that has access to it's lexical scopes... at least it's own scope and it's parent scope. 4 | 5 | ```js 6 | const workshop = "JavaScript"; 7 | 8 | function parent() { 9 | const par = "tyler"; 10 | return function child() { 11 | const chi = "clark"; 12 | console.log(workshop, par, chi); 13 | }; 14 | } 15 | 16 | const me = parent(); 17 | 18 | me(); // JavaScript tyler clark 19 | ``` 20 | 21 | - It is a way to make variables private from the outside scope. Hiding implementations while programming towards interfaces. Implementation details change frequently and often. 22 | - This is used everyday with callbacks, currying, and partially applied functions. 23 | 24 | * So think this, It is not a snapshot of values.. Closure does not close over a "value". You close over variables. It is a preservation of a linkeage to a variable, not the capturing of a variable. 25 | 26 | ```js 27 | let workshop = "JavaScript"; 28 | 29 | function parent() { 30 | const par = "tyler"; 31 | return function child() { 32 | const chi = "clark"; 33 | console.log(workshop, par, chi); 34 | }; 35 | } 36 | 37 | workshop = "React"; 38 | 39 | const me = parent(); 40 | 41 | me(); // React tyler clark 42 | ``` 43 | -------------------------------------------------------------------------------- /lesson-8/notes.md: -------------------------------------------------------------------------------- 1 | # Strict mode 2 | 3 | - Coined as the opposite of "sloppy mode". It intentionally has different semantics from normal code. 4 | - If you are using compilers like babel, it is turned out automatically. ES6 JavaScript modules are automatically Other than that, it needs to be added to the file 5 | - `"use strict"` is the syntax 6 | - Catches silent errors and throws them, fixes mistakes that makes it difficult for JS engines to perform optimizations, and prohibits some syntax likely to be defined in future versions of ECMAScript 7 | - Works within entire scripts or to individual functions. Does not apply to block statements. 8 | 9 | Doesn't allow global vars: 10 | 11 | ```js 12 | 'use strict' 13 | 14 | name = 'tyler' // throws a ReferenceError 15 | ``` 16 | 17 | Doesn't allow assignment to a non-writable global and/or property. (Same for getters on object ) 18 | 19 | ```js 20 | 'use strict' 21 | 22 | var undefined = 5 // throws a TypeError 23 | var Infinity = 5 // throws a TypeError 24 | 25 | var name = {} 26 | Object.defineProperty(name, 'first', { value: 'clark', writable: false }) 27 | name.first = 'tyler' // throws a TypeError 28 | ``` 29 | 30 | Throws error when attempting to delete undeletable properties: 31 | 32 | ```js 33 | 'use strict' 34 | delete Object.prototype // throws a TypeError 35 | ``` 36 | 37 | Throws when functions have same param names 38 | 39 | ```js 40 | function name(first, first) { // syntax error 41 | 'use strict'; 42 | return first 43 | } 44 | 45 | ``` 46 | 47 | #### Strict mode and `this` 48 | 49 | - When `this` references the global object in browsers, strict mode returns undefined... because it is a security hazard. 50 | 51 | ```js 52 | 'use strict' 53 | 54 | function name() { 55 | return this 56 | } 57 | 58 | name() // undefined 59 | ``` 60 | 61 | #### Strict mode and the future of JS 62 | 63 | - Strict mode makes guesses on names that might be implemented in later ECMAScript versions. 64 | - These words are `implements`, `interface`, `package`, `private`, `protected`, and `public`. 65 | 66 | ```js 67 | 'use strict' 68 | 69 | var implements = 'tyler' // error: Binding implements in strict mode 70 | ``` 71 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "advanced-javascript-fundamentals", 3 | "version": "1.0.0", 4 | "description": "Worksop docs for advanced-javascript-fundamentals", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/twclark0/advanced-javascript-fundamentals.git" 12 | }, 13 | "author": "Tyler Clark", 14 | "license": "MIT", 15 | "bugs": { 16 | "url": "https://github.com/twclark0/advanced-javascript-fundamentals/issues" 17 | }, 18 | "homepage": "https://github.com/twclark0/advanced-javascript-fundamentals#readme" 19 | } 20 | --------------------------------------------------------------------------------