Be insensitive, and keep a lifelong growth mindset.

0%

How JavaScript Works Behind the Scenes?

1. What Happens to Our Code?

What Happens to Our Code

2. Execution Contexts and the Execution Stack

2.1. Execution Context

Execution Context

  • Code that is not inside any function
  • Associated with the global object
  • In the browser, that’s the window object
1
lastName === window.lastName

2.2. Execution Stack

When executing the code inside a function, a new Execution Context will be created on top of the existing one.

Execution Stack

3. The Execution Context in Detail: Creation and Execution Phase and Hoisting

3.1. The Execution Context in Detail

The Execution Context in Detail

  1. Creation phase
    • Creation of the Variable Object(VO)
    • Creation of the scope chain
    • Determine value of the ‘this’ variable
  2. Execution phase
    • The code of the function that generated the current execution context is ran line by line

3.2. The Variable Object

  • The argument object is created, containing all the arguments that were passed into the function.
  • Code is scanned for function declarations: for each function, a property is created in the Variable Object, pointing to the function. [Hoisting]
  • Code is scanned for variable declarations: for each variable, a property is created in the Variable Object, and set to undefined. [Hoisting]

4. Hoisting in Practice

4.1. Function Hoisting

1
2
3
4
caculatedAge(1990);
function calculatedAge(year) { //Function has already been available before executing
console.log(2016 - year);
}

The above code works because the function has already been available before executing.

However, for the following code, it’s not working, since retirement has been created, but just set to undefined before execution.

1
2
3
4
retirement(1990);
var retirement = function(year) {
console.log(65 - (2016 - year));
}

4.2. Variable Hoisting

1
2
console.log(age);
var age = 23;

The above code only prints undefined, which is as expected.

1
2
3
4
5
6
7
8
9
console.log(age);
var age = 23;

function foo() {
var age = 65;
console.log(age);
}
foo();
console.log(age);

The results are:

1
2
65
23

Because the first age is a local variable, but the second is a global one.

5. Scoping and the Scope Chain

5.1. Scoping in JavaScript

  • Scoping answers the question “where can we access a certain variable?”
  • Each new function creates a scope: the space/environment, in which the variables it defines are accessible.
  • Lexical scoping: a function that is lexically within another function gets access to the scope of the outer function.

Scoping in JavaScript

5.2. Execution Stack vs Scope Chain

Though the stack and scope chain look similar, they are still different.
Execution Stack vs Scope Chain

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var a = 'Hello!';
first();

function first() {
var b = 'Hi';
second();

function second() {
var c = 'Hey!';
third();
}
}

function third() {
var d = 'John';
console.log(c);
}

The execution result:

1
Uncaught ReferenceError: c is not defined.

Because of the scope of the third function, it can only access variable a and d.

6. The ‘this’ Keyword

  • Regular function call: the this keyword points at the global object, (the window object, in the browser).
  • Method call: the this variable points to the object that is calling the method.

The this keyword is not assigned a value until a function where it is defined is actually called.

7. The ‘this’ Keyword in Practice

Case 1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

calculateAge(1985);

function calculateAge(year) {
console.log(2016 - year);
console.log(this); //First 'this'
}

var john = {
name: 'John',
yearOfBirth: 1990,
calculateAge: function() {
console.log(this); //Second 'this'
console.log(2016 - this.yearOfBirth);
}
}
john.calculateAge();

In this case, the first ‘this’ is the window object, and the second ‘this’ is the john object.

Case 2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var john = {
name: 'John',
yearOfBirth: 1990,
calculateAge: function() {
console.log(this); //First 'this'
console.log(2016 - this.yearOfBirth);
function innerFunction() {
console.log(this); //Second 'this'
}
innerFunction();
}
}

john.calculateAge();

In this case, the first ‘this’ is the john object, however, the second object is the window object. It’s because the second ‘this’ is inside a regular function call.

Case 3 (Method Borrowing):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var john = {
name: 'John',
yearOfBirth: 1990,
calculateAge: function() {
console.log(this);
console.log(2016 - this.yearOfBirth);
}
}

john.calculateAge();

var mike = {
name: 'Mike',
yearOfBirth: 1984
}

mike.calculateAge = john.calculateAge;

In this case, ‘this’ in calling john.calculateAge() is john object, and ‘this’ in calling mike.calculateAge() is mike object.