JavaScript: high-level, prototype-based, object-oriented, multi-paradigm, interpreted or just-in-time compiled,
dynamic, single-threaded, garbage-collected programming language with first-class functions and a non-blocking event loop concurrency model.
- high-level
every program that runs on computer needs hardware resources: memory and the CPU to do work.
low-level languages: like C, manually manage these resources (asking computer for memory to create a new variable)
high-level languages: JavaScript and Python, have abstractions where we don't have to manage resources. Makes it easier to learn and use but not fast and optimised as low-level.
- garbage collection
(continuing from high-level)
An algorithm inside the JS engine,which automatically removes old, unused objects from the computer memory to avoid clog.
- interpreted/ just-in-time compiled language
every single program needs to be written in 0 and 1, which is called machine code.
since its not practical to write, we write human-readable JS code which is an abstraction over machine code and this needs to be translated back. That step is called compiling or interpreting.
- multi-paradigm language
paradigm is an approach and an overall mindset of structuring our code
paradigms can be classified as imperative or as declarative
- procedural
organizing code in linear way
-object-oriented
-functional programming
Many languages only use one of the above but JS does all of it.
- object-oriented
almost everything in JavaScript is an object, except for primitive values such as numbers, strings, etc.
How can we create an array and then use the push method on it? => prototypal inheritance
create arrays from an array blueprint, which is like a template and this is called the prototype.
prototype contains all the array methods and the arrays that we create in our code then inherit the methods from the blueprint.
- first-class functions
functions that are treated just as regular variables so we can pass functions into other functions and we can even return functions from functions => allows for functional-programming
- dynamic language
In JS, we don't assign data types to variables, they only become known when the JS engine executes our code.
other programming languages, we have to manually assign types like Typescript.
- single-thread event loop
concurrency model: how the JavaScript engine handles multiple tasks happening at the same time.
JavaScript runs in one single-thread: that it can only do one thing at a time.
But what if there is a long-running task,like fetching data from a remote server? => will block the single thread
hence we use an event loop
event loop takes long-running tasks,executes them in the background and then puts them back in the main thread
once they are finished.
JS Engine
> a computer program that executes JavaScript code
Now every browser has its own JavaScript engine : most well known engine is Google's V-Eight = powers Chrome along with Node.js
JavaScript engine always contains a call stack and a heap
call stack: where our code is actually executed using something called execution contexts
heap: is an unstructured memory pool which stores all the objects that our application needs.
How is the code is compiled to machine code so that it actually can be executed afterwards?
The computer's processor only understands 0 and 1 and every single computer program needs to be converted into this machine code.
compilation VS interpretation
- compilation: the entire source code is converted into machine code at once => written in a portable file that can be executed on any computer.
machine code is built and executed in the CPU so in the processor (execution can happen anytime, so it can be compiled in advance before executing.)
- interpretation: an interpreter which runs through the source code and executes it line by line
code is read and executed all at the same time, conversion happens right before it's executed
JavaScript used to be a purely interpreted language but the problem with interpreted languages is that they are much, much slower than compiled languages.
modern JavaScript and web applications that we use today, low performance is no longer acceptable.
JS engine now use a mix between compilation and interpretation => just-in-time compilation
JIT > execution happens immediately after a compilation
How JS works
1.) Parsing : reading the code
> the code is parsed into a data structure called Abstract Syntax Tree
each line of code is split up into pieces that are meaningful to the language.like (const or function) then saved in a tree-like structure.
This step also checks for syntax errors!!

AST has nothing to do with the DOM tree!!
2.) Compilation
takes the generated AST and compiles it into machine code and executed right away
modern JavaScript engines optimization strategies
1.) create a very unoptimized version of machine code in the beginning to start execution as fast as possible.
2.) in the background, this code is being optimized and recompiled during the already running program execution
this happens as a cycle where unoptimized code is simply swept for the new more optimized code until the optimisation is complete and the execution never pauses => this makes modern engines so fast!!
this happens seperately from the main thread where the call stack executes code.
JS runtimes
in the browser:
JS runtime is a big box which includes everything needed to use JS
In order to use JS, runtime is always needed as the JS engine.
We also need web APIs (everything related to DOM: console.log, timers => functionalities provided to the engine but note related to JS itself). JS gets access through the global window object.
JS runtime also includes a callback queue: data structure that contains all the callback functions that are ready to be executed. This is called the event loop.
Event Loop example: an event handler (also called callback functions) 'click' happens > callback function called > put into callback queue > when callstack is empty > function is passed to stack and executed.
JS can exist outside of browsers => Node.js
similar to browser but no APIs instead there are multiple C++ bindings called thread pool.
How is JS code executed?
compiling finished > global execution context is created for top level code: code that is not inside any function like const, and executed > functions are executed only when called
Execution Context: an environment in which a piece of JavaScript is executed => box that stores all the necessary information for code to be executed (variables and arguments)

No matter how large a JS project, there is only ever one global execution context
For each and every function call, a new execution context will be created =>
containing all the information that is necessary to run that function.
Same goes for methods as they are functions attached to objects
Execution Context

inside an execution context:
- variable enviornment
- let const and var declarations
- functions
- arguments object: all the arguments that passed into the function that the current execution context belongs
- scope chain
- this key word (not in arrow functions)
all the above is generated in a creation phase => happens before execution
The Call Stack
call stack: a place where ECs get stacked on top of each other, in order to keep track of where we are in the programs execution

1.) Global EC gets handed first (const name)
2.) function first() is put into the call stack and runs until it encounter second(7,9)
3.) function second() enters the call stack and returns c
4.) first continues running until second(7,9) is solved, then second() function is completed from the call stack
5.) first() returns a then completes its cycle from the call stack
Scope and the Scope chain
Scoping: how our program's variables are organized and accessed. => where do variables live and where can we access a certain variable and where not?
Lexical scoping: Scoping is controlled by placement of functions and blocks in code
Scope: Space or enviornment in which a certain variable is declared (variable enviornment in case of function)
Scope of a variable: Region of code where a certain variable can be accessed
3 types of scope
- Global scope
- Outside of any function or block
- variables declared in global scope is accessible anywhere
- also called global variable
- Function scope
- Variables are accessible only inside function, not outside
- Also called local scope
- block scope ( inside {} like if block or for loop block etc)
-Variables only accessible inside block,
-However this only applies to let and const variables. var end up in the closest function scope
-Functions are also block scoped (only in strict mode)
The scope chain
Scopes has access to variables from all outer scopes!! => called variable loopup
HOWEVER!!! this doesn't work in reverse

scope chain only works upwards not sideways!!
Scope chain vs call stack

there will be a reference error in function third() as the scope chain is unable to access c and b because the values are in a function and it cannot be accessed as its not in the scope chain.
Scoping in practice
- JS retrieves the cloest information within the scope chain!!
ex: in the code below there are two requests of firstName, in line 8 and in line 14.
As seen in console log, in line 8 the firstName is declared as a global variable, same as function printAge, therefore they use Jonas.
However in line 14, firstName is declared as Steven so it retrieves the value Steven instead of going up the scope chain for Jonas.

Hoisting and the TDZ
Hoisting: Makes some types of variables accessible in code before they are declared
.=> before execution, code is scanned for variable declarations, and for each variable a new property is created in the variable enviornment object.

function expressions (anon functions, ex: function doStuff() {}; const doStuff = () => {};) can't be hoisted before declaration, only function declarations (function with name: function doStuff() {};) can be called.
TDZ (Temporal Dead Zone) ES6

since const values cannot be reassigned it only makes sense that it only gets acknowledged when the engine gets to the line. If it was assigned as 'undefined' due to TDZ then reassigned to 'teacher', it wouldnt make sense.
This Keyword
this keyword/variable: Special variable that is created for every execution context (every function). Takes the value of (points to) the "owner" of the function in which the this keyword is used.
this is NOT static. it depends on how the function is called, and its value is only assigned when the function is actually called.
Different ways to use this
- Method : object that is calling the method
methods are actions that can be performed on objects and is a property containing a function.

- Simple function call : in strict mode, otherwise: window
- Event listener: DOM element that the handler is attached to
this does NOT point to the function itself, and also NOT the variable enviornment
Regular functions VS Arrow functions
When using the 'this' keyword, only regular functions can retrieve this from the owner of the function and it cannot transcent scoping!!
ex:
in this case 'this' points to roxy.
However when using arrow functions, this will always point to window.
But we can use this to our advantage.
when using this in a function scope in a regular function, the inner scope won't be able to access 'this' and therefore need 'this' to be assigned to a seperate variable in order for it to be accessed before ES6.
However there is an upgraded version to use 'this' using the arrow function
in this arrow function. 'this' will point to roxy because arrow functions inherit the this keyword from the parent.
Arguments
despite it not being used as often it is still useful to know!!
we can use arguments to see and use multiple arguments in a function! this can only be done with normal functions not arrows!!
- NORMAL FUNTION:

- ARROW FUNCTION:

Primitive types VS Objects (primitives vs reference types)
Primitives (primitive types): stored in Callstack (in execution context to be exact)
- Number
- String
- Boolean
- Undefined
- Null
- Symbol
- BigInt
Objects (reference types): stored in Heap
- Object literal
- Arrays
- Functions
- etc..

How primitive VS reference values work within the JS engine

- Primitive values: when entering the call stack, each value gets assigned an identifier, address and value.
The indentifier point to the ADDRESS not the VALUE!!!
when another variable gets assigned to the same identifier, the end up sharing the same address!
However when the first indentifier then gets a new value assigned, a new address is created to store the new value/
- Reference values: The object gets stored in the heap first (due to storage size) then the identifier is creaqted with the address of the object stored in heap.
When two or more identifiers share the same object, it also shares the same address. Therefore when one of the values of the indentifier changes. it alters the entire object and does not create a new address therefore they end up sharing the same changed value.
'Javascript' 카테고리의 다른 글
| Data structures, Moden operators and strings (0) | 2024.04.23 |
|---|---|
| DOM and Events Fundamentals (0) | 2024.04.03 |
| JavaScript Fundamental part 2 (0) | 2024.01.29 |
| JavaScript fundamental notes 1 (0) | 2024.01.23 |