preface

Start the interview question series. Experience comes from various markets, a few others face me, most I face others.

Welcome to the kickoff. It’s going to be fun. Get right to the point.

Question 1:How much do you know about JS closures? `

You’ve probably been asked:

  1. What is a closure?
  2. What are some real-world scenarios for closures?
  3. How do closures come about?
  4. How are variables generated by closures reclaimed?

The interviewer is asking you: What do you know about JS closures?

To summarize the answers I’ve heard, try to fully rephrase what the candidate said in the interview.

If a function returns a subfunction, the subfunction calls a variable in the function.

Answer 2: You can use closures inside the for loop to solve the problem.

for(var i = 0; i < 10; i++){
    setTimeout(() = >console.log(i),0)}// The console outputs 10 times 10.
for(var i = 0; i < 10; i++){
    (function(a){
    setTimeout(() = >console.log(a),0)
    })(i)
}
 // The console outputs 0-9
Copy the code

Answer 3: The current scope production generates a reference to the parent scope.

Answer 4: NO. Is it something to do with the browser’s garbage collection mechanism?

Open bar. How much is the answer similar to the above?

In fact, take these questions and think about them, and you will find that they are all for the ultimate problem.

The underlying implementation of closures

1. JS Execution context

As we all know, our hand-written JS code is precompiled by browser V8 before it is actually executed. For example, variable promotion, function promotion. Take chestnuts.

/ / chestnut:
var d = 'abc';
function a(){
    console.log("Function a");
};
console.log(a);   ƒ a(){console.log(" function a"); }
a();		      // 'function a'
var a = Variable "a";  
console.log(a);   // 'variable a'
a();			  // a is not a function
var c = 123;
 
// Output results and order:
ƒ a(){console.log(" function a"); }
// 'function a'
// 'variable a'
// a is not a function

// Chestnut preedited equivalent to:
function a(){
    console.log("Function a");
};
var d;
console.log(a);  ƒ a(){console.log(" function a"); }
a(); 			 // 'function a'

a = Variable "a";     // When a is assigned, the function declaration is overridden

console.log(a); // "variable a"
a(); 		// a is not a function

Copy the code

So here’s the problem. Who performs the precompile operation? Who precompiled this and where?

Yes, you are right to be confused. Js code needs a runtime environment to run, and this environment is the execution context. Yes, the precompilation of js before it runs is also done in this environment.

There are three types of js execution contexts:

  • Global execution context: The environment that the code first enters when it starts executing.
  • Function execution context: When a function is called, it starts executing the code in the function.
  • Eval execution context: This parameter is not recommended and can be ignored.

The execution context cycle, then, is divided into two phases:

  • Create a stage
    • Create a lexical environment
    • Generate variable objects (VO), the establishment ofThe scope chain,The scope chain,The scope chain(Say important things three times)
    • confirmthisPoint to and bindthis
  • Execution phase. This stage performs variable assignments, function references, and code execution.

Look at the picture to understand.

Now, can you guess when the precompilation happened?

Oh, I forgot to mention that there’s another name for compilation: execution context.

Precompilation occurs before the function is executed. The precompiled tetralogy is:

  1. createAOobject
  2. Find the parameter and variable declaration, and use the variable and parameter as the AO attribute name with the valueundefined
  3. Unify arguments and parameters
  4. Find the function declaration in the function body, and assign the value to the function body. Finally, when the program prints the value of the variable, it’s fromAOObject.

So, the real result of precompilation is:


var AO = {
    a = function a(){console.log("Function a"); }; d ='abc'
}
Copy the code

Let’s start over.

1. What is a variable object?

The variable object is an object created by the JS engine in memory when the JS code enters the execution context, which is used to store the variables in the current execution environment.

2. Creation process of variable object (VO)

The creation of variable objects is in the execution context creation stage, which goes through the following three processes in turn:

  • Create the Arguments object.

    For function execution environments, the first query is to see if any arguments were passed in. If so, the key-value pair with the argument name being the argument value is put into the Arguments object. Otherwise, put the key-value pair of the parameter name and undefined into the Arguments object.

// Take chestnuts for example
function bar(a, b, c) {
    console.log(arguments);  / / [1, 2]
    console.log(arguments[2]); // undefined
}
bar(1.2)
Copy the code
  • When a function with the same name is encountered, the later one overrides the previous one.
console.log(a); // function a() {console.log('Is a ?') }
function a() {
    console.log('Is a');
}
function a() {
  console.log('Is a ? ')}/** ps: the function declaration is created before the first line of code is executed. The following overrides the previous statement. * * /
Copy the code
  • Check the variable declaration in the current environment and assign toundefined. When a function declaration of the same name is encountered,In order to avoid the function being assignedundefinedIs ignored
console.log(a); // function a() {console.log('Is a ?') }
console.log(b); // undefined
function a() {
  console.log('Is a ');
}
function a() {
console.log('Is a ? ');
}
var b = 'Is b';
var a = 10086;

/** a = function (); b = function (); * * /
Copy the code

Based on the above three steps, you will know what is going on for variable promotion.

3. The variable object becomes an active object

In the second phase of the execution context, called the execution phase, variable assignments are made, function references are made, and other code is executed, at which point the variable object becomes an active object.

Let’s go back to the example above:

console.log(a); // function a() {console.log('fjdsfs') }
console.log(b); // undefined
function a() {
   console.log('Is a');
}
function a() {
 console.log('Is a? ');
}
var b = 'Is b';
console.log(b); // 'Is b'
var a = 10086; 
console.log(a);  / / 10086
var b = 'Is b? ';
console.log(b); // 'Is b? '
Copy the code

In the above code, the actual execution of the code starts at the first line console.log(), and before that, the execution context looks like this:

// Create processEC= {VO: {};// Create a variable object
  scopeChain: {}; // Scope chain
}
VO = {
  argument: {... };// The current context is global, so the value of this property is null
  a: <a reference>// a: undefiend // see step 3 to create the variable object above}Copy the code

Lexical scope (Lexical scope)

The point here is that we have variables in the function execution context and variables in the global execution context. One of the complexities of JavaScript is how it looks for variables, and if it can’t find a variable in the function execution context, it looks for it in the call context, and if it can’t find it in its call context, it keeps going up until it looks for it in the global execution context. (If it is not found, it is undefined).

Here’s another example:

 1: let top = 0; // 
 2: function createWarp() {
 3:   function add(a, b) {
 4:     let ret = a + b
 5:     return ret
 6:}7:   return add
 8:}9: let sum = createWarp()
10: let result = sum(top, 8)
11: console.log('result:',result)


Copy the code

The analysis process is as follows:

  • Declare variables in a global contexttopAnd assign it to 0.
  • Lines 2-8. A name is declared in the global execution contextcreateWarpAnd assign a function definition to it. Lines 3-7 describe its function definition and store it in that variable (createWarp).
  • Line 9. We declare a name in the global execution contextsumThe new variable of, temporarily, has a value ofundefined.
  • Line 9. encounter(a), indicating that a function needs to be executed or called.Then look for the memory of the global execution context and look for the namecreateWarpThe variables.Obviously, it was created in Step 2. Next, call it.
  • When the function is called, go back to line 2. Create a new onecreateWarpExecution context. We can go to thecreateWarpCreates its own variables in the execution context ofjsenginecreateWarpIs added to the call stack (call stack). Since this function has no arguments, skip to its body.
  • Rows 3-6. We have a new function declaration that creates the variable add in the context of the createWarp execution. Add exists only in the context of the createWarp execution, and its function definition is stored in its own variable named add.
  • In line 7, we return the variableaddThe content of the. The js engine looks for a name calledaddAnd find it. The content between the parentheses on lines 4 and 5 constitutes the function definition.
  • createWarpAfter the call,createWarpThe execution context will be destroyed. The add variable is also destroyed.addThe function definition still exists because it is returned and assigned tosumThe variable.(ps:This is the truth that the variables generated by closures are stored in memory)
  • The following is a simple implementation process, not to repeat.
  • When the code completes execution, the global execution context is destroyed. Sum and result were also destroyed.

The subtotal

Now, if you were asked what a closure is, how much would you say?

Actually, everyone is right. Whether a function returns a function or produces a reference to an outer scope, it makes sense.

So, what is a closure?

  • Explain how the scope chain is created.
  • Js execution context to explain the creation, execution process.
  • Explain where the variables generated by the closure are stored.
  • Finally, please combine the above three points to the interviewer.

In addition, if you are asked about the Event loop, the EC Stack, and the Call Stack, please make sure that one thing is clear. The EC Stack and the Call Stack are not the same thing. A lot of articles don’t tell the difference, or just say they’re the same thing. Later on, I’ll write an article about them for the conference

I wish you all the best.

Next, the WebPack compilation process. Absolutely dry stuff, it looks easy. Can deal with all webpack class interview questions