Advanced JavaScript Concepts Cheat Sheet
Advanced JavaScript Concepts Cheat Sheet
I’m
Andrei Neagoie, Founder and Lead Instructor of the Zero To Mastery Academy. We iniBally
created this JavaScript Cheat Sheet for Zero To Mastery students taking our JavaScript: The
Advanced Concepts course where they learn modern, advanced JavaScript pracBces and
grow to be in the top 10% of JavaScript developers. We are now making this available to help
all web developers learn and remember common JavaScript concepts. If you're just starBng
to learn JavaScript, congrats! Being a web developer is a fantasBc career opBon and industry
demand for JavaScript developers is HUGE. Check out my Complete Web Developer in 2021
course to learn everything you need to know to become a web developer. Already a web
developer but stuck in a junior or intermediate role? We can fast track you to get the
knowledge that Senior Javascript Developers have in just 30 days. By the end of our
JavaScript: The Advanced Concepts course, you'll be in the top 10% of JavaScript
Programmers. Start learning for free with over one hour of free lessons by visiBng the
course links above and click PREVIEW next to the lessons. Happy Coding! Andrei Founder &
Lead Instructor, Zero To Mastery Andrei Neagoie P.S. I also recently wrote a book called
Principles For Programmers. You can download the first five chapters for free here. CREDITS
A huge thanks and credit goes to Zero To Mastery student and Star Mentor, Bri_ney, from
her notes while taking and compleBng the JavaScript: The Advanced Concepts course. Check
out some of Bri_ney's other fantasBc notes on a variety of topics. CONTENTS JavaScript
Engine The Parser, The AST, The Interpreter, The Compiler, The Combo WriBng OpBmized
Code MemoizaAon, Inline Caching, Hidden Classes, Managing Arguments Call Stack and
Memory Heap Memory Heap, Call Stack Stack Overflow Garbage CollecAon, Synchronous,
Event Loop and Callback Queue, Job Queue, 3 Ways to Promise, Threads, Concurrency, and
Parallelism ExecuBon Context Global ExecuAon Context, FuncAon ExecuAon Context,
Arrow FuncAons HoisBng Go Back to Table of Contents Page of 1 93 Lexical Environment
Scope Chain FuncBon and Block Scope IIFE - Immediately Invoked FuncBon Expression This
Lexical vs Dynamic Scope Call, Apply, Bind Call, Apply, Bind, Currying with bind JavaScript
Types Objects in JavaScript, PrimiAve vs Non PrimiAve, Type Coercion, StaAc vs Dynamic
Typed Go Back to Table of Contents Page of 2 93 The 2 Pillars: Closures and Prototypes
FuncAon Constructor, Prototypal Inheritance, Prototype vs proto, Callable Object, Higher
Order FuncAons, Closures, Memory Efficient, EncapsulaAon Object Oriented Programming
Object Oriented Programming, Factory FuncAons, Stores, [Link], Constructor
FuncAons, Class, Private and public fields 4 Pillars of OOP FuncBonal Programming Pure
FuncAons, ReferenAal transparency, Idempotence, ImperaAve vs DeclaraAve,
Immutability, ParAal ApplicaAon, Pipe and Compose, Arity ComposiBon vs Inheritance OOP
Problems, Finally Modules in JavaScript Module PaUerns, Issues With Modules, ES6
Modules Go Back to Table of Contents Page of 3 93 Error Handling The End... Data Structures
& Algorithms Data Structures, How do computers work?, Popular Data Structures, Arrays,
ImplemenAng an Array, Hash tables, Hash Collisions, Hashing in JavaScript, Create a Hash
Table Credits Go Back to Table of Contents Page of 4 93 COURSE MAP Course Map Go Back
to Table of Contents Page of 5 93 JAVASCRIPT ENGINE A JavaScript engine is a computer
program that you give JavaScript code to and it tells the computer how to execute it.
Basically a translator for the computer between JavaScript and a language that the computer
understands. But what happens inside of the engine? Well, that depends on the engine.
There are many JavaScript Engines out there and typically they are created by web browser
vendors. All engines are standardized by ECMA Script or ES. List of JavaScript Engines Ni#y
Snippet: 2008 was a pivotal moment for JavaScript when Google created the Chrome V8
Engine. The V8 engine is an open source high-performance JavaScript engine, wriBen in C++
and used in the Chrome browser and powers Node JS. The performance outmatched any
engine that came before it mainly because it combines 2 parts of the engine, the interpreter
and the compiler. Today, all major engines use this same technique. Go Back to Table of
Contents Page of 6 93 THE PARSER Parsing is the process of analyzing the source code,
checking it for errors, and breaking it up into parts. THE AST The parser produces a data
structure called the Abstract Syntax Tree or AST. AST is a tree graph of the source code that
does not show every detail of the original syntax, but contains structural or content-related
details. Certain things are implicit in the tree and do not need to be shown, hence the Btle
abstract. THE INTERPRETER An interpreter directly executes each line of code line by line,
without requiring them to be compiled into a machine language program. Interpreters can
use different strategies to increase performance. They can parse the source code and
execute it immediately, translate it into more efficient machine code, execute precompiled
code made by a compiler, or some combinaBon of these. In the V8 engine, the interpreter
outputs bytecode. Ni#y Snippet: The first JavaScript engine was wriBen by Brendan Eich, the
creator of JavaScript, in 1995 for the Netscape navigator web browser. Originally, the
JavaScript engine only consisted of an interpreter. This later evolved into the SpiderMonkey
engine, sQll used by the Firefox browser. THE COMPILER The compiler works ahead of Bme
to convert instrucBons into a machine-code or lower-level form so that they can be read and
executed by a computer. It runs all of the code and tries to figure out what the code does
and then compiles it down into another language that is easier for the computer to read.
Have you heard of Babel or TypeScript? They are heavily used in the Javascript ecosystem
and you should now have a good idea Go Back to Table of Contents Page of 7 93 of what
they are. Babel is a Javascript compiler that takes your modern JS code and returns browser
compaBble JS (older JS code). Typescript is a superset of Javascript that compiles down to
Javascript. Both of these do exactly what compilers do. Take one language and convert into a
different one! THE COMBO In modern engines, the interpreter starts reading the code line
by line while the profiler watches for frequently used code and flags then passes is to the
compiler to be opBmized. In the end, the JavaScript engine takes the bytecode the
interpreter outputs and mixes in the opBmized code the compiler outputs and then gives
that to the computer. This is called "Just in Time" or JIT Compiler. Ni#y Snippet: Back in 1995
we had no standard between the browsers for compiling JavaScript. Compiling code on the
browser or even ahead of Qme was not feasible because all the browsers were compeQng
against each other and could not agree on an executable format. Even now, different
browsers have different approaches on doing things. Enter WebAssembly a standard for
binary instrucQon (executable) format. Keep your eye on WebAssembly to help standardize
browsers abiliQes to execute JavaScript in the future! WebAssemby WRITING OPTIMIZED
CODE We want to write code that helps the compiler make its opBmizaBons, not work
against it making the engine slower. MemoizaAon MemoizaBon is a way to cache a return
value of a funcBon based on its parameters. This makes the funcBon that takes a long Bme
run much faster aper one execuBon. If the parameter changes, it will sBll have to reevaluate
the funcBon. Go Back to Table of Contents Page of 8 93 Here are a few things you should
avoid when wriBng your code if possible: • eval() • arguments • for in Go Back to Table of
Contents Page of 9 93 // Bad Way function addTo80(n) { [Link]('long time...') return n +
80 }addTo80(5)addTo80(5)addTo80(5)// long time... 85 // long time... 85 // long time... 85 //
Memoized Way functions memoizedAddTo80() { let cache = {} return function(n) { // closure
to access cache obj if (n in cache) { return cache[n] } else { [Link]('long time...') cache[n]
= n + 80 return cache[n] } }}const memoized = memoizedAddTo80()[Link]('1.',
memoized(5))[Link]('2.', memoized(5))[Link]('3.', memoized(5))[Link]('4.',
memoized(10))// long time... // 1. 85 // 2. 85 // 3. 85 // long time... // 4. 90 • with • delete
There are a few main reasons these should be avoided. JavaScript Hidden Classes and Inline
Caching in V8 Managing Arguments Inline Caching If this code gets opBmized to return only
1 name, then the computer would have to do a lot more work if you needed to return a
different user. Hidden Classes Go Back to Table of Contents Page of 10 93 function Animal(x,
y) { this.x = x; this.y = y;}const obj1 = new Animal(1, 2);const obj2 = new Animal(3, 4);obj1.a =
30;obj1.b = 100;obj2.b = 30;obj2.a = 100;delete obj1.x = 30;function findUser(user) { return
`found ${[Link]} ${[Link]}` }const userData = { firstName: 'Brittney',
lastName: 'Postma'}findUser(userData)// if this findUser(userData) is called multiple
times, // then it will be optimized (inline cached) to just be 'found Brittney Postma' By serng
these values in a different order than they were instanBated, we are making the compiler
slower because of hidden classes. Hidden classes are what the compiler uses under the
hood to say that these 2 objects have the same properBes. If values are introduced in a
different order than it was set up in, the compiler can get confused and think they don't
have a shared hidden class, they are 2 different things, and will slow down the computaBon.
Also, the reason the delete keyword shouldn't be used is because it would change the
hidden class. Managing Arguments There are many ways using arguments that can cause a
funcBon to be unopBmizable. Be very careful when using arguments and remember: Safe
Ways to Use Arguments • [Link] • arguments[i] when i is a valid integer • NEVER
use arguments directly without .length or [i] • STRICTLY [Link](y, arguments) is ok Go Back
to Table of Contents Page of 11 93 // This is the more optimized version of the code.
function Animal(x, y) { // instantiating a and b in the constructor this.a = x; this.b = y;}const
obj1 = new Animal(1, 2);const obj2 = new Animal(3, 4);// and setting the values in order
obj1.a = 30;obj1.b = 100;obj2.a = 30;obj2.b = 100; CALL STACK AND MEMORY HEAP The
JavaScript engine does a lot of work for us, but 2 of the biggest jobs are reading and
execuBng it. We need a place to store and write our data and a place to keep track line by
line of what's execuBng. That's where the call stack and the memory heap come in.
Memory Heap The memory heap is a place to store and write informaBon so that we can
use our memory appropriately. It is a place to allocate, use, and remove memory as needed.
Think of it as a storage room of boxes that are unordered. Go Back to Table of Contents Page
of 12 93 // tell the memory heap to allocate memory for a number const number = 11;//
allocate memory for a string const string = "some text";// allocate memory for an object and
it's values const person = { first: "Brittney", last: "Postma" }; Call Stack The call stack keeps
track of where we are in the code, so we can run the program in order. Things are placed
into the call stack on top and removed as they are finished. It runs in a first in last out mode.
Each call stack can point to a locaBon inside the memory heap. In the above snippet the call
stack looks like this (see next page). Go Back to Table of Contents Page of 13 93 function
subtractTwo(num) { return num - 2;}function calculate() { const sumTotal = 4 + 5; return
subtractTwo(sumTotal);}debugger;calculate(); Go Back to Table of Contents Page of 14 93
anonymous; // file is being ran // CALL STACK // hits debugger and stops the file // step
through each line calculate( // steps through calculate() sumTotal = 9 anonymous);// CALL
STACK // steps into subtractTwo(sumTotal) num = 9 subtractTwo; // returns 9 - 2
calculate(anonymous);// CALL STACK // subtractTwo() has finished and has been removed
calculate( // returns 7 anonymous)( // CALL STACK // calculate() has finished and has been
removed anonymous);// CALL STACK // and finally the file is finished and is removed // CALL
STACK STACK OVERFLOW So what happens if you keep calling funcBons that are nested
inside each other? When this happens it’s called a stack overflow. Ni#y Snippet: Did you
know, Google has hard-coded recursion into their program to throw your brain for a loop
when searching recursion? Garbage CollecAon JavaScript is a garbage collected language. If
you allocate memory inside of a funcBon, JavaScript will automaBcally remove it from the
memory heap when the funcBon is done being called. However, that does not mean you can
forget about memory leaks. No system is perfect, so it is important to always remember
memory management. JavaScript completes garbage collecBon with a mark and sweep
method. Go Back to Table of Contents Page of 15 93 // When a function calls itself, // it is
called RECURSION function inception() { inception();}inception();// returns Uncaught
RangeError: // Maximum call stack size exceeded Mark and Sweep Method In the example
above a memory leak is created. By changing the variable person from an object to a string,
it leaves the values of first and last in the memory heap and does not remove it. This can be
avoided by trying to keep variables out of the global namespace, only instanBate variables
inside of funcBons when possible. JavaScript is a single threaded language, meaning only
one thing can be executed at a Bme. It only has one call stack and therefore it is a
synchronous language. Go Back to Table of Contents Page of 16 93 var person = { first:
"Brittney", last: "Postma" };person = "Brittney Postma"; Synchronous So, what is the issue
with being a single threaded language? Lets's start from the beginning. When you visit a web
page, you run a browser to do so (Chrome, Firefox, Safari, Edge). Each browser has its own
version of JavaScript RunAme with a set of Web API's, methods that developers can access
from the window object. In a synchronous language, only one thing can be done at a Bme.
Imagine an alert on the page, blocking the user from accessing any part of the page unBl the
OK bu_on is clicked. If everything in JavaScript that took a significant amount of Bme,
blocked the browser, then we would have a pre_y bad user experience. This is where
concurrency and the event loop come in. Event Loop and Callback Queue When you run
some JavaScript code in a browser, the engine starts to parse the code. Each line is executed
and popped on and off the call stack. But, what about Web API's? Web API's are not
something JavaScript recognizes, so the parser knows to pass it off to the browser for it to
handle. When the browser has finished running its method, it puts what is needed to be ran
by JavaScript into the callback queue. The callback queue cannot be ran unBl the call stack is
completely empty. So, the event loop is constantly checking the call stack to see if it is empty
so that it can add anything in the callback queue back into the call stack. And finally, once it
is back in the call stack, it is ran and then popped off the stack. Go Back to Table of Contents
Page of 17 93 In the last example, we get the same output. How does this work if it waits 0
seconds? The JavaScript engine will sBll send off the setTimeout() to the Web API to be ran
and it will then go into the callback queue and wait unBl the call stack is empty to be ran. So,
we end up with the exact same end point. Go Back to Table of Contents Page of 18 93
[Link]("1");// goes on call stack and runs 1 setTimeout(() => { [Link]("2"),
1000;});// gets sent to web api // web api waits 1 sec, runs and sends to callback queue //
the javascript engine keeps going [Link]("3");// goes on call stack and runs 3 // event
loop keeps checking and see call stack is empty // event loop sends calback queue into call
stack // 2 is now ran // 1 // 3 // 2 // Example with 0 second timeout
[Link]("1");setTimeout(() => { [Link]("2"), 0;});[Link]("3");// 1 // 3 // 2 // Still
has the same output JS RunBme Playground What the heck is the event loop anyway? |
Philip Roberts | JSConf EU (link to YouTube) Ni#y Snippet: UnQl 2009, JavaScript was only
run inside of the browser. That is when Ryan Dahl decided it would be great if we could use
JavaScript to build things outside the browser. He used C and C++ to build an executable
(exe) program called Node JS. Node JS is a JavaScript runQme environment built on Chrome's
V8 engine that uses C++ to provide the event loop and callback queue needed to run
asynchronous operaQons. Go Back to Table of Contents Page of 19 93 2020 Update = Deno
10 Things I Regret About [Link] - Ryan Dahl (link to YouTube) The very same Ryan Dahl
then gave a talk back in 2018, 10 Things I Regret About [Link] which led to the recent
release of his new (and improved) JavaScript and TypeScript called Deno which aims to
provide a producBve and secure scripBng environment for the modern programmer. It is
built on top of V8, Rust, and TypeScript. If you're interested in learning Deno, Zero To
Mastery instructors, Andrei Neagoie and Adam Odziemkowski (also an official Deno
contributor), released the very first comprehensive Deno course. Go Back to Table of
Contents Page of 20 93 Job Queue The job queue or microtask queue came about with
promises in ES6. With promises we needed another callback queue that would give higher
priority to promise calls. The JavaScript engine is going to check the job queue before the
callback queue. Go Back to Table of Contents Page of 21 93 // 1 Callback Queue ~ Task
Queue setTimeout(() => { [Link]("1", "is the loneliest number");}, 0);setTimeout(() =>
{ [Link]("2", "can be as bad as one");}, 10);// 2 Job Queue ~ Microtask Queue
[Link]("hi").then(data => [Link]("2", data));// 3 [Link]("3", "is a
crowd");// 3 is a crowd // 2 hi // undefined Promise resolved // 1 is the loneliest number // 2
can be as bad as one 3 Ways to Promise There are 3 ways you could want promises to
resolve, parallel (all together), sequenBal (1 aper another), or a race (doesn't ma_er who
wins). Go Back to Table of Contents Page of 22 93 const promisify = (item, delay) => new
Promise(resolve => setTimeout(() => resolve(item), delay));const a = () => promisify("a",
100);const b = () => promisify("b", 5000);const c = () => promisify("c", 3000);async function
parallel() { const promises = [a(), b(), c()]; const [output1, output2, output3] = await
[Link](promises); return `parallel is done: ${output1} ${output2} ${output3}`;}async
function sequence() { const output1 = await a(); const output2 = await b(); const output3 =
await c(); return `sequence is done: ${output1} ${output2} ${output3}`;}async function race()
{ const promises = [a(), b(), c()]; const output1 = await [Link](promises); return `race
is done: $
{output1}`;}sequence().then([Link]);parallel().then([Link]);race().then([Link]
);// race is done: a // parallel is done: a b c // sequence is done: a b c Threads, Concurrency,
and Parallelism Even though JavaScript is a single threaded language, there are worker
threads that work in the background that don't block the main thread. Just like a browser
creates a new thread when you open a new tab. The workers work through messages being
sent, but don't have access to the full program. Web Workers Scaling NodeJS MulB threading
EXECUTION CONTENT Code in JavaScript is always ran inside a type of execuAon context.
ExecuBon context is simply the environment within which your code is ran. There are 2 types
of execuBon context in JavaScript, global or funcBon. There are 2 stages as well to each
context, the creaBon and execuBng phase. As the JavaScript engine starts to read your code,
it creates something called the Global ExecuAon Context. Global ExecuAon Context
CreaAon Phase 1. Global object created 2. IniBalizes this keyword to global Go Back to Table
of Contents Page of 23 93 var worker = new
Worker("[Link]");[Link]("Helloooo");addEventListener("message");
ExecuAng Phase 3. Variable Environment created - memory space for var variables and
funcQons created 4. IniBalizes all variables to undefined (also known as hoisAng) and places
them with any funcBons into memory FuncAonal ExecuAon Context A funcBon context is
created by the JavaScript engine when it sees a funcBon call. Each funcBon gets its own
execuBon context. CreaAon Phase 1. Argument object created with any arguments 2. Sets
this to the global object unless in strict mode, where it’s undefined ExecuAng Phase 3.
Variable Environment created - memory space for variable and funcQons created 4.
IniBalizes all variables to undefined and places them into memory with any new funcBons Go
Back to Table of Contents Page of 24 93 this;window;this === window;// Window {...} //
Window {...} // true Go Back to Table of Contents Page of 25 93 // Function Execution
Context creates arguments object function showArgs(arg1, arg2) { [Link]('arguments: ',
arguments); return `argument 1 is: ${arg1} and argument 2 is: ${arg2}`;}showArgs("hello",
"world");// arguments: { 0: 'hello', 1: 'world' } // argument 1 is hello and argument 2 is world
function noArgs() { [Link]('arguments: ', arguments);}noArgs();// arguments: {} // even
though there are no arguments, the object is still created function showArgs(arg1, arg2)
{ [Link]("arguments: ", arguments);
[Link]([Link](arguments));}showArgs("hello", "world");// arguments: { 0: 'hello', 1:
'world' } // [ 'hello', 'world' ] function showArgs2(...args)
{ [Link]([Link]("arguments: ", args)); [Link]([Link](arguments)); return
`${args[0]} ${args[1]}`;}showArgs2("hello", "world");// arguments: [ 'hello', 'world' ] //
[ 'hello', 'world' ] // hello world The keyword arguments can be dangerous to use in your
code as is. In ES6, a few methods were introduced that can help be_er use arguments.
Arrow FuncAons Some people think of arrow funcQons as just being syntacQc sugar for a
regular funcQon, but arrow funcQons work a bit differently than a regular funcQon. They are
a compact alternaQve to a regular funcQon, but also without its own bindings to this,
arguments, super, or [Link] keywords. Arrow funcQons cannot be used as constructors
and are not the best opQon for methods. HOISTING HoisBng is the process of purng all
variable and funcBon declaraBons into memory during the compile phase. In JavaScript,
funcBons are fully hoisted, var variables are hoisted and iniBalized to undefined, and let and
const variables are hoisted but not iniBalized a value. Var variables are given a memory
allocaBon and iniBalized a value of undefined unBl they are set to a value in line. So if a var
variable is used in the code before it is iniBalized, then it will return undefined. However, a
funcBon can be called from anywhere in the code base because it is fully hoisted. If let and
const are used Go Back to Table of Contents Page of 26 93 var obj = { // does not create a
new scope i: 10, b: () => [Link](this.i, this), c: function() { [Link](this.i,
this); }};obj.b(); // prints undefined, Window {...} (or the global object) obj.c(); // prints 10,
Object {...}``` before they are declared, then they will throw a reference error because they
have not Go Back to Table of Contents Page of 27 93 // function expression gets hoisted as
undefined var sing = function() { [Link]("uhhhh la la la");};// function declaration gets
fully hoisted function sing2() { [Link]("ohhhh la la la");}// function declaration gets
hoisted function a() { [Link]("hi");}// function declaration get rewritten in memory
function a() { [Link]("bye");}[Link](a());// bye // variable declaration gets hoisted
as undefined var favoriteFood = "grapes";// function expression gets hoisted as undefined
var foodThoughts = function() { // new execution context created favoriteFood = undefined
[Link](`Original favorite food: ${favoriteFood}`); // variable declaration gets hoisted as
undefined var favoriteFood = "sushi"; [Link](`New favorite food: $
{favoriteFood}`);};foodThoughts(); yet been iniBalized (conBnued on next page). TAKEAWAYS
Avoid hoisQng when possible. It can cause memory leaks and hard to catch bugs in your
code. Use let and const as your go to variables. LEXICAL ENVIRONMENT A lexical
environment is basically the scope or environment the engine is currently reading code in. A
new lexical environment is created when curly brackets {} are used, even nested brackets
{{...}} create a new lexical environment. The execuBon context tells the engine which lexical
environment it is currently working in and the lexical scope determines the available
variables. Go Back to Table of Contents Page of 28 93 function one() { var isValid = true; //
local env two(); // new execution context }function two() { var isValid; // undefined }var
isValid = false; // global one();/* two() isValid = undefined one() isValid = true global() isValid
= false ------------------------ call stack*/ SCOPE CHAIN Each environment context that is
created has a link outside of its lexical environment called the scope chain. The scope chain
gives us access to variables in the parent environment (conBnued on next page). Go Back to
Table of Contents Page of 29 93 In this example, all the funcBons have access to the global
variable x, but trying to access a variable from another funcBon would return an error. The
example below will show how the scope chain links each funcBon. Go Back to Table of
Contents Page of 30 93 var x = "x";function findName() { [Link](x); var b = "b"; return
printName();}function printName() { var c = "c"; return "Brittney Postma";}function
sayMyName() { var a = "a"; return findName();}sayMyName();// sayMyName runs a = 'a' //
findName runs // x // b = 'b' // printName runs c = 'c' // Brittney Postma In this example, you
can see that the funcBons only get access to the variables in their parent container, not a
child. The scope chain only links down the call stack, so you almost have to think of it in
reverse. It goes up to the parent, but down the call stack. Go Back to Table of Contents Page
of 31 93 function sayMyName() { var a = "a"; [Link](b, c); // returns error return
function findName() { var b = "b"; [Link](a); // a [Link](c); // returns error return
function printName() { var c = "c"; [Link](a, b); // a, b }; };}sayMyName()()(); //each
function is returned and has to be called JavaScript is Weird Go Back to Table of Contents
Page of 32 93 // It asks global scope for height. // Global scope says: ummm... no but here I
just created it for you. // We call this leakage of global variables. // Adding 'use strict' to the
file prevents this and causes an error. function weird() { height = 50;}var heyhey = function
doodle() { // code here };heyhey();doodle(); // Error! because it is enclosed in its own scope.
FUNCTION AND BLOCK SCOPE Most programming languages are block scoped, meaning
every Bme you see a new { } (curly braces) is a new lexical environment. However, JavaScript
is funcBon scoped, meaning it only creates a new local environment if it sees the keyword
funcBon on the global scope. To give us access to block scope, in ES6 let and const were
added to the language. Using these can prevent memory leaks, but there is sBll an argument
to be made for using var. Go Back to Table of Contents Page of 33 93 //Function Scope
function loop() { for (var i = 0; i < 5; i++) { [Link](i); } [Link]("final", i); // returns
final 5 }//Block Scope function loop2() { for (let i = 0; i < 5; i++) { // can access i here }
[Link]("final", i); // returns an error here }loop();/* 1 2 3 4 final 5*/ loop2();//
ReferenceError: i is not defined LET AND CONST Variable declaraQons with let and const
work differently from the var variable declaraQon and I wanted to take a minute to explain.
When a lexical scope is entered and the execuQon context is created, the engine allocates
memory for any var variable in that scope and iniQalizes it to undefined. The let and const
variables only get iniQalized on the line they are executed on and only get allocated
undefined if there is no assignment to the variable. Trying to access a let or const variable
before it is declared or outside of its block without returning it will result in a Reference Error.
IIFE - IMMEDIATELY INVOKED FUNCTION EXPRESSION Immediately Invoked FuncBon
Expression or more simply IIFE is a JavaScript funcBon that runs as soon as it is defined. Can
also be referred to as a Self-ExecuBng Anonymous FuncBon. Takeaways: Avoid polluQng the
global namespace or scope when possible. Go Back to Table of Contents Page of 34 93 //
Grouping Operator () creates a lexical scope (function() { // statements })();// Immediately
invokes the function with 2nd set of () THIS Here we are… The moment has arrived, Bme to
talk about this. What is this? Why is this so confusing? For some, this is the scariest part of
JavaScript. Well, hopefully we can clear some things up. this is the object that the funcRon is
a property of There that's simple right? Well, maybe not, what does that mean? Back in
ExecuBon Context, we talked about how the JavaScript engine creates the global execuBon
context and iniBalizes this to the global window object. Go Back to Table of Contents Page of
35 93 this; // Window {...} window; // Window {...} this === window; // true function a()
{ [Link](this);}a();// Window {...} In the example above, it is easy to understand that this
is equal to the window object, but what about inside of funcBon a? Well, what object is
funcBon a apart of? In the dev tools, if you expand the window object and scroll down the
list, you will see a() is a method on the window object. By calling a(), you are essenBally
saying window.a() to the console. this refers to whatever is on the lec of the . (dot) when
calling a method SBll confused? Try this: Go Back to Table of Contents Page of 36 93 const
obj = { property: `I'm a property of obj.`, method: function() { // this refers to the object obj
[Link]([Link]); }};[Link]();// I'm a property of obj. // obj is to the left of the
dot [Link]();function whichName() { [Link]([Link]);}var name =
"window";const obj1 = { name: "Obj 1", whichName};const obj2 = { name: "Obj 2",
whichName};whichName(); // window [Link](); // Obj 1 [Link](); // Obj
2 Another way to look at this is to check which object called it. Here is this 4 ways: • new
keyword binding - the new keyword changes the meaning of this to be the object that is
being created. • implicit binding - "this" refers to the object that is calling it. It is implied,
without doing anything it's just how the language works. • explicit binding - using the "bind"
keyword to change the meaning of "this". • arrow funcAons as methods - "this" is lexically
scoped, refers to it's current surroundings and no further. However, if "this" is inside of a
method's funcBon, it falls out of scope and belongs to the window object. To correct this,
you can use a higher order funcBon to return an arrow funcBon that calls "this". Go Back to
Table of Contents Page of 37 93 const a = function() { [Link]("a", this); const b =
function() { [Link]("b", this); const c = { hi: function() { [Link]("c", this); } }; [Link](); //
new obj c called function }; b(); // ran by a window.a(b()) };a(); // called by window // a
Window {…} // b Window {…} // c {hi: ƒ} Go Back to Table of Contents Page of 38 93 // new
binding function Person(name, age) { [Link] = name; [Link] = age;
[Link](this);}const person1 = new Person("person1", 55);// this = Person { name:
'person1', age: 55 } //implicit binding const person = { name: "person", age: 20, hi()
{ [Link]("hi " + this); }};[Link]();// this = person { name: 'person', age: 20, hi()
{...} } //explicit binding let name = "Brittney";const person3 = { name: "person3", age: 50, hi:
function() { [Link]("hi " + [Link]); }.bind(window)};[Link]();// hi Brittney // this
= window {...} // arrow functions inside objects const person4 = { name: "person4", age: 40,
hi: function() { var inner = () => { [Link](this); }; return inner(); }};[Link]();// this =
person4 { name: 'person4', age: 40, hi() {...} } // if either function is changed around, it
doesn't work Lexical vs Dynamic Scope A big gotcha for a lot of people working with *this is
when a funcBon is ran inside of another funcBon. It gets a li_le confusing, but we can
remember who called the funcBon. In the example above, the obj called sing() and then
anotherFunc() was called within the sing() funcBon. In JavaScript, that funcBon defaults to
the Window object. It happens because everything in JavaScript is lexically scoped except for
the this keyword. It doesn't ma_er where it is wri_en, it ma_ers how it is called. Changing
anotherFunc() instead to an arrow funcBon will fix this problem, as seen below. Arrow
funcBons do not bind or set their own context for this. If this is used in an arrow funcBon, it
is taken from the outside. Arrow funcBons also have no arguments created as funcBons do.
Go Back to Table of Contents Page of 39 93 const obj = { name: "Billy", sing()
{ [Link]("a", this); var anotherFunc = function() { [Link]("b", this); };
anotherFunc(); }};[Link]();// a {name: "Billy", sing: ƒ} // b Window {…} const obj = { name:
"Billy", sing() { [Link]("a", this); var anotherFunc = () => { [Link]("b", this); };
anotherFunc(); }};[Link]();// a {name: "Billy", sing: ƒ} // b {name: "Billy", sing: ƒ} Okay, last
example to really solidify our knowledge of this. Aper everything is said and done, using this
can sBll be a bit confusing. If you aren't sure what it's referencing, just [Link](this) and
see where it's poinBng. Go Back to Table of Contents Page of 40 93 var b = { name: "jay",
say() { [Link](this); }};var c = { name: "jay", say() { return function()
{ [Link](this); }; }};var d = { name: "jay", say() { return () =>
[Link](this); }};[Link](); // b {name: 'jay', say()...} // b called the function [Link](); //
function() {[Link](this)} // returned a function that gets called later [Link]()(); // Window
{...} // [Link]() gets the function and the Window runs it [Link](); // () => [Link](this) //
returned the arrow function [Link]()(); // d {name: 'jay', say()...} // arrow function does not
rebind this and inherits this from parent CALL, APPLY, BIND Call Call is a method of an object
that can subsBtute a different object than the one it is wri_en on. In this example call is used
to borrow the heal method from the wizard and is used on the archer (which is actually
poinBng this to archer), with the opBonal arguments added. Apply Apply is almost idenBcal
to call, except that instead of a comma separated list of arguments, it takes an array of
arguments. Go Back to Table of Contents Page of 41 93 const wizard = { name: "Merlin",
health: 100, heal(num1, num2) { return ([Link] += num1 + num2); }};const archer =
{ name: "Robin Hood", health: 30 };[Link](archer); // health: 30 [Link](archer,
50, 20);[Link](archer); // health: 100 // instead of this // [Link](archer, 50, 20)
// apply looks like this [Link](archer, [50, 20]);// this has the same result Bind
Unlike call and apply, bind does not run the method it is used on, but rather returns a new
funcBon that can then be called later. Currying With Bind Currying is breaking down a
funcBon with mulBple arguments into one or more funcBons that each accept a single
argument. Exercise: Find the largest number in an array Go Back to Table of Contents Page
of 42 93 const array = [1, 2, 3];function getMaxNumber(arr) { return [Link](null,
arr);}getMaxNumber(array); // 3 [Link](archer); // health: 30 const healArcher =
[Link](archer, 50, 20);healArcher();[Link](archer); // health: 100 function
multiply(a, b) { return a * b;}let multiplyByTwo = [Link](this, 2);multiplyByTwo(4); // 8
let multiplyByTen = [Link](this, 10);multiplyByTen(6); // 60 Exercise 2: How would you
fix this? Go Back to Table of Contents Page of 43 93 const character = { name: "Simon",
getCharacter() { return [Link]; }};const giveMeTheCharacterNOW =
[Link];//How Would you fix this? [Link]("?",
giveMeTheCharacterNOW()); //this should return 'Simon' but doesn't // ANSWER // change
this line const giveMeTheCharacterNOW =
[Link](character);[Link]("?", giveMeTheCharacterNOW()); // ?
Simon JAVASCRIPT TYPES Bri_ney goes into all of the types in her basic JavaScript course
notes, but decided to take a deeper dive into types in JavaScript here. Type Result *Null -
Why does the typeof null return object? When JavaScript was first implemented, values were
represented as a type tag and a value. The objects type tag was 0 and the NULL pointer
(0x00 in most plaeorms) consequently had 0 as a type tag as well. A fix was proposed that
would have made typeof null === 'null', but it was rejected due to legacy code that would
have broken. Undefined undefined Null object* Boolean boolean Number number BigInt
(new in ECMAScript 2020) bigint String string Symbol (new in ECMAScript 2015) symbol
FuncBon object function Any other object object Go Back to Table of Contents Page of 44
93 // Numbers typeof 37 === "number";typeof 3.14 === "number";typeof 42 ===
"number";typeof Math.LN2 === "number";typeof Infinity === "number";typeof NaN ===
"number"; // Despite being "Not-A-Number" typeof Number("1") === "number"; // Number
tries to parse things into numbers typeof Number("shoe") === "number"; // including values
that cannot be type coerced to a number typeof 42n === "bigint"; Go Back to Table of
Contents Page of 45 93 // Strings typeof "" === "string";typeof "bla" === "string";typeof
`template literal` === "string";typeof "1" === "string"; // note that a number within a string is
still typeof string typeof typeof 1 === "string"; // typeof always returns a string typeof
String(1) === "string"; // String converts anything into a string, safer than toString //
Booleans typeof true === "boolean";typeof false === "boolean";typeof Boolean(1) ===
"boolean"; // Boolean() will convert values based on if they're truthy or falsy typeof !!1 ===
"boolean"; // two calls of the ! (logical NOT) operator are equivalent to Boolean() // Symbols
typeof Symbol() === "symbol";typeof Symbol("foo") === "symbol";typeof [Link]
=== "symbol";// Undefined typeof undefined === "undefined";typeof
declaredButUndefinedVariable === "undefined";typeof undeclaredVariable ===
"undefined";// Objects typeof { a: 1 } === "object";// use [Link] or
[Link] // to differentiate regular objects from arrays typeof [1, 2, 4]
=== "object";typeof new Date() === "object";typeof /regex/ === "object"; // See Regular
expressions section for historical results // The following are confusing, dangerous, and
wasteful. Avoid them. typeof new Boolean(true) === "object";typeof new Number(1) ===
"object";typeof new String("abc") === "object";// Functions typeof function() {} ===
"function";typeof class C {} === "function";typeof [Link] === "function"; Undefined vs
Null: Undefined is the absence of definiQon, it has yet to be defined, and null is the absence
of value, there is no value there. Objects in JavaScript Objects are one of the broadest types
in JavaScript, almost "everything" is an object. MDN Standard built-in objects • Booleans can
be objects (if defined with the new keyword) • Numbers can be objects (if defined with the
new keyword) • Strings can be objects (if defined with the new keyword) • Dates are always
objects • Maths are always objects • Regular expressions are always objects • Arrays are
always objects • FuncBons are always objects • Objects are always objects PrimiAve vs. Non
PrimiAve PrimiAve - PrimiBve values are defined by being immutable, they cannot be
altered. The variable assigned to a primiBve type may be reassigned to a new value, but the
original value can not be changed in the same way objects can be modified. PrimiBves are
passed by value, meaning their values are copied and then placed somewhere else in the
memory. They are also compared by value. There are currently 7 primiBve data types in
JavaScript. • string • number • bigint • boolean • null • undefined • symbol Go Back to Table
of Contents Page of 46 93 Non PrimiAve - The only type that leaves us with is objects.
Objects are able to be mutated and their properBes are passed by reference, meaning their
properBes are not stored separately in memory. A new variable poinBng to an object will not
create a copy, but reference the original objects locaBon in memory. Therefore, changing the
2nd object will also change the first. There are two ways to get around this, [Link]()
or use the spread operator {...} to "spread" or expand the object into a new variable. By
doing this, it will allow the new variable to be modified without changing the original.
However, these only create a "shallow copy". Shallow copy: Shallow copy is a bit-wise copy
of an object. A new object is created that has an exact copy of the values in the original
object. If any of the fields of the object are references to other objects, just the reference
addresses are copied i.e., only the memory address is copied. > Deep copy: A deep copy
copies all fields, and makes copies of dynamically allocated memory pointed to by the fields.
A deep copy occurs when an object is copied along with the objects to which it refers. >
Understanding Deep and Shallow Copy Go Back to Table of Contents Page of 47 93 // objects
are passed by reference let obj = { name: "object 1" };let newObj = obj; // points to same
place in memory as obj [Link] = "newObj"; // modifies the memory // Since both
point to the same place... [Link](obj); // {name: newObj} [Link](newObj); //
{name: newObj} // They are both modified. let arr = [1, 2, 3];let newArr =
arr;[Link](4);[Link](arr); // [1, 2, 3, 4] [Link](newArr); // [1, 2, 3, 4] Go Back
to Table of Contents Page of 48 93 const originalObj = { nested: { nestedKey: "nestedValue" },
key: "value" };// originalObj points to location 1 in memory const assignObj = originalObj;//
assignObj will point to 1 in memory const shallowObj = { ...originalObj };// shallowObj points
to a new location 2, but references location 1 for the nested object const deepObj =
[Link]([Link](originalObj));// deepObj clones all parts of the object to a new
memory address Go Back to Table of Contents Page of 49 93 const originalObj = { nested:
{ nestedKey: "nestedValue" }, key: "value" };const assignObj = originalObj;const shallowObj =
{ ...originalObj };const deepObj =
[Link]([Link](originalObj));[Link]("originalObj: ",
originalObj);[Link]("assignObj: ", assignObj);[Link]("shallowObj: ",
shallowObj);[Link]("deepObj: ", deepObj);/*originalObj: {nested: { nestedKey:
"changed value" }, key: "changed value"}assignObj: {nested: { nestedKey: "changed value" },
key: "changed value"}shallowObj: {nested: { nestedKey: "changed value" }, key:
"value"}deepObj: {nested: { nestedKey: "nestedValue" }, key: "value"}*/ Ni#y Snippet: If you
try to check if 2 objects with the same properQes are equal with obj1 = obj2, it will return
false. It does this because each object has its own address in memory as we learned about.
The easiest way to check the contents of the objects for equality is this. This will return true if
all properQes are the same. Type Coercion Type coercion is the process of converBng one
type of value into another. There are 3 types of conversion in JavaScript. • to stringx • to
boolean • to number Strict equals: The triple equals (===) or strict equality compares two
values without type coercion. If the values are not the same type, then the values are not
equal. This is almost always the right way to check for equality in JavaScript, so you don't
accidentally coerce a value and end up with a bug in your program. Here is the MDN Equality
Comparison page and the ECMAScript Comparison Algorithm. Go Back to Table of Contents
Page of 50 93 [Link](obj1) === [Link](obj2);let num = 1;let str = "1";num ==
str; // true // notice loose equality ==, not === // double equals (==) will perform a type
conversion // one or both sides may undergo conversions // in this case 1 == 1 or '1' == '1'
before checking equality There are several edge cases that you will come in contact with in
JavaScript as well. Check out this Comparison Table if you have quesBons about how types
are coerced. StaAc vs Dynamic Typed The major difference between staBc and dynamic
typed languages is when the types of variables are checked. StaBc typed languages (Java, C,
C++, C#) are checked during the compile stage, so all types are known before run-Bme.
Dynamic languages (JavaScript, PHP, Python, Ruby, Perl) are checked on the fly, during the
execuBon stage. Also, aper dividing the languages into dynamic and staBc, they are then
divided again into strong and weak typed. Weakly typed (JavaScript, PHP, C, C++) languages
can make type coercions implicitly while strongly typed (Python, Ruby, C#, Java) do not allow
conversions between unrelated types. THE 2 PILLARS: CLOSURES AND PROTOTYPES
Closures and Prototypal Inheritance are two things that make JavaScript special and different
from other programming languages. FuncAon Constructor FuncBons are objects in
JavaScript, which is not true for other languages. Because of that, they can be called mulBple
ways, but they can also be constructors. A funcAon constructor creates a new object and
returns it. Every JavaScript funcBon, is actually a funcBon object itself. Go Back to Table of
Contents Page of 51 93 Almost everything in JavaScript can be created with a constructor.
Even basic JavaScript types like numbers and strings can be created using a constructor. Go
Back to Table of Contents Page of 52 93 (function() {}.contructor === Function);// true //
function constructor new Function("optionalArguments", "functionBody");const four = new
Function("return four"); // 4 const sum = new Function("x", "y", "return x +
y");[Link](sum(2, 3)); // 5 // examples of constructor functions in JavaScript const five =
new Number(5);const assignFive = 5;// this is different than using regular assignment const
newString = new String(`I am a new string`);const assignString = `I am an assigned
string`;typeof five; // object typeof assignFive; // number typeof newString; //object typeof
assignString; // string five === assignFive; // false five == assignFive; // true - types are
coerced // Notice how the types are different // depending on how they are created. //
Arrays, Booleans, Dates, Objects, and Strings // can be created this way as well. Prototypal
Inheritance Almost all objects in Javascript pass down properBes through a prototype chain.
We call this chain, prototypal inheritance. The child of the object "inherits" properBes from
its parent. All objects in JavaScript are descended from the Object constructor unless
deliberately created or altered to not do so. The objects inherit methods and properBes
from [Link]. The prototype property also has an accessor property called
__proto__ that creates a link between the current object and points to the object it was
created from, the "prototype". Prototype vs __proto__ Understanding the difference
between __proto__ and prototype can be quite a confusing concept for JavaScript
developers. Every funcBon in JavaScript automaBcally gets a prototype property when it is
created that gives it the call, apply, and bind methods. It doesn't really do anything with
regular funcBons, but in constructor Go Back to Table of Contents Page of 53 93
[Link].__proto__;// null [Link];{ __proto__: null; // ...more methods
and properties }Object;// function Object() // This is the object constructor function
[Link];// function Object() // Points to the constructor
Object.__proto__;// function () {...} // Because it is created with a constructor function
funcBons the prototype property allows us to add our own methods to the objects we
create. The __proto__ property is what creates the link between prototype objects, the child
inherits properBes from the parent through the prototype chain. Each Bme a new object is
created in JavaScript, it uses the __proto__ ge_er funcBon to use a built in constructor
funcBon based on what is being created. This could be an Array, Boolean, Date, Number,
Object, String, FuncBon, or RegExp. Each one has their own separate properBes and
methods that they inherit from the constructor. Go Back to Table of Contents Page of 54 93
let newArr = new Array newArr/* [] {// all array properties and methods// inherited from
Array constructor function. length: 0 prototype: { concat, forEach, pop, splice... __proto__:
Array(0) prototype: { __proto__: Object prototype: { __proto__: null } } } } Callable Object
Because funcBons are objects in JavaScript, this also gives them the ability to have
properBes added to them. This creates a callable object, a special object that creates
properBes not available on normal objects. Below is a visualizaBon of how this works under
the hood. This code can not be ran in the console, but it is a representaBon of how the
object looks. Go Back to Table of Contents Page of 55 93 function say() { [Link]('say
something')}[Link] = 'yell something' // under the hood visual // will not run or show in
console const funcObj = { // name will not exist if anonymous name: 'say', // code to be ran
(): [Link]('say something') // properties get added // apply, arguments, bind, call, caller,
length, name, toString yell: 'yell something',}// with an obj const obj = { // nothing gets
created } Ni#y snippet: You might hear people say "FuncQons are first-class ciQzens in
JavaScript". All this means is that funcQons can be passed around as if they were a
JavaScript type. Anything that can be done with other 7n hhb , can also be done with
funcQons. This introduces JavaScript to a whole different type of programming called
funcRonal programming. Below are some examples of how funcQons work differently in
JavaScript. Higher Order FuncAons A Higher Order FuncBon (HOF) is a funcBon that either
takes a funcBon as an argument or returns another funcBon. There are 3 kinds of funcBons
in JavaScript. • funcBon () • funcBon (a,b) • funcBon hof() { return funcBon () {} } Instead of
wriBng mulBple funcBons that do the same thing, remember DRY (don't repeat yourself).
Imagine in the example below, if you separated each code out into individual funcBons how
much more code you would be wriBng and how much code would be repeated. Go Back to
Table of Contents Page of 56 93 // setting functions to variables var setFuncToVar = function
() {}// call function within another function a(fn) { fn()}a(function () {[Link]('a new
function')}// return functions within another function b() { return function c()
{[Link]('another func')}} Take the example below of how you can separate code out and
break it down to make it more reusable. Go Back to Table of Contents Page of 57 93 const
giveAccessTo = name => `Access granted to ${name}`;function auth(roleAmt) { let array = [];
for (let i = 0; i < roleAmt; i++) { [Link](i); } return true;}function checkPerson(person, fn) {
if ([Link] === "admin") { fn(100000); } else if ([Link] === "user") { fn(500000); }
return giveAccessTo([Link]);}checkPerson({ level: "admin", name: "Brittney" },
auth);// "Access granted to Brittney" function multBy(a) { return function(b) { return a *
b; };}// can also be an arrow function const multiplyBy = a => b => a * b;const multByTwo =
multiplyBy(2);const multByTen = multiplyBy(10);multByTwo(4); // 8 multByTen(5); // 50
Closures Closures allow a funcBon to access variables from an enclosing scope or
environment even aper it leaves the scope in which it was declared. In other words, a
closure gives you access to its outer funcBons scope from the inner scope. The JavaScript
engine will keep variables around inside funcBons that have a reference to them, instead of
"sweeping" them away aper they are popped off the call stack. Go Back to Table of Contents
Page of 58 93 function a() { let grandpa = 'grandpa' return function b() { let father = 'father'
let random = 12345 // not referenced, will get garbage collected return function c() { let son
= 'son' return `closure inherited all the scopes: ${grandpa} > ${father} > ${son}` } }}a()()()//
closure inherited all the scopes: grandpa > father > son const closure = grandma => mother
=> daughter => return `${grandma} > ${mother} > ${daughter} ` // grandma > mother >
daughter A Fun Example with Closures: Do not run this in the console, it takes 1 day to
Qmeout! Two of the major reasons closures are so beneficial are memory efficiency and
encapsulaBon. Go Back to Table of Contents Page of 59 93 function callMeMaybe() { const
callMe = `Hey, I just met you!` setTimeout(function() { [Link](callMe) },
8640000000);callMeMaybe()// ONE DAY LATER // Hey, I just met you! Memory Efficient
Using closures makes your code more memory efficient. Take the example below. Go Back to
Table of Contents Page of 60 93 function inefficient(idx) { const bigArray = new
Array(7000).fill("😄 "); [Link]("created!"); return bigArray[idx];}function efficient()
{ const bigArray = new Array(7000).fill("😄 "); [Link]("created again!"); return
function(idx) { return
bigArray[idx]; };}inefficient(688);inefficient(1000);inefficient(6500);const getEfficient =
efficient();getEfficient(688);getEfficient(1000);getEfficient(6500);// created! // created! //
created! // created Again! // '😄 ' // inefficient created the bigArray 3 times // efficient
created the bigArray only once EncapsulaAon EncapsulaBon means the restricBon of direct
access to some of an object's components. It hides as much as possible of an object's
internal parts and only exposes the necessary parts to run. Why use encapsulaBon? •
Security - Controlled access • Hide ImplementaBon and Expose Behaviours • Loose Coupling
- Modify the implementaBon at any Bme Go Back to Table of Contents Page of 61 93 const
encapsulation = () => { let people = []; const setName = name => [Link](name); const
getName = idx => people[idx]; const rmName = idx => [Link](idx, 1); return
{ setName, getName, rmName };};const data = encapsulation();[Link]("Brittney"); //
0 [Link](0); // 'Brittney' [Link](0); // ['Brittney'] // you have no access to the
array people // can only change it via methods provided OBJECT ORIENTED PROGRAMMING
VS FUNCTIONAL PROGRAMMING There are 2 basic philosophies when it comes to how you
structure your programs, object oriented and funcBonal. Each style has its use in
programming, it is not one over the other, but merely a preference in style. Object Oriented
Programming Object Oriented Programming, or OOP, is the idea that all code should be
grouped into "boxes" (objects) to make your program easier to read and understand.
Keeping the data encapsulated helps to keep the program organized. Each object has a state
that defines what it does and methods (funcBons on an object) that can use or modify the
state. Considering almost everything in JavaScript is an object, you would think this would be
easy to do. Say we want to create a game that has lots of characters that all have different
abiliBes. How would we go about this? Go Back to Table of Contents Page of 62 93 Go Back
to Table of Contents Page of 63 93 const elf1 = { name: 'Dobby', type: 'house', weapon:
'cloth', say: function() { return `Hi, my name is ${[Link]}, I am a ${[Link]} elf.` } attack:
function() { return `attack with ${[Link]}` }}const elf2 = { name: 'Legolas', type: 'high',
weapon: 'bow', say: function() { return `Hi, my name is ${[Link]}, I am a ${[Link]} elf.` }
attack: function() { return `attack with ${[Link]}` }}[Link]()// attack with cloth
[Link]()// attack with bow Factory FuncAons As you can see, this code is already gerng
very repeBBve and is not maintainable with only 1 character type. Imagine adding more
characters, things would get out of control quickly. So, another way to create objects was
introduced, factory funcAons. Factory funcBons return a new object every Bme they are ran.
This could improve the code somewhat. Go Back to Table of Contents Page of 64 93 function
createElf(name, type, weapon) { return { name: name, type: type, weapon: weapon, say()
{ return `Hi, my name is ${name}, I am a ${type} elf.`; }, attack() { return `${name} attacks
with ${weapon}`; } };}const dobby = createElf("Dobby", "house", "cloth");const legolas =
createElf("Legolas", "high", "bow");[Link](); // Hi, my name is Dobby, I am a house elf.
[Link](); // Hi, my name is Legolas, I am a high elf. [Link](); // Dobby attacks with
cloth. [Link](); // Legolas attacks with bow. Stores This is a step in the right direcBon,
but if we added more characters, we would run into some of the same issues again. Not only
is the code not DRY, the a_ack method is being created and taking up memory space for
every new elf. This is not very efficient. How do we solve this? Well, we could separate the
methods out into a store. Go Back to Table of Contents Page of 65 93 const elfMethodsStore
= { attack() { return `attack with ${[Link]}`; }, say() { return `Hi, my name is $
{[Link]}, I am a ${[Link]} elf.`; }};function createElf(name, type, weapon) { return
{ name: name, // old way type, // with ES6 assignment, if they are the same name
weapon };}// each method has to be assigned to the store method to // create the
__proto__ chain const dobby = createElf("Dobby", "house", "cloth");[Link] =
[Link];[Link] = [Link];const legolas = createElf("Legolas",
"high", "bow");[Link] = [Link];[Link] = [Link];
[Link] Having a store saved us some efficiency in memory, but this was a lot of
manual work to assign each method. So, we were given [Link] to help create this
chain without having to assign each method. Constructor FuncAons Using [Link] is
true prototypal inheritance, the code is cleaner and easier to read. However, you will not see
this being used in most programs. Before [Link] came around, we had the ability to
use constructor funcBons. Constructor funcBons are exactly like the funcBon constructor we
talked about above. The number and string funcBons were constructed and invoked with the
new keyword and they were capitalized. The new keyword actually changes the meaning of
this for the constructor Go Back to Table of Contents Page of 66 93 const elfMethodsStore =
{ attack() { return `attack with ${[Link]}`; }, say() { return `Hi, my name is ${[Link]},
I am a ${[Link]} elf.`; }};function createElf(name, type, weapon) { // this creates the
__proto__ chain to the store let newElf = [Link](elfMethodsStore);
[Link](newElf.__proto__); // { attack: [Function], say: [Function] } // this assigns all the
methods [Link] = name; [Link] = type; [Link] = weapon; // this returns
the new Elf with everything attached return newElf;}const dobby = createElf("Dobby",
"house", "cloth");const legolas = createElf("Legolas", "high", "bow");[Link]; // attack
with cloth [Link]; // attack with bow funcBon. Without new, this will point to the
window object instead of the object that we just created. It is best pracBce to capitalize
constructor funcBons to help us idenBfy them and know to use the new keyword. ProperBes
added to a constructor funcBon can only be done using the this keyword, regular variables
do not get added to the object. Go Back to Table of Contents Page of 67 93 // constructor
functions are typically capitalized function Elf(name, type, weapon) { // not returning
anything // "constructing" a new elf [Link] = name; [Link] = type; [Link] =
weapon;}// to use a constructor function // the "new" keyword must be used const dobby =
new Elf("Dobby", "house", "cloth");const legolas = new Elf("Legolas", "high", "bow");// To
add methods we need to add [Link] = function() { // cannot be an arrow
function // this would be scoped to the window obj return `attack with ${[Link]}`;};//
This would need to be repeated for each method. [Link](); // attack with cloth
[Link](); // attack with bow Ni#y Snippet: A constructor funcQon in JavaScript is
actually just a constructor itself. Class Confused yet? Prototype is a li_le weird and hard to
read unless you really understand your prototypal inheritance. No one really liked using the
prototype way of adding methods, so in ES6 JavaScript gave us the class keyword. However,
classes in JavaScript are not true classes, they are syntacBc sugar. Under the hood, it is sBll
using the old prototype method. They are in fact just "special funcBons" with one big
difference, funcBons are hoisted and classes are not. You need to declare your class before it
can be used in your codebase. Classes also comes with a new method, the constructor that
creates and instanBates an object created with class. Classes are able to be extended upon
using the extends keyword, allowing subclasses to be created. If there is a constructor
present in the extended class, the super keyword is needed to link the constructor to the
base class. You can check if something is inherited from a class by using the keyword
instanceof to compare the new object to the class. Go Back to Table of Contents Page of 68
93 // What happens under the hood... const Elf = new Function( 'name', 'type', 'weapon', //
the \ n just creates a new line // it can be ignored here '[Link] = name \n [Link] = type
\n [Link] = weapon` )const dobby = new Elf('Dobby', 'house', 'cloth')// This will work
the same as our code above. Go Back to Table of Contents Page of 69 93 class Character
{ constructor(name, weapon) { [Link] = name; [Link] = weapon; } attack() { return
`attack with ${[Link]}`; }}class Elf extends Character { constructor(name, weapon,
type) { super(name, weapon); // pulls in name and weapon from Character [Link] =
type; }}class Ogre extends Character { constructor(name, weapon, color) { super(name,
weapon); [Link] = color; } enrage() { return `double attack power`; }}const legolas = new
Elf("Legolas", "high", "bow");const gruul = new Ogre("Gruul", "club", "gray");[Link]();
// attack with bow [Link](); // double attack power [Link](); // attack with club
legolas instanceof Elf; //true gruul instanceof Ogre; //true Private and public fields Most
class based languages have the ability to create either public or private fields within a class.
Adding these to classes in JavaScript is sBll an experimental feature in development. Support
in browsers is limited, but can be implemented with systems like Babel. Public declaraAons
are set above the constructor and can be used within the class, but do not get added to a
new instance. The private declaraAons are set with the # sign in front of the variable and are
only accessible within that class, they cannot be accessed or changed from outside. So, did
we obtain perfect object oriented programming? Well, that is up for debate. It is really up to
you the developer to decide which style of wriBng you like best. We did learn that object
oriented programming helps make you code more understandable, easy to extend, easy to
maintain, memory efficient, and DRY! Go Back to Table of Contents Page of 70 93 // public
declarations class Rectangle { height = 0; width; constructor(height, width) { [Link] =
height; [Link] = width; }}// private declarations class Rectangle { #height = 0; #width;
constructor(height, width) { this.#height = height; this.#width = width; }} Ni#y Snippet: Why
didn't Eich just add classes to JavaScript in the beginning? "If I had done classes in JavaScript
back in May 1995, I would have been told that it was too much like Java or the JavaScript
was compeQng with Java ... I was under markeQng orders to make it look like Java but not
make it too big for its britches ... [it] needed to be a silly liBle brother language." —Brendan
Eich 4 PILLARS OF OOP • EncapsulaBon - Organizes code into containers that relate to each
other and makes it easier to maintain and reuse. • AbstracBon - Hides the complexity from
the user by doing the method calculaBons behind the scenes. • Inheritance - Gives the
properBes of a class to another class, keeping code DRY and saving on memory space. •
Polymorphism - The ability of an object to take on many forms allowing methods to be used
differently by different classes. Go Back to Table of Contents Page of 71 93 FUNCTIONAL
PROGRAMMING FuncBonal programming has the same goals in mind as object oriented
programming, to keep your code understandable, easy to extend, easy to maintain, memory
efficient, and DRY. Instead of objects, it uses reusable funcBons to create and act on data.
FuncBonal program is based on a separaBon of concerns similar to object oriented
programming. However, in funcBonal programming there is a complete separaBon between
the data and the behaviors of a program. There is also an idea that once something is
created, it should not be changed, being immutable. Unlike OOP, shared state is avoided
funcBonal programming works on the idea of pure funcAons. Pure FuncAons A pure
funcAon has no side effects to anything outside of it and given the same input will always
output the same value. They do not change any data passed into them, but create new data
to return without altering the original. However, it is not possible to have 100% pure
funcBons. At some point you need to interact with the dom or fetch an api. Even [Link]
makes a funcBon unpure because it uses the window object outside of the funcBon. Fact is a
program cannot exist without side effects. So, the goal of funcBonal programming is to
minimize side effects by isolaBng them away from the data. Build lots of very small, reusable
and predictable pure funcBons that do the following: • Complete 1 task per funcBon. • Do
not mutate state. • Do not share state. • Be predictable. • Be composable, one input and
one output. • Be pure if possible. • Return something. ReferenAal transparency One
important concept of funcBonal programming is referenAal transparency, the ability to
replace an expression with the resulBng value without changing the result of the program.
Go Back to Table of Contents Page of 72 93 Idempotence Idempotence is another important
piece of funcBonal programming. It is the idea that given the same input to a funcBon, you
will always return the same output. The funcBon could be used over and over again and
nothing changes. This is how you make your code predictable. ImperaAve vs DeclaraAve
ImperaBve programming tells the computer what to do and how to complete it. DeclaraBve
programming only tells the computer what to do, but not how to do things. Humans are
declaraBve by nature, but computers typically need more imperaBve type programming.
However, using higher level languages like JavaScript is actually being less declaraBve. This is
important in funcBon programming because we want to be more declaraBve to be_er
understand our code and let the computer handle the dirty work of figuring out the best
way to do something. Go Back to Table of Contents Page of 73 93 function a(num1, num2)
{ return num1 + num2;}function b(num) { return num * 2;}b(a(3, 4)); // 14 // a should always
return 7 // so it could be changed to b(7); // 14 // and the output is the same Go Back to
Table of Contents Page of 74 93 // more imperative for (let i = 0; i < 10; i++)
{ [Link](i);}// more declarative let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];[Link](item =>
[Link](item)); Immutability Immutability is simply not modifying the original data or
state. Instead we should create copies of the state inside our funcBons and return a new
version of the state. You may be thinking that this could get really expensive, memory wise,
to just copy code over and over. However, there is something called structural sharing that
allows the data to only copy new informaBon and points to the original state for any
commonaliBes. Go Back to Table of Contents Page of 75 93 // Bad code const obj = {name:
'Brittney'}function clone(obj) { return {...obj} // this is pure }[Link] = 'Joe' //mutated the
state // Better code function updateName(obj) { const newObj = clone(obj) [Link] =
'Joe' return newObj}const updatedNameObj = updateName(obj)[Link](`obj = ${obj}`,
`updatedNameObj = ${updatedNameObj}) ParAal ApplicaAon ParBal applicaBon is
expanding on the idea of currying and taking it a step farther by separaBng a parameter out.
If you have more than 2 arguments in a funcBons, then you can bind one of them to a value
to be used later. Pipe and Compose In JavaScript it is best for speed and efficiency to keep
funcBons small and reusable. FuncBon composiBon is the idea that you lay out your
funcBons like a factory assembly line. The actual funcBons pipe() and compose() don't
actually exist in JavaScript yet, but there are many libraries that use them. You can however
create your own versions of them. The compose() funcBon reads the funcBons from right to
lep and the pipe() funcBon will read from lep to right. Go Back to Table of Contents Page of
76 93 const multiply = (a, b, c) => a * b * c;const curriedMultiplyBy5 = [Link](null,
5); // this is null curriedMultiplyBy5(4, 10); // 200 // create our own COMPOSE function
const compose = (fn1, fn2) => data => fn1(fn2(data));// create our own PIPE function const
pipe = (fn1, fn2) => data => fn2(fn1(data));const multiplyBy3 = num => num * 3;const
makePositive = num => [Link](num);// use compose to combine multiple functions const
composeFn = compose(multiplyBy3, makePositive);const pipeFn = pipe(multiplyBy3,
makePositive);composeFn(-50); // 150 pipeFn(-50); // 150 // essentially we are doing this //
fn1(fn2(fn3(50))) // compose(fn1, fn2, fn3)(50) // pipe(fn3, fn2, fn1)(50) Ni#y Snippet: The
Pipeline Operator is in the experimental stage 1 of being introduced to JavaScript. Stage 1
means that it has only started the process and could be years before it is a part of the
language. The pipeline operator, |>, would be syntacQc sugar for composing and piping
funcQons the long way. This would improve readability when chaining mulQple funcQons.
Arity Arity simply means the number of arguments a funcBon takes. The more parameters a
funcBon has the harder it becomes to break apart and reuse. Try to sBck to only 1 or 2
parameters when wriBng funcBons. Reviewing FuncAonal Programming So, is funcBonal
programming the answer to everything? No, but it is great in situaBons where you have to
perform different operaBons on the same set of data. FuncBonal programming just lays the
foundaBon for creaBng reusable funcBons that can be moved around as needed. For
example, it is great in areas of industry and machine learning and it is even in some front
end libraries like React and Redux. Redux really popularized funcBonal programming for
JavaScript developers. I'll leave you with one more example, a basic shopping cart (next
page). Go Back to Table of Contents Page of 77 93 const double = n => n * 2;const increment
= n => n + 1;// without pipeline operator double(increment(double(double(5)))); // 42 //
with pipeline operator 5 |> double |> double |> increment |> double; // 42 Go Back to Table
of Contents Page of 78 93 const user = { name: "Kim", active: true, cart: [], purchases:
[]};const userHistory = [];function addToCart(user, item) { [Link]( [Link]({},
user, { cart: [Link], purchases: [Link] }) ); const updateCart =
[Link](item); return [Link]({}, user, { cart: updateCart });}function
taxItems(user) { [Link]( [Link]({}, user, { cart: [Link], purchases:
[Link] }) ); const { cart } = user; const taxRate = 1.4; const updatedCart =
[Link](item => { return { name: [Link], price: [Link] * taxRate }; }); return
[Link]({}, user, { cart: updatedCart });}function buyItems(user)
{ [Link]( [Link]({}, user, { cart: [Link], purchases: [Link] }) );
return [Link]({}, user, { purchases: [Link] });}function emptyCart(user)
{ [Link]( [Link]({}, user, { cart: [Link], purchases: [Link] }) );
return [Link]({}, user, { cart: [] });}function refundItem(user, item)
{ [Link]( [Link]({}, user, { cart: [Link], purchases: [Link] }) );
const { purchases } = user; const refundItem = [Link](item); return
[Link]({}, user, { purchases: refundItem });}const compose = (fn1, fn2) => (...args) =>
fn1(fn2(...args));const purchaseItems = (...fns) =>
[Link](compose);purchaseItems( emptyCart, buyItems, taxItems, addToCart)(user,
{ name: "laptop", price: 200 });refundItem(user, { name: "laptop", price:
200 });[Link](userHistory); COMPOSITION VS INHERITANCE ComposiBon is what we
just did with FP, creaBng small reusable funcBons to make code modular. Inheritance is what
we did with OOP, creaBng a class and extending it to subclasses that inherit the properBes.
In OOP we create few operaBons on common data that is stateful with side effects. In FP we
create many operaBons on fixed data with pure funcBons that don't mutate state. There is a
big debate over which one is be_er and most people believe that composiBon is be_er. OOP
Problems One of the drawbacks to inheritance is that it is based on the fact that it won't
change, we tell it what it is. We create a class and give it properBes and methods that
describe the class. But say, down the road, we need to update that class and add more
funcBonality. Adding a new method to the base class will create rippling effects through your
enBre program. FP is more declaraBve, what to do not how, and OOP is more imperaBve,
what and how to do something. This is the Aght coupling problem, things having to depend
on one another, which leads to the fragile base class problem, seemingly safe changes cause
unforeseen repercussions. It is the opposite of small reusable code. Changing one small
thing in either of the class or subclasses could break the program. Another problem is
hierarchy where you may need to create a subclass that can only do 1 part of the class, but
instead you get everything passed down to it. Finally ComposiBon is probably a be_er tool to
use when creaBng programs because it creates a more stable environment that is easier to
change in the future. The key is to decide which structure is be_er for your project. You can
use ideas from both of these styles to write your code. React uses OOP in class components
to extend inheritance and then uses FP in the pure components. Go Back to Table of
Contents Page of 79 93 MODULES IN JAVASCRIPT Modules are pieces of code, grouped
together, that can be combined together to create an expandable program that can get
bigger as it needs to. Good modules are self contained and grouped together with their own
specific funcBonality allowing them to be moved or deleted without breaking the program.
Module PaUerns Originally in JavaScript, we had the module paUern. Before block scope
came around, there was only global scope and funcBon scope. To create this idea of
modules, a module scope was implemented just above the funcBon scope. This allowed
variables to be shared, by exporBng and imporBng, between the funcBons without having to
go through the global scope. A funcBon as a module is essenBally just an immediately
invoked funcBon expression, IIFE. Go Back to Table of Contents Page of 80 93 var
globalScopeVar = "I can be accessed anywhere";var moduleName =
(function(globalScopeVar) { // add private variables here var privateVar = "I cannot be
accessed outside"; // create the function function say(msg1, msg2) { var say1 =
[Link]([Link]() * [Link]); var say2 = [Link]([Link]() *
[Link]); return say1 > say2 ? say1 : say2; } globalScopeVar = `I don't change the outside
scope`; // return only what you want the outside to access return { say: say };})
(globalScopeVar); Issues with Modules Even though modules help us to contain and
organize code, there are sBll problems that can arise. There can be naming conflicts if you
don't use const to declare the module. Also, there are dependency issues if scripts are
placed in the wrong order, such as jQuery needing to be called before it can be used.
Because of these problems, people started developing libraries to solve them. Before ES6 we
had 2 ways to implement modules in JavaScript CommonJS and AMD. • CommonJS - uses
the keywords require and exports to interact with the module system. Require is a funcBon
used to import from another module and exports is an object where funcBons get exported
from. These are run synchronously where we wait on one module to load before another
can start and this is not ideal for browsers. However, this code may look familiar because
NodeJS sBll uses this library. There are other packages such as Browserify and webpack that
aid in bundling scripts with CommonJS to be used in the browsers. • Asynchronous Module
DefiniAon (AMD) - as in the name, AMD loads modules asynchronously. This was great for
browsers early on before packages that bundled code. define(['module1', 'module2'],
funcBon(module1, module2) {[Link]([Link]());}); The define funcBon takes
an array of dependency modules that are loaded in a non-blocking manner in the
background. Once completed, the callback funcBon is then executed. Packages came out like
RequireJS that implemented the AMD endpoint and was the main way people used AMD
modules. ES6 Modules Aper ES6 came out, pre_y much everything above was thrown out
the window with 2 new keywords. We can now use the import and export keywords in our
files to implement modules. This again may look familiar from popular frameworks like
React. Go Back to Table of Contents Page of 81 93 import module1 from "module1";import
module2 from "module2";export function name() {} Here is our module code from above in
the new ES6 syntax. There are 2 types of exports, named and default. A named export is
imported using curly braces ({ importFnName }) and a default funcBon is added in created
like this: Trying to run this in the browser there is sBll 2 more things that have to be done.
You have to declare the type in the html script tag as module and the file has to be served
from a server. You can spin up your own server with a package like live-server on npm. Go
Back to Table of Contents Page of 82 93 const privateVar = "I cannot be accessed outside this
file";export function name(msg1, msg2) { const say1 = [Link]([Link]() *
[Link]); const say2 = [Link]([Link]() * [Link]); return say1 > say2 ?
say1 : say2;}import { importFnName } from "./[Link]";// with a default function the {} are
not needed import name from "./[Link]";// both default and named function import
import name, { importFnName } from "./[Link]";export default function name(msg1, msg2)
{ const say1 = [Link]([Link]() * [Link]); const say2 =
[Link]([Link]() * [Link]); return say1 > say2 ? say1 : say2;}<script
type="module" src="'./[Link]'></script> ERROR HANDLING One of the most important
things to learn in being a developer is how to solve errors. Learning to handle errors makes
you a be_er programmer. WriBng your programs you have the ability to use the throw
keyword to stop the program and handle an error by using a try/catch block that has an
opBonal finally block or the .catch() method for asynchronous code. Throwing a new error in
asynchronous code gets what is called a silent fail if there is no catch block present. In
synchronous code, if there is no catch statement placed in the code, the runBme will create
catch: onerror() and we see the built in JavaScript error message in red (see next page). Go
Back to Table of Contents Page of 83 93 Go Back to Table of Contents Page of 84 93 throw
new Error();// synchronous try/catch/finally block function fail() { try { [Link]("this
works"); throw new Error("oopsie!!!"); } catch (error) { [Link]("we have made an
oopsie", error); } finally { [Link]("still good"); }}fail();// this works // because it goes line
by line // we have made an oopsie Error: oopsie at fail // still good // asynchronous .catch()
[Link]("asyncfail") .then(response => { [Link](response); return
response; }) .catch(error => { [Link](err); });(async function() { try { await
[Link]("oopsie #1"); await [Link]("oopsie #2"); } catch (err)
{ [Link](err); } [Link]("is this still good?");})();// Promise {} // Promise resolved //
ooopsie #2 // is this still good? Besides the generic Error constructor, there are seven other
built in error constructors. • EvalError - an error with the global funcBon eval(). •
InternalError - an error in the JavaScript engine is thrown. Usually when something is too
large. • RangeError - an error when a numeric variable or parameter is outside of its valid
range. • ReferenceError - an error that occurs when referencing something invalid. E.g.
When a variable is used before it is declared. • SyntaxError - an error that occurs in parsing,
the engine does not understand what is wri_en. • TypeError - an error when a variable is not
the correct type. • URIError - an error when encodeURI() or decodeURI() are passed invalid
parameters. Errors created using the new keyword come with 3 properBes. • name - the
name of the error. • message - the parameter given to the error. • stack - the stack trace or
callback queue when the error occurred that also includes the line and character number
where the error happened. Go Back to Table of Contents Page of 85 93 const myError = new
Error("oopsie");[Link]; // "Error" [Link]; // "oopsie" [Link]; //
"Error: oopsie at <anonymous>:1:17 function a() { const b = new Error("uh oh"); return
b;}b(); // b().stack // Error: uh oh // at a (<anonymous>:2:12) // at <anonymous>:1:1
Because Error is a constructor funcBon, we can use that to extend it and add to it. You don't
want to reveal parts of your program by allowing an error to give the stack trace and other
informaBon to possible bad actors. So, you can customize what you want your errors to
reveal. THE END… This is the "official" end of the Advanced JavaScript secBon, but Bri_ney
added a small secBon of her notes on data structures and algorithms because they are an
important part of developing great programs. DATA STRUCTURES & ALGORITHMS Data
structures and algorithms are the fundamentals of every program. Data structures are
collecBons of values and algorithms are the steps we put in place to manipulate the data
structures. No ma_er what language you write in if you understand these 2 things, you have
the ability to write great programs. Go Back to Table of Contents Page of 86 93 class
AuthenticationError extends Error { constructor(message) { super(message); [Link] =
"AuthenticationError"; [Link] = "authentication problem"; [Link] = "please log
in"; }}const err = new AuthenticationError("oopsie");err; // authenticationError:
"authentication problem" stack trace [Link]; // please log in Data Structures A data structure
is different types of containers that hold your data. Each container has its own type of data it
holds and its specific to that type. You want to be able to easily access your data and know
where it is located. It is basically a way to organize your data. There are 2 parts to data
structures, how to build one and how to use it. How do computers work? A computer has
many parts but 3 that run almost all of our everyday operaBons, the CPU, RAM, and a hard
drive (storage). The CPU processes all the data and only has so much power, the RAM is
memory that is temporarily delegated to programs, and a hard drive is persistent memory
that stays where we put it. Persistent storage is quiet slow, so we need RAM to use as a
temporary holder for memory. RAM is like a storage shelf of memory addresses that each
contain 8 bits or 1 byte. Each bit is either a 0 or a 1 to indicate whether it is on or off, 1 for
on and 0 for off. Popular Data Structures There are many implementaBons of data
structures out there but there are only 2 fundamental kinds, array of conBguous memory
locaBons and linked structures, or you can combine the two. The most important ones you
will run into are arrays, stacks, queues, linked lists, trees, tries, graphs, and hash tables. With
algorithms there are sorBng, dynamic programming, BFS + DFS (Searching), and recursion.
Each data structure has things they are good at and may be be_er in certain situaBons than
others. Below is Go Back to Table of Contents Page of 87 93 a list of data structures that are
built into several popular languages. That doesn't mean that you can't use other types, you
just have to build our own. Such as if JavaScript doesn't have stacks, we can build one.
Arrays Arrays order items sequenBally with an index. Arrays are probably the simplest and
the most widely used data structure because the are fast and take up the least amount of
space. They also have the least amount of rules. Array methods have different Bme
complexiBes, called Big-Order or Big-O notaBons. _O(1) is constant Bme, meaning the Bme
does not change with the data input. The _O(n) is linear Bme, meaning Bme changes or goes
up the more operaBons that need to be performed. _O(1) can end up as _O(n) in languages
like JavaScript if it needs to allocate more memory for the array. There is also, Big-Omega or
Big-Ω notaBon that give the best possible Bme for your Go Back to Table of Contents Page of
88 93 program. If a program has the same Bme complexity in Big-O and in Big-Ω, then you
can use θ as shorthand for both combined. ImplemenAng an Array Arrays can be declared
easily in JavaScript, but what if we built our own… Go Back to Table of Contents Page of 89
93 const strings = ["a", "b", "c", "d"];// 4 * 4 = 16 bytes of storage strings[2]; // c // O(1)
[Link]("e"); // O(1) // ['a', 'b', 'c', 'd', 'e'] [Link](); // O(1) // ['a', 'b', 'c', 'd']
[Link]("z"); // O(n) // ['z', 'a', 'b', 'c', 'd'] // unshift took 5 operations to complete. //
['a', 'b', 'c', 'd'] // [ 0 1 2 3 ] all indexes need to shift // ['z', 'a', 'b', 'c', 'd'] // [ 0 1 2 3 ] // [ 0 1 2
3 4 ] Go Back to Table of Contents Page of 90 93 class MyArray { constructor() { [Link] =
0; [Link] = {}; } get(index) { return [Link][index]; } push(item) { [Link][[Link]] =
item; [Link]++; return [Link]; } pop() { const lastItem = [Link][[Link] - 1];
delete [Link][[Link] - 1]; [Link]--; return lastItem; } delete(index) { const item =
[Link][index]; [Link](index); return item; } shiftItems(index) { for (let i = index; i <
[Link]; i++) { [Link][i] = [Link][i + 1]; } delete [Link][[Link] - 1]; [Link]--;
}}const newArray = new MyArray();[Link]("hi"); Hash Tables Different languages
have different names for a hash table, but in JavaScript a hash table is an object. A data
structure that stores data in key/value pairs. Hash FuncAon A hash funcBon takes a key and
maps it to a value of fixed length for every input. It is an idempotent funcBon meaning given
the same input the output will always be the same. A hash table uses the hash funcBon to
compute the key into a hash code and map that to an address in memory where it is stored
with the value in a bucket. Using the hashing technique makes looking up data inside the
hash table very fast and is usually O(1) Bme. Hash Collisions Every data structure is going to
come with downsides. Hash collisions are what happens when a hash funcBon maps a key to
the same address as a previously added key. With enough data and limited memory, we will
always run into this collision. This does not overwrite the previous informaBon, but creates a
linked list and slows down our ability to access the informaBon. Your big O notaBon Bme
jumps from O(1) to O(n/k) where n is the Bme and k is the size of the hash table. Go Back to
Table of Contents Page of 91 93 let character = { age: 20, name: "Harry Potter", muggle:
false, patronus: function() { [Link]("Expecto Patronum!"); }};[Link]; // 20 // O(1)
[Link] = "Wingardium Leviosa!"; // O(1) [Link](); // Expecto
Patronum! // O(1) Hashing in JavaScript JavaScript came out with 2 ways to help prevent
hash collisions when implemenBng hash tables, the Map object and the Set. Map will store
key/value pairs like an object, but will remember the original order in memory. A Map also
allows for any data type to be stored as a key such as an array or funcBon. A Set will only
store the values and also remembers the original order, but the values may only occur once.
Create a Hash Table (conBnued on next page) Go Back to Table of Contents Page of 92 93 Go
Back to Table of Contents Page of 93 93 class HashTable { constructor(size) { [Link] = new
Array(size); // [Link] = []; } _hash(key) { let hash = 0; for (let i = 0; i < [Link]; i++) { hash
= (hash + [Link](i) * i) % [Link]; } return hash; } set(key, value) { let
address = this._hash(key); if (![Link][address]) { [Link][address] = []; }
[Link][address].push([key, value]); return [Link]; } get(key) { const address =
this._hash(key); const currentBucket = [Link][address]; if (currentBucket) { for (let i = 0; i <
[Link]; i++) { if (currentBucket[i][0] === key) { return currentBucket[i][1]; } } }
return undefined; } keys() { const keysArray = []; for (let i = 0; i < [Link]; i++) { if
([Link][i]) { [Link]([Link][i][0][0]); } } return keysArray; }}const myHashTable =
new HashTable(50);[Link]("grapes",
10000);[Link]("grapes");[Link]("apples",
9);[Link]("apples");[Link]();