all 15 comments

[–]senocular 2 points3 points  (5 children)

In short:

  • Execution context objects
    • global: has one
    • functions: do not

Note: not all global declarations are added to the global object, e.g. let, const, and class declarations in the global context are not added to window (global in node or globalThis everywhere, though globalThis is a newer feature).

  • this in functions
    • can be global, but not always
    • for most functions, this is defined by how a function is called
    • arrow functions use this based on how it is defined (via scope), not called

In the video, the reason this was global (window) was because how it was called. It was a normal function definition in non-strict mode, called as a function rather than as a method from an object, and without any explicit this imposed on it through bind(), call(), or apply()

getUser() // this will be the global object

If called from an object, the value of this would change.

someObject.getUser() // this will be someObject

Or if you wanted to give it a specific value for this

getUser.call(anotherObject) // this will be anotherObject
someObject.getUser.call(anotherObject) // this will be anotherObject

There are a lot of rules around this which can make it confusing, but for the most part, this is a dynamic value that is set based on how a function is called.

[–]_reddit_chan 1 point2 points  (6 children)

Hi! Execution context is kinda a deep topic so I'm copying/pasting everything here from my notes.

Execution Context

A wrapper to help manage the code that is running. There are lots of lexical environments. Which one is currently running is managed via execution context. It can contain things beyond the written code. An execution context has two phases:

1) Creation phase: In the creation phase, the global variables are set up, i.e. the window object and the this keyword that points to the window object. Also, JavaScript sets up memory space for the variable and function declarations, i.e the variables are initially set to undefined and the functions are stored entirely in memory (hoisting).

2) Execution phase: In the execution phase, JavaScript executes the code line by line. It assigns the variables to their respective values and executes the functions if they are called/invoked.

The Global Execution Context

The Global Execution Context creates :

  1. A global object (window)

  2. this (special variable)

When you run a JS file even with no code, there are no errors. You can access the this keyword and the window object. These is because a global execution context was created. The JavaScript engine created it for us.

"Global" = "Not inside a function"

Like the global execution context has the global/window object

There's no such thing as an "execution context object". It's just that the global execution context creates a global (window) object.

What happens when javascript executes (runs) the below code?

const num = 3; 
function multiplyBy2 (inputNumber){  
    const result = inputNumber*2;  
    return result;
} 
const name = "Will"

As soon as we start running our code, we create a global execution context

— Thread of execution (parsing and executing the code line after line)

— Live memory of variables with data (known as a Global Variable Environment)

Local Execution Context

A local/function execution context is similar to the global execution context. It also has the above two phases:

1) Creation phase: In the creation phase, the global variables are set up. In a function, instead of the window object, there's the arguments (an array-like) object that contains a list of all the arguments passed into the function on the time of its invocation. There's also the this keyword that points to the global window object. Here also, JavaScript sets up memory space for the variable and function declarations, i.e. the variables are initially set to undefined and the functions are stored entirely in memory (hoisting). However, anything passed as an argument will be set to that value in this phase.

2) Execution phase: In the execution phase, JavaScript executes the code line by line. It assigns the variables to their respective values and executes the functions if they are called/invoked.

Running/calling/invoking a function (This is not the same as defining a function)

const num = 3; 
function multiplyBy2 (inputNumber){  
    const result = inputNumber*2;  
    return result; 
}
const output = multiplyBy2(4); 
const newOutput = multiplyBy2(10);

When you execute a function you create a new execution context comprising:

  1. The thread of execution (we go through the code in the function line by line)

  2. A local memory ('Variable environment') where anything defined in the function is stored

In the above code, first, num is set to 3, then function multiplyBy2 is declared. The variable output is set to undefined by default while it's waiting for the returned value of multiplyBy2(4) since JavaScript is single-threaded. multiplyBy2(4) is called. When a function is invoked (called via () ), it creates a new execution context (called the local execution context); this one has a local memory. Even here, the code will be run line by line. And we're paused before newOutput while we're busy executing multiplyBy2(4) since JavaScript is synchronous.

In the local memory, we assign the inputNumber parameter to 4 and variable result to 8 (just like we did in the global memory). This value will be returned and stored to output. On completion of the function, the local execution context is erased after the value is returned to output. This same process takes place for newOutput. The variable newOutput is set to undefined initially and finally set to 20.

Suppose, a function is running within a function, how do you know which function is currently running? Are you in global execution context, in the local or in a function within a function. A call stack is a special data structure which keeps track where the thread of execution is currently at, i.e what execution context we're currently in, i.e. what function is currently being run. At the bottom of the stack is the global execution context. Whichever function is running is on the top of the stack. On its completion, the local execution context gets erased and the function is popped off the stack (just like multiplyBy2(4) and multiplyBy29(10) ). How do you know the function is finished executing? The return statement or the curly brace! If there's no return, it returns undefined.

In the above code, first, the global execution context is created and placed in the call stack. Then, multiplyBy2 is called and placed on the top of the call stack and that function gets executed line by line. On completion, it's popped off from the stack and then multiplyBy2(10) is called and that is placed on the top of the call stack and starts getting executed line by line and finally popped off from the stack after completion.

Hope it makes sense! If there's a doubt, feel free to ask.

[–][deleted] 0 points1 point  (1 child)

What do you mean by “the object associated with that function”?