Accidentally, I did the wrong JS closure interview questions, and accidentally did the wrong js questions.
Interview Questions evolved from work
This is a problem I encountered at work. It seems very interesting. I went to the interview as a question and found that almost no one could answer all the correct questions and tell the reason. Let's have a chat.
First look at the question code:
Function fun (n, o) {console. log (o) return {fun: function (m) {return fun (m, n) ;};} var a = fun (0);. fun (1);. fun (2);. fun (3); // undefined ,?,?,? Var B = fun (0). fun (1). fun (2). fun (3); // undefined ,?,?,? Var c = fun (0). fun (1); c. fun (2); c. fun (3); // undefined ,?,?,? // Q: What are the outputs of three rows a, B, and c?
This is a very typical JS closure problem. Three Layers of fun functions are nested. It is particularly important to find out the fun function at each layer.
You can write down what you think on paper or elsewhere, and then expand to see what the correct answer is?
Answer
//a: undefined,0,0,0//b: undefined,0,1,2//c: undefined,0,1,1
Are you correct? If you have all the correct answers, congratulations, there is almost nothing to block you in the js closure question. If there is no answer, continue the analysis.
JS has several functions
First, you need to know that functions in JS can be divided into two types: named functions and anonymous functions.
The method for distinguishing these two functions is very simple. You can judge by outputting fn. name. If there is a name, it is a name function. If there is no name, it is an anonymous function.
Note:In earlier versions of IE, the name of the function cannot be obtained and undefined is returned. We recommend that you test the function on Firefox or Google Chrome.
Or use the IE-compatible method to obtain the function name:
/*** Get the Function name of the specified function (for IE compatibility) * @ param {Function} fun any function */Function getFunctionName (fun) {if (fun. name! = Undefined) return fun. name; var ret = fun. toString (); ret = ret. substr ('function '. length); ret = ret. substr (0, ret. indexOf ('); return ret ;}
Use the above function to test whether the function is anonymous:
We can know that the variable fn1 is a named function, and fn2 is an anonymous function.
How to Create a function
After talking about the function types, you also need to know several methods to create functions in JS.
1. Declare a function
The most common and standard declaration function method, including the function name and function body.
Function fn1 (){}
2. Create an anonymous function expression
Create a variable whose content is a function
Var fn1 = function (){}
Note that the function created using this method is an anonymous function, that is, there is no function name.
var fn1=function (){};getFunctionName(fn1).length;//0
3. Create a name function expression
Create a variable with a name.
Var fn1 = function xxcanghai (){};
Note:The name of a function expression can only be used inside the created function.
That is, the function created using this method can only use fn1 in the outer layer of the function and cannot use the xxcanghai function name. The xxcanghai name can only be used within the created function.
Test:
var fn1=function xxcanghai(){ console.log("in:fn1<",typeof fn1,">xxcanghai:<",typeof xxcanghai,">");};console.log("out:fn1<",typeof fn1,">xxcanghai:<",typeof xxcanghai,">");fn1();//out:fn1< function >xxcanghai:< undefined >//in:fn1< function >xxcanghai:< function >
The function name of xxcanghai cannot be used outside the function (out), which is undefined.
Note:Define a function in an object, such as var o = {fn: function (){...} }, Also belongs to the function expression
4. Function Constructor
You can pass a Function string to the Function constructor to return the Function that contains the string command. This method creates an anonymous Function.
5. Self-executed Functions
(function(){alert(1);})();(function fn1(){alert(1);})();
The self-executed function belongs to the above "function expression" and has the same rules.
6. other methods for creating Functions
Of course, there are other methods to create or execute functions, which are not mentioned here, such as usingEval, setTimeout, setIntervalThis is a non-standard method and is not described too much here.
What is the relationship between the three fun functions?
After talking about the function type and the method for creating the function, you can return to the topic and read this question.
This Code contains three fun functions, so the first step is to figure out the relationship between the three fun functions, which function is the same as the function.
function fun(n,o) { console.log(o) return { fun:function(m){ //... } };}
First, let's look at the first fun function, which belongs to the standard name function declaration and is a newly created function. Its return value is an object literal expression and belongs to a new object.
The new object contains an anonymous function expression, which is stored in the fun attribute.
Note:All declared anonymous functions are new functions.
Therefore, the first fun function is different from the second fun function. They are all newly created functions.
Function scope chain problems
Before talking about the third fun function, let's talk about whether the function expression can access the variable that stores the current function.
Test 1: function expressions inside the object:
Var o = {fn: function () {console. log (fn) ;}}; o. fn (); // ERROR
Test 2: Non-object internal function expressions:
Var fn = function () {console. log (fn) ;}; fn (); // function () {console. log (fn) ;}; correct
Conclusion:You can use var or a non-internal function expression to access the variables that store the current function.
The reason is also very simple, because of the function scope chain problem, the use of var is to create a fn variable in the external, the function can of course find the fn internally and then find the fn in the scope of the previous book, however, you cannot access the created object because the fn is not created in the function scope.
So in conclusion, we can know that the fun function at the inmost return is not the second-layer fun function, but the fun function at the outermost layer.
Therefore, the relationship between the three fun functions is also clear. The first is equal to the third, and they are not equal to the second.
Which function is being called?
Let's look at the original question again. Now we know that there are two fun functions in the program (the first and the third are the same). The next question is to find out which fun function is executed during runtime?
Function fun (n, o) {console. log (o) return {fun: function (m) {return fun (m, n) ;};} var a = fun (0);. fun (1);. fun (2);. fun (3); // undefined ,?,?,? Var B = fun (0). fun (1). fun (2). fun (3); // undefined ,?,?,? Var c = fun (0). fun (1); c. fun (2); c. fun (3); // undefined ,?,?,? // Q: What are the outputs of three rows a, B, and c?
1. First Line
Var a = fun (0); a. fun (1); a. fun (2); a. fun (3 );
We can know that the first fun (0) is to call the first level of fun function. The second fun (1) is the fun function that calls the return value of the previous fun, so:
The next few fun (1), fun (2), fun (3) functions are all calling the second-level fun function.
Ui:
When fun (0) is called for the first time, o is undefined;
When fun (1) is called for the second time, m is 1. At this time, fun closures the n of the outer function, that is, n = 0, that is, m = 1, n = 0, and internally call the first level of fun function (); so o is 0;
M is 2 when fun (2) is called for the third time, but a is still called. fun, so the n of the first call is closed, so the first layer of fun (2, 0) is called internally, so o is 0.
The fourth time is the same;
That is, the final answer is undefined, 0, 0
2. Row B
Var B = fun (0). fun (1). fun (2). fun (3); // undefined ,?,?,?
First, from fun (0), it must be the first level of fun function called; and its return value is an object, so the second fun (1) the second-level fun function is called, and the second-level fun function is called later.
Ui:
When the first level of fun (0) is called, o is undefined;
The second call. when fun (1), m is 1. At this time, fun closures the n of the outer function, that is, the n = 0 called for the first time, that is, m = 1, n = 0, and internally call the first level of fun function (); so o is 0;
M is 2 for the third call. fun (2). At this time, the current fun function is not the returned object for the first execution, but the returned object for the second execution. In the second execution of the first layer of the fun function (), so n = 1, o = 0, the second n is closed when the return value is, then when the third layer of the fun function is called, m = 2, n = 1, that is, the first layer of fun function fun (2, 1) is called, so o is 1;
For the fourth call. fun (3), m is 3, and n of the third call is closed. Similarly, the first-layer fun function is called (3, 2), so o is 2;
That is, the final answer: undefined, 0, 1, 2
3. Row c
Var c = fun (0). fun (1); c. fun (2); c. fun (3); // undefined ,?,?,?
Based on the previous two examples, we can see that:
Fun (0) is used to execute the first level of fun function ,. fun (1) executes the second-layer fun function returned by fun (0). The statement ends here, and then c stores the return value of fun (1) instead of fun (0) so the closure in c is also the value of n for the second execution of fun (1. C. fun (2) executes the second-level fun function returned by fun (1), and c. fun (3) executes the second-level fun function returned by fun (1.
Ui:
When the first level of fun (0) is called, o is undefined;
The second call. when fun (1), m is 1. At this time, fun closures the n of the outer function, that is, the n = 0 called for the first time, that is, m = 1, n = 0, and internally call the first level of fun function (); so o is 0;
The third call. when fun (2) is used, m is 2. At this time, the fun closure is the n = 1 of the second call, that is, m = 2, n = 1, and internally call the first level of fun function (2, 1); so o is 1;
The fourth time. fun (3) is the same, but it is still the second return value of the call. Then, the first layer of fun function fun (3, 1) is finally called, so o is 1
That is, the final answer: undefined, 0, 1, 1
Remarks
This code was originally used to write an asynchronous callback into a synchronously called component. It found this pitfall and gained a deeper understanding of the closure of JS.
There are countless articles on the Internet about what a closure is, but to understand what a closure is, you must discover and comprehend it yourself in the code.
If I want to talk about a closure, I think that a closure in the broad sense means that a variable is used in its own scope and is called a closure.
Are you all correct? I hope that you will have a better understanding of the closure phenomenon through this article. If you have any other opinions or opinions, please let us know.