JS compilation - execution
What we will see . . .
● Compilation
● Execution
● Variable shadowing
● Variable hoisting
● Closures
● Execution context stack
● Event loop
Compilation Phase
● Creates the variable object: Variable object is a special object in JS which contain all the variables, function arguments and
inner functions declarations information.
● Creates the scope chain
● Determines the value of this
Extracts all the declarations (variable, function). It prepares the memory so that it can execute the code
variableObject: {
argumentObject: { }
},
scopechain: [],
This
Execution Phase
JavaScript is a single threaded language, meaning only one task can be executed at a time. When the JavaScript interpreter initially
executes code, it first enters into a global execution context by default. Each invocation of a function from this point on will result in
the creation of a new execution context.
● Global execution context
● Functional execution context
executionContextObj = {
variableObject: {
argumentObject: { }
},
scopechain: [],
this
}
Compilationglobal
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
globalExecutionContextObj = {
variableObject: {
argumentObject: { }
},
scopechain: [],
this
}
>
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
globalExecutionContextObj = {
variableObject: {
argumentObject: { },
a: undefined
},
scopechain: [],
this
}
>
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
globalExecutionContextObj = {
variableObject: {
argumentObject: { },
a: undefined
},
scopechain: [],
this
}
> no declaration found on this line. The JS engine moves on the next
line
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
globalExecutionContextObj = {
variableObject: {
argumentObject: { },
a: undefined,
funcName: pointer to heap memory in the function definition
},
scopechain: [],
this
}
> Whenever the JS engines finds a function declaration, creates a
property and points to heap memory where the function definition is
stored
> Moves to line 23
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
globalExecutionContextObj = {
variableObject: {
argumentObject: { },
a: undefined,
funcName: pointer to heap memory in the function definition
},
scopechain: [],
this
}
> This is not a declaration. Code won’t do anything here
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
globalExecutionContextObj = {
variableObject: {
argumentObject: {
length: 0
},
a: undefined,
funcName: pointer to heap memory in the function definition
},
scopechain: [Global execution context],
this: value of this
}
> end of code. Hence...
> scopechain is set
> this is set
Executionglobal
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
globalExecutionContextObj = {
variableObject: {
argumentObject: {
length: 0
},
a: 2,
funcName: pointer to heap memory in the function definition
},
scopechain: [Global execution context],
this: value of this
}
>
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
globalExecutionContextObj = {
variableObject: {
argumentObject: {
length: 0
},
a: 2,
funcName: pointer to heap memory in the function definition,
b: 1
},
scopechain: [Global execution context],
this: value of this
}
> No property with name b found. JS engine will create it and
initialize it with value 1
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
globalExecutionContextObj = {
variableObject: {
argumentObject: {
length: 0
},
a: 2,
funcName: pointer to heap memory in the function definition,
b: 1
},
scopechain: [Global execution context],
this: value of this
}
> No property with name b found. JS engine will create it and
initialize it with value 1
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
globalExecutionContextObj = {
variableObject: {
argumentObject: {
length: 0
},
a: 2,
funcName: pointer to heap memory in the function definition,
b: 1
},
scopechain: [Global execution context],
this: value of this
}
> Since it’s a function declaration the engine won’t do anything, and
moves to line 23
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
globalExecutionContextObj = {
variableObject: {
argumentObject: {
length: 0
},
a: 2,
funcName: pointer to heap memory in the function definition,
b: 1
},
scopechain: [Global execution context],
this: value of this
}
>
CompilationfuncName
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameExecutionContextObj = {
variableObject: {
argumentObject: {}
},
scopechain: [],
this:
}
> No arguments specified. Nothing will added in the argumentObject
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameExecutionContextObj = {
variableObject: {
argumentObject: {},
foo: undefined
},
scopechain: [],
this:
}
>
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameExecutionContextObj = {
variableObject: {
argumentObject: {},
foo: undefined,
funcNameA: pointer to heap memory in the function definition
},
scopechain: [],
this:
}
>
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameExecutionContextObj = {
variableObject: {
argumentObject: {},
foo: undefined,
funcNameA: pointer to heap memory in the function definition
},
scopechain: [],
this:
}
> This is not a declaration. Code won’t do anything here
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameExecutionContextObj = {
variableObject: {
argumentObject: {},
foo: undefined,
funcNameA: pointer to heap memory in the function definition,
bar: undefined
},
scopechain: [],
this:
}
>
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameExecutionContextObj = {
variableObject: {
argumentObject: {},
foo: undefined,
funcNameA: pointer to heap memory in the function definition,
bar: undefined
},
scopechain: [],
this:
}
> This is not a declaration. Code won’t do anything here
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameExecutionContextObj = {
variableObject: {
argumentObject: {},
foo: undefined,
funcNameA: pointer to heap memory in the function definition,
bar: undefined
},
scopechain: [funcName execution context, Global execution context],
this: value of this
}
> end of code. Hence...
> scopechain is set
> this is set
>
> As there is no other code, JS engine will start the execution phase
ExecutionfuncName
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameExecutionContextObj = {
variableObject: {
argumentObject: {
length: 0
},
foo: “foo”,
funcNameA: pointer to heap memory in the function definition,
bar: undefined
},
scopechain: [funcName execution context, Global execution context],
this: value of this
}
>
funcNameExecutionContextObj = {
variableObject: {
argumentObject: {
length: 0
},
foo: “foo”,
funcNameA: pointer to heap memory in the function definition,
bar: undefined
},
scopechain: [funcName execution context, Global execution context],
this: value of this
}
> It’s a function declaration, JS engine won’t do anything and moves
to line 17
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameExecutionContextObj = {
variableObject: {
argumentObject: {
length: 0
},
foo: “foo”,
funcNameA: pointer to heap memory in the function definition,
bar: undefined
},
scopechain: [funcName execution context, Global execution context],
this: value of this
}
globalExecutionContextObj = {
variableObject: {
argumentObject: {
length: 0
},
a: 2,
funcName: pointer to heap memory in the function definition,
b: 1,
foo1: “foo value”
},
scopechain: [Global execution context],
this: value of this
}
> There is no foo1 variable in the execution context. JS engines asks
the next execution context of the scope chain if this variable
exists. It doesn’t, so it creates it and assign the value
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameExecutionContextObj = {
variableObject: {
argumentObject: {
length: 0
},
foo: “foo”,
funcNameA: pointer to heap memory in the function definition,
bar: “bar”
},
scopechain: [funcName execution context, Global execution context],
this: value of this
}
>
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameExecutionContextObj = {
variableObject: {
argumentObject: {
length: 0
},
foo: “foo”,
funcNameA: pointer to heap memory in the function definition,
bar: “bar”
},
scopechain: [funcName execution context, Global execution context],
this: value of this
}
globalExecutionContextObj = {
variableObject: {
argumentObject: {
length: 0
},
a: 2,
funcName: pointer to heap memory in the function definition,
b: 1,
foo1: “foo value”
},
scopechain: [Global execution context],
this: value of this
}
>
CompilationfuncNameA
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameAExecutionContextObj = {
variableObject: {
argumentObject: {
0: arg1,
length: 1
},
arg1: 10
},
scopechain: [],
this:
}
> funcNameA has arg1 as variable. JS engine will add the arg1 in the
argument object and will create the property arg1 with value 10 in
the variable object
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameAExecutionContextObj = {
variableObject: {
argumentObject: {
0: arg1,
length: 1
},
arg1: 10,
foo1: undefined
},
scopechain: [],
this:
}
> Variable shadowing
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameAExecutionContextObj = {
variableObject: {
argumentObject: {
0: arg1,
length: 1
},
arg1: 10,
foo1: undefined,
foo2: undefined
},
scopechain: [],
this:
}
>
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameAExecutionContextObj = {
variableObject: {
argumentObject: {
0: arg1,
length: 1
},
arg1: 10,
foo1: undefined,
foo2: undefined
},
scopechain: [],
this:
}
> This is not a declaration. Code won’t do anything here
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameAExecutionContextObj = {
variableObject: {
argumentObject: {
0: arg1,
length: 1
},
arg1: 10,
foo1: undefined,
foo2: undefined
},
scopechain: [],
this:
}
> This is not a declaration. Code won’t do anything here
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameAExecutionContextObj = {
variableObject: {
argumentObject: {
0: arg1,
length: 1
},
arg1: 10,
foo1: undefined,
foo2: undefined
},
scopechain: [funcNameA execution context, funcName execution context,
Global execution context],
this:
}
> end of code. Hence...
> scopechain is set
> this is set
>
> As there is no other code, JS engine will start the execution phase
ExecutionfuncNameA
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameAExecutionContextObj = {
variableObject: {
argumentObject: {
0: arg1,
length: 1
},
arg1: 10,
foo1: ”foo1”,
foo2: undefined
},
scopechain: [funcNameA execution context, funcName execution context,
Global execution context],
this:
}
>
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameAExecutionContextObj = {
variableObject: {
argumentObject: {
0: arg1,
length: 1
},
arg1: 10,
foo1: ”foo1”,
foo2: undefined
},
scopechain: [funcNameA execution context, funcName execution context,
Global execution context],
this:
}
>
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameAExecutionContextObj = {
variableObject: {
argumentObject: {
0: arg1,
length: 1
},
arg1: 10,
foo1: ”foo1”,
foo2: undefined
},
scopechain: [funcNameA execution context, funcName execution context,
Global execution context],
this:
}
globalExecutionContextObj = {
variableObject: {
argumentObject: { length: 0 },
a: 2,
funcName: pointer to heap memory in the function definition,
b: 1,
foo1: “foo value”
foo3: “foo3”
}
}
> JS engine checks if foo3 exists in funcNameA. It’s not
> JS engine checks if foo3 exists in funcName. It’s not
> JS engine checks if foo3 exists in global scope. It’s not. It
creates the variable in global scope and sets the value foo3
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameAExecutionContextObj = {
variableObject: {
argumentObject: {
0: arg1,
length: 1
},
arg1: 10,
foo1: ”foo1”,
foo2: undefined
},
scopechain: [funcNameA execution context, funcName execution context,
Global execution context],
this:
}
globalExecutionContextObj = {
variableObject: {
argumentObject: { length: 0 },
a: 4,
funcName: pointer to heap memory in the function definition,
b: 1,
foo1: “foo value”
foo3: “foo3”
}
}
> JS engine checks if a exists in funcNameA. It’s not
> JS engine checks if a exists in funcName. It’s not
> JS engine checks if a exists in global scope. It exists. It
replaces the value with 4
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameAExecutionContextObj = {
variableObject: {
argumentObject: {
0: arg1,
length: 1
},
arg1: 10,
foo1: ”foo1”,
foo2: undefined
},
scopechain: [funcNameA execution context, funcName execution context,
Global execution context],
this:
}
globalExecutionContextObj = {
variableObject: {
argumentObject: { length: 0 },
a: 4,
funcName: pointer to heap memory in the function definition,
b: 1,
foo1: “foo value”
foo3: “foo3”
}
}
> funcNameA is garbage collected
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameAExecutionContextObj = {
variableObject: {
argumentObject: {
0: arg1,
length: 1
},
arg1: 10,
foo1: ”foo1”,
foo2: undefined
},
scopechain: [funcNameA execution context, funcName execution context,
Global execution context],
this:
}
globalExecutionContextObj = {
variableObject: {
argumentObject: { length: 0 },
a: 4,
funcName: pointer to heap memory in the function definition,
b: 1,
foo1: “foo value”
foo3: “foo3”
}
}
>
1 let a = 2;
2 b = 1;
3
4 function funcName() {
5 let foo = "foo";
6
7 function funcNameA(arg1) {
8 let foo1 = "foo1";
9
10 let foo2;
11
12 foo3 = "foo3";
13
14 a = 4;
15 }
16
17 foo1 = "foo value";
18 let bar = "bar";
19
20 funcNameA(10);
21 }
22
23 funcName();
funcNameAExecutionContextObj = {
variableObject: {
argumentObject: {
0: arg1,
length: 1
},
arg1: 10,
foo1: ”foo1”,
foo2: undefined
},
scopechain: [funcNameA execution context, funcName execution context,
Global execution context],
this:
}
globalExecutionContextObj = {
variableObject: {
argumentObject: { length: 0 },
a: 4,
funcName: pointer to heap memory in the function definition,
b: 1,
foo1: “foo value”
foo3: “foo3”
}
}
> funcName is garbage collected
Variable hoisting
1 console.log(b);
2 var b = 1;
var b;
console.log(b);
b=1;
> undefined
1 console.log(c);
2 var b = 1;
var b;
console.log(c);
b=1;
> Uncaught ReferenceError: c is not defined
1 function funcA(condition) {
2 console.log(var1);
3 if (condition) {
4 var var1 = "value of var1";
5 // do something
6 }
7 }
function funcA(condition) {
var var1;
console.log(var1);
if (condition) {
var1 = "value of var1";
// do something
}
}
> undefined
Closures
1 var adder = (num) => {
2 var sum = 0;
3 return () => {
4 sum += num;
5 console.log(sum);
6 }
7 }
8
9 var adder2 = adder(2);
10 adder2(); //2
11 adder2(); //4
12 adder2(); //6
13 adder2(); //8
> a closure is a stack frame which is allocated when a function
starts its execution, and not freed after the function returns (as if
a 'stack frame' were allocated on the heap rather than the stack!).
> https://stackoverflow.com/questions/111102/how-do-javascript-closures-work
1 var classA = function () {};
2
3 function func() {
4 var funcClassA = new classA();
5
6 function unreachable() {
7 funcClassA
8 };
9 return function () {};
10 }
11
12 var funVar = func();
>
1 var classA = function () {};
2
3 function func() {
4 var funcClassA = new classA();
5
6 return function () {};
7 }
8
9 var funVar = func();
>
Fanis Prodromou
https://www.linkedin.com/in/prodromouf/
Thank you

Javascript compilation execution

  • 1.
  • 2.
    What we willsee . . . ● Compilation ● Execution ● Variable shadowing ● Variable hoisting ● Closures ● Execution context stack ● Event loop
  • 3.
    Compilation Phase ● Createsthe variable object: Variable object is a special object in JS which contain all the variables, function arguments and inner functions declarations information. ● Creates the scope chain ● Determines the value of this Extracts all the declarations (variable, function). It prepares the memory so that it can execute the code variableObject: { argumentObject: { } }, scopechain: [], This
  • 4.
    Execution Phase JavaScript isa single threaded language, meaning only one task can be executed at a time. When the JavaScript interpreter initially executes code, it first enters into a global execution context by default. Each invocation of a function from this point on will result in the creation of a new execution context. ● Global execution context ● Functional execution context executionContextObj = { variableObject: { argumentObject: { } }, scopechain: [], this }
  • 5.
  • 6.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); globalExecutionContextObj = { variableObject: { argumentObject: { } }, scopechain: [], this } >
  • 7.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); globalExecutionContextObj = { variableObject: { argumentObject: { }, a: undefined }, scopechain: [], this } >
  • 8.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); globalExecutionContextObj = { variableObject: { argumentObject: { }, a: undefined }, scopechain: [], this } > no declaration found on this line. The JS engine moves on the next line
  • 9.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); globalExecutionContextObj = { variableObject: { argumentObject: { }, a: undefined, funcName: pointer to heap memory in the function definition }, scopechain: [], this } > Whenever the JS engines finds a function declaration, creates a property and points to heap memory where the function definition is stored > Moves to line 23
  • 10.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); globalExecutionContextObj = { variableObject: { argumentObject: { }, a: undefined, funcName: pointer to heap memory in the function definition }, scopechain: [], this } > This is not a declaration. Code won’t do anything here
  • 11.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); globalExecutionContextObj = { variableObject: { argumentObject: { length: 0 }, a: undefined, funcName: pointer to heap memory in the function definition }, scopechain: [Global execution context], this: value of this } > end of code. Hence... > scopechain is set > this is set
  • 12.
  • 13.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); globalExecutionContextObj = { variableObject: { argumentObject: { length: 0 }, a: 2, funcName: pointer to heap memory in the function definition }, scopechain: [Global execution context], this: value of this } >
  • 14.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); globalExecutionContextObj = { variableObject: { argumentObject: { length: 0 }, a: 2, funcName: pointer to heap memory in the function definition, b: 1 }, scopechain: [Global execution context], this: value of this } > No property with name b found. JS engine will create it and initialize it with value 1
  • 15.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); globalExecutionContextObj = { variableObject: { argumentObject: { length: 0 }, a: 2, funcName: pointer to heap memory in the function definition, b: 1 }, scopechain: [Global execution context], this: value of this } > No property with name b found. JS engine will create it and initialize it with value 1
  • 16.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); globalExecutionContextObj = { variableObject: { argumentObject: { length: 0 }, a: 2, funcName: pointer to heap memory in the function definition, b: 1 }, scopechain: [Global execution context], this: value of this } > Since it’s a function declaration the engine won’t do anything, and moves to line 23
  • 17.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); globalExecutionContextObj = { variableObject: { argumentObject: { length: 0 }, a: 2, funcName: pointer to heap memory in the function definition, b: 1 }, scopechain: [Global execution context], this: value of this } >
  • 18.
  • 19.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameExecutionContextObj = { variableObject: { argumentObject: {} }, scopechain: [], this: } > No arguments specified. Nothing will added in the argumentObject
  • 20.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameExecutionContextObj = { variableObject: { argumentObject: {}, foo: undefined }, scopechain: [], this: } >
  • 21.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameExecutionContextObj = { variableObject: { argumentObject: {}, foo: undefined, funcNameA: pointer to heap memory in the function definition }, scopechain: [], this: } >
  • 22.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameExecutionContextObj = { variableObject: { argumentObject: {}, foo: undefined, funcNameA: pointer to heap memory in the function definition }, scopechain: [], this: } > This is not a declaration. Code won’t do anything here
  • 23.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameExecutionContextObj = { variableObject: { argumentObject: {}, foo: undefined, funcNameA: pointer to heap memory in the function definition, bar: undefined }, scopechain: [], this: } >
  • 24.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameExecutionContextObj = { variableObject: { argumentObject: {}, foo: undefined, funcNameA: pointer to heap memory in the function definition, bar: undefined }, scopechain: [], this: } > This is not a declaration. Code won’t do anything here
  • 25.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameExecutionContextObj = { variableObject: { argumentObject: {}, foo: undefined, funcNameA: pointer to heap memory in the function definition, bar: undefined }, scopechain: [funcName execution context, Global execution context], this: value of this } > end of code. Hence... > scopechain is set > this is set > > As there is no other code, JS engine will start the execution phase
  • 26.
  • 27.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameExecutionContextObj = { variableObject: { argumentObject: { length: 0 }, foo: “foo”, funcNameA: pointer to heap memory in the function definition, bar: undefined }, scopechain: [funcName execution context, Global execution context], this: value of this } >
  • 28.
    funcNameExecutionContextObj = { variableObject:{ argumentObject: { length: 0 }, foo: “foo”, funcNameA: pointer to heap memory in the function definition, bar: undefined }, scopechain: [funcName execution context, Global execution context], this: value of this } > It’s a function declaration, JS engine won’t do anything and moves to line 17 1 let a = 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName();
  • 29.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameExecutionContextObj = { variableObject: { argumentObject: { length: 0 }, foo: “foo”, funcNameA: pointer to heap memory in the function definition, bar: undefined }, scopechain: [funcName execution context, Global execution context], this: value of this } globalExecutionContextObj = { variableObject: { argumentObject: { length: 0 }, a: 2, funcName: pointer to heap memory in the function definition, b: 1, foo1: “foo value” }, scopechain: [Global execution context], this: value of this } > There is no foo1 variable in the execution context. JS engines asks the next execution context of the scope chain if this variable exists. It doesn’t, so it creates it and assign the value
  • 30.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameExecutionContextObj = { variableObject: { argumentObject: { length: 0 }, foo: “foo”, funcNameA: pointer to heap memory in the function definition, bar: “bar” }, scopechain: [funcName execution context, Global execution context], this: value of this } >
  • 31.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameExecutionContextObj = { variableObject: { argumentObject: { length: 0 }, foo: “foo”, funcNameA: pointer to heap memory in the function definition, bar: “bar” }, scopechain: [funcName execution context, Global execution context], this: value of this } globalExecutionContextObj = { variableObject: { argumentObject: { length: 0 }, a: 2, funcName: pointer to heap memory in the function definition, b: 1, foo1: “foo value” }, scopechain: [Global execution context], this: value of this } >
  • 32.
  • 33.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameAExecutionContextObj = { variableObject: { argumentObject: { 0: arg1, length: 1 }, arg1: 10 }, scopechain: [], this: } > funcNameA has arg1 as variable. JS engine will add the arg1 in the argument object and will create the property arg1 with value 10 in the variable object
  • 34.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameAExecutionContextObj = { variableObject: { argumentObject: { 0: arg1, length: 1 }, arg1: 10, foo1: undefined }, scopechain: [], this: } > Variable shadowing
  • 35.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameAExecutionContextObj = { variableObject: { argumentObject: { 0: arg1, length: 1 }, arg1: 10, foo1: undefined, foo2: undefined }, scopechain: [], this: } >
  • 36.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameAExecutionContextObj = { variableObject: { argumentObject: { 0: arg1, length: 1 }, arg1: 10, foo1: undefined, foo2: undefined }, scopechain: [], this: } > This is not a declaration. Code won’t do anything here
  • 37.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameAExecutionContextObj = { variableObject: { argumentObject: { 0: arg1, length: 1 }, arg1: 10, foo1: undefined, foo2: undefined }, scopechain: [], this: } > This is not a declaration. Code won’t do anything here
  • 38.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameAExecutionContextObj = { variableObject: { argumentObject: { 0: arg1, length: 1 }, arg1: 10, foo1: undefined, foo2: undefined }, scopechain: [funcNameA execution context, funcName execution context, Global execution context], this: } > end of code. Hence... > scopechain is set > this is set > > As there is no other code, JS engine will start the execution phase
  • 39.
  • 40.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameAExecutionContextObj = { variableObject: { argumentObject: { 0: arg1, length: 1 }, arg1: 10, foo1: ”foo1”, foo2: undefined }, scopechain: [funcNameA execution context, funcName execution context, Global execution context], this: } >
  • 41.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameAExecutionContextObj = { variableObject: { argumentObject: { 0: arg1, length: 1 }, arg1: 10, foo1: ”foo1”, foo2: undefined }, scopechain: [funcNameA execution context, funcName execution context, Global execution context], this: } >
  • 42.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameAExecutionContextObj = { variableObject: { argumentObject: { 0: arg1, length: 1 }, arg1: 10, foo1: ”foo1”, foo2: undefined }, scopechain: [funcNameA execution context, funcName execution context, Global execution context], this: } globalExecutionContextObj = { variableObject: { argumentObject: { length: 0 }, a: 2, funcName: pointer to heap memory in the function definition, b: 1, foo1: “foo value” foo3: “foo3” } } > JS engine checks if foo3 exists in funcNameA. It’s not > JS engine checks if foo3 exists in funcName. It’s not > JS engine checks if foo3 exists in global scope. It’s not. It creates the variable in global scope and sets the value foo3
  • 43.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameAExecutionContextObj = { variableObject: { argumentObject: { 0: arg1, length: 1 }, arg1: 10, foo1: ”foo1”, foo2: undefined }, scopechain: [funcNameA execution context, funcName execution context, Global execution context], this: } globalExecutionContextObj = { variableObject: { argumentObject: { length: 0 }, a: 4, funcName: pointer to heap memory in the function definition, b: 1, foo1: “foo value” foo3: “foo3” } } > JS engine checks if a exists in funcNameA. It’s not > JS engine checks if a exists in funcName. It’s not > JS engine checks if a exists in global scope. It exists. It replaces the value with 4
  • 44.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameAExecutionContextObj = { variableObject: { argumentObject: { 0: arg1, length: 1 }, arg1: 10, foo1: ”foo1”, foo2: undefined }, scopechain: [funcNameA execution context, funcName execution context, Global execution context], this: } globalExecutionContextObj = { variableObject: { argumentObject: { length: 0 }, a: 4, funcName: pointer to heap memory in the function definition, b: 1, foo1: “foo value” foo3: “foo3” } } > funcNameA is garbage collected
  • 45.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameAExecutionContextObj = { variableObject: { argumentObject: { 0: arg1, length: 1 }, arg1: 10, foo1: ”foo1”, foo2: undefined }, scopechain: [funcNameA execution context, funcName execution context, Global execution context], this: } globalExecutionContextObj = { variableObject: { argumentObject: { length: 0 }, a: 4, funcName: pointer to heap memory in the function definition, b: 1, foo1: “foo value” foo3: “foo3” } } >
  • 46.
    1 let a= 2; 2 b = 1; 3 4 function funcName() { 5 let foo = "foo"; 6 7 function funcNameA(arg1) { 8 let foo1 = "foo1"; 9 10 let foo2; 11 12 foo3 = "foo3"; 13 14 a = 4; 15 } 16 17 foo1 = "foo value"; 18 let bar = "bar"; 19 20 funcNameA(10); 21 } 22 23 funcName(); funcNameAExecutionContextObj = { variableObject: { argumentObject: { 0: arg1, length: 1 }, arg1: 10, foo1: ”foo1”, foo2: undefined }, scopechain: [funcNameA execution context, funcName execution context, Global execution context], this: } globalExecutionContextObj = { variableObject: { argumentObject: { length: 0 }, a: 4, funcName: pointer to heap memory in the function definition, b: 1, foo1: “foo value” foo3: “foo3” } } > funcName is garbage collected
  • 47.
  • 48.
    1 console.log(b); 2 varb = 1; var b; console.log(b); b=1; > undefined
  • 49.
    1 console.log(c); 2 varb = 1; var b; console.log(c); b=1; > Uncaught ReferenceError: c is not defined
  • 50.
    1 function funcA(condition){ 2 console.log(var1); 3 if (condition) { 4 var var1 = "value of var1"; 5 // do something 6 } 7 } function funcA(condition) { var var1; console.log(var1); if (condition) { var1 = "value of var1"; // do something } } > undefined
  • 51.
  • 52.
    1 var adder= (num) => { 2 var sum = 0; 3 return () => { 4 sum += num; 5 console.log(sum); 6 } 7 } 8 9 var adder2 = adder(2); 10 adder2(); //2 11 adder2(); //4 12 adder2(); //6 13 adder2(); //8 > a closure is a stack frame which is allocated when a function starts its execution, and not freed after the function returns (as if a 'stack frame' were allocated on the heap rather than the stack!). > https://stackoverflow.com/questions/111102/how-do-javascript-closures-work
  • 53.
    1 var classA= function () {}; 2 3 function func() { 4 var funcClassA = new classA(); 5 6 function unreachable() { 7 funcClassA 8 }; 9 return function () {}; 10 } 11 12 var funVar = func(); >
  • 54.
    1 var classA= function () {}; 2 3 function func() { 4 var funcClassA = new classA(); 5 6 return function () {}; 7 } 8 9 var funVar = func(); >
  • 55.