What does the interpreter do next when the function is added to the Call Stack and the execution context for that function is created?

When an execution context is pushed, it has two life cycles, the creation and execution phases:

  1. Creation stage:

(1) Create a Variable Object: (2) establish a Scope chain; (3) determine the point of this in the function

  1. Execution phase:

① Variable assignment ② function reference ③ execute other code

When the execution phase is complete, the execution context is off the stack and the memory is reclaimed.

1. Variable Object

Normally, we write code that includes defining many variables and functions. How does the browser’s built-in interpreter work when given JS code?

The interpreter first needs to find the definitions of these variables and functions, and it will first generate variable objects when the execution context is created.

In a function environment, for example, when a function is called, it is pushed onto the function call stack and is at the top of the stack. At this point, we first enter the execution context creation phase, which consists of the following three parts:

  1. Create the Arguments object for the function. Check the parameters in the current context and establish the properties and property values under the object. Without an argument, the property value is undefined.
  2. All function declarations inside this function. Is a function declared using the function keyword. Create a property in the variable object with the function name. The property value is a reference to the memory address where the function resides. If the property of the function name already exists, it will be overwritten by the new reference.
  3. All variable declarations inside this function. Each time a variable declaration is found, a property is created in the variable object with the name of the variable and the value of the property is undefined. If the variable name is the same as the declared formal parameter or function, the variable declaration does not affect the existing attributes.

The process of creating variable objects


Activation Object 2

Again, the functional environment is the main scenario. The properties in the variable object are not accessible until the execution phase. After the execution phase, the variable Object becomes an active Object, and its properties can be accessed, and the code is executed.

Note that”become“Is the word. It is indicated in the context of function executionVariable ObjectActivation ObjectIt’s the same object, they just exist in different lifecycles.

3.JS Hosting mechanism

1. Variable improvement

Here’s an example:

var str = 'global';
function fn() {
  console.log(str);
  var str = 'local';
  console.log(str);
}
fn();
Copy the code

The output

undefined
'local'
Copy the code

We know that variable promotion is promoting the declaration part to the top of the function level scope. Here’s how the interpreter handles this code:

var str = 'global';
function fn() { / / fn functions
  var str; // STR is promoted here in the declaration part of the fn scope. The default value is undefined
  console.log(str); // Read the value of STR in the fn scope, and get undefined
  str = 'local'; // STR is assigned to the fn scope
  console.log(str); // Take STR again and get the value 'local'
}
fn();
Copy the code

Var STR = ‘local’ in the second line of the fn function is broken into two parts:

  • Var STR; In the context creation phase of fn, the variable object is generated with only the name of the variable, and the declaration part of the code is raised to the top of fn’s scope. The value of STR is undefined by default
  • ② Assignment part: STR = ‘local’;

Inside fn, the assignment to STR is already the third line. Assignment occurs during the execution phase of the function execution context, which completes the transformation of the variable object into the live object, determines the value of the variable’s property and references to the function declaration inside the function fn. At this point, we also enter the part of the code to execute, the first print STR output undefined, the second output ‘local’.

2. Function promotion

Function promotion is the same as variable promotion, which is promoted to the top of the current scope, but there are some differences: let’s look at an example:

console.log(fn1); // [Function: fn1]
fn1(); // fn1
console.log(fn2); // undefined
fn2(); // Uncaught TypeError: fn2 is not a function
function fn1() { // Declare the function
  console.log('fn1');
}
var fn2 = function(){ // Function expression
  console.log('fn2');
};
Copy the code


  • Function fn1 is called before the declaration, and the printed result can be obtained, and the call succeeds successfully, indicating that function fn1 is promoted.
  • An error will be reported when calling fn2, indicating that the function expression will not be promoted. If you want to call fn2, the calling statement should be written after the function expression that declares fn2.

That’s one, but the point is the second example:

var str = 'global';
function fn() {
    str = 'local';
    console.log(str);
    return;
    function str() {};
}
fn();
console.log(str);
Copy the code

The output

'local'
'global'
Copy the code

When this code is processed, the execution context enters the execution phase, completes variable assignments and function references, and is ready to execute the code, the code looks like this:

var str = 'global';
function fn() {
  var str = function () {};
  str = 'local';
  console.log(str);
  return;
}
fn();
console.log(str);
Copy the code

Var STR = function () {} Then the second line of STR = ‘local’ assigns STR to ‘local’, and the third line prints ‘local’.

Function promotion takes precedence over variable promotion because:


This happens from left to right, so obviously the second assignment to the function comes before the third assignment to the variable.

To conclude: describe the function context lifecycle in a relatively abstract piece of code (which is almost the processing logic of the interpreter) : first, the creation phase:

// The function fn performs the creation phase of the context
fnExecutionContext = { // fn Execution context
  VariableObject: {},  // Variable object
  ScopeChain: {}, // Scope chains. We'll discuss scopes and scope chains in a later article}...// the variableObject that handles the fn execution contextVariableObject = { args: {... },// Suppose the interpreter initializes a variable object with a list of fn arguments defined by args
    _fn: <_fn reference>  // _fn indicates a function definition in the execution context of fn, and <_fn reference> indicates an address reference
    str: undefined // STR represents the definition of a variable in the execution context of fn
}
Copy the code

Then comes the execution phase:

// Convert the variable object into an active object
Variable Object => Activation Object
...
// Complete the assignment to the variableObjectVariableObject = { args: {... },// Suppose fn passes arguments and args has some specific values
    _fn: <_fn reference>  // <_fn reference> function () {}
    str: 'local' // the STR variable has a value of 'local'
    this: window // Assume that fn is defined in the window, i.e. in the global execution environment
}
Copy the code