0

I am new to JS and was learning the role of execution context in JS and asked myself what is the benefit of execution context in JS and why JS is run via execution context. The second question is as we know there are global and functional execution contexts and each context has two phases creation phase and execution phase. So, why we need these two phases? what is the point of having them.

  • read [here](https://stackoverflow.com/questions/9384758/what-is-the-execution-context-in-javascript-exactly) – doc-han Jul 20 '19 at 09:52

1 Answers1

2

The concept of an "execution context" provides a way of reasoning about what happens when the global environment is created and executed, or when a function is called. It's a conceptual container for the local variables (globals, in the case of the global environment), parameters (for functions), etc. A JavaScript engine can be written without literally having any object it calls an "execution context," as long as it implements the language in keeping with the spec's defined execution context behavior.

One thing that the execution context helps explain is the behavior of closures. A function created within a given execution context has (conceptually) a reference to that context, even after the function call related to the context has completed:

function foo(answer) {
    return function say() {
        console.log(answer);
    };
}
const s = foo(42);
s(); // 42

That works because the function say has a reference to the context of the call to foo that created it (well, more specifically to the thing called its "lexical environment"). That lexical environment continues to exist after foo returns because something still has a reference to it (say). So the call to say afterward works.

The reason for having two phases is to allow use of identifiers before their declaration. This is primarily useful for function declarations:

main();

function main() {
    console.log("Worked");
}

The first phase processes the function declarations (and var statements), and then the step-by-step phase runs the code. Without the first phase, the code above would fail as of main(); because main would be undeclared. Of course, with the simple example above, you could just move the main(); call to after the function declaration, but more complicated cases become harder to solve in that way. Languages that didn't have two phases (early C, for instance) had to provide a mechanism for "forward declaring" things that would be defined later. Having two phases means JavaScript doesn't have to have those. (To be fair, C also differs from JavaScript in that it needs to know what all identifiers refer to during compilation, even if the identifiers are in code within functions. So it needed forward declarations just to allow foo and bar to call one another. JavaScript doesn't check the identifiers used within functions until the function is called, so some of the reasons for forward declarations in C wouldn't come up in JavaScript even if it didn't have two phases.)

It wasn't perfectly successful. Having var statements initialize the variables they declare with undefined before the var statement is reached in the code was often the source of bugs and confusion:

console.log(answer); // undefined
var answer = 42;

It's easy for people to be confused by the fact that half of the var answer = 42; was done early (the var answer part), but the other half (answer = 42;) isn't done until later when that statement is reached.

That's why let and const create, but don't initialize, their variables during that first phase. You can use a variable above where it's declared, but only in code that runs after the initialization:

function foo() {
    console.log(answer);
}
// foo(); <== Would fail, `answer` isn't initialized yet
let answer = 42;
foo(); // Works, logs 42
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • thank you for your kind answer, one thing that still confuses me is that "having two phases is to allow use of identifiers before their declaration" but why to allow, for example, function to be used before its declaration. The reason is simply Flexibility or...? – user11807902 Jul 20 '19 at 10:06
  • please mr.Crowder I really need your help. Just this question – user11807902 Jul 20 '19 at 10:11
  • @user11807902 - I think so, yes. Again, languages that didn't have two phases ended up needing to have something to deal with not having it. For instance, in C, you could *forward declare* the function (`void main();`) before using it, and use it (`main();`) before defining it (`void main() { /*...do stuff...*/ }`). That's *mostly* useful when writing a program across multiple files, but not only there. – T.J. Crowder Jul 20 '19 at 10:11
  • @user11807902 - It was only four minutes between your first comment above and your second one. All due respect, nagging someone after just four minutes is inappropriate. If you're going to nag someone at all, the interval should be hours, at least. – T.J. Crowder Jul 20 '19 at 10:12
  • sorry about that sir. I dunno I just thought you ignored my question. but anyways thank you sir you are the best:D – user11807902 Jul 20 '19 at 10:16