A face test that evolved from work
This is a problem I encountered in the work, it seems very interesting, as a problem to interview, found that almost no one can all correct and say the reason, so take out a chat.
First look at the topic code:
function Fun (n,o) {
console.log (o) return
{
fun:function (m) {return
fun (m,n);}}
;
}
var a = fun (0); A.fun (1); A.fun (2); A.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 output of line three a,b,c?
This is a very typical JS closure problem. The three-layer fun function is nested, and it is particularly important to know that the function of each layer fun is that fun function.
You can start by writing down the results you think on paper or elsewhere, and then start to see what the correct answer is?
Answer
a:undefined,0,0,0
//b:undefined,0,1,2
//c:undefined,0,1,1
Did you answer the right thing? If it's all right, congratulations. Almost nothing can get you down in the JS closure problem; If there is no answer, continue to analyze.
There are several functions in JS
First of all, before you need to understand that in JS functions can be divided into two types, named functions (named functions) and anonymous functions.
The method of distinguishing between these two functions is very simple, and can be judged by the output fn.name, the name of which is the named function, and the anonymous function without name.
Note: the name of the named function cannot be obtained on the lower version of IE, and will return to undefined, suggesting that it be tested on Firefox or Google browsers
Or the use of a compatible IE to obtain the function name method to get function names:
/**
* Gets the function name of the specified function (for IE compatible)
* @param {function} fun any function */functions
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;
}
The above function is used to test the anonymous function:
You can learn that variable fn1 is a named function, FN2 is an anonymous function
Several ways to create a function
To finish the type of function, you also need to know several ways to create a function in JS.
1. Declaring functions
The most common and standard method of declaring functions, including function names and function bodies.
function fn1 () {}
2. Create an anonymous function expression
Create a variable with the contents of the variable as a function
var fn1=function () {}
Note the function created by this method is an anonymous function, that is, no function name
var fn1=function () {};
Getfunctionname (FN1). length;//0
3. Create a named function expression
Create a variable with a function with a name
var fn1=function xxcanghai () {};
Note: The function name of a named function expression can only be used inside the creation function
That is, a function created using this method can only use the function name of fn1 that cannot use Xxcanghai in the outer layer of the function. The Xxcanghai name can only be used inside 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 >
You can see a function name outside of the function (out) that cannot use Xxcanghai, which is undefined.
Note: defining functions within an object, such as Var o={fn:function () {...}}, is also part of a function expression
4. Function constructor
You can pass a function string to the function constructor and return the function that contains the string command, which creates an anonymous function.
5. Self-executing function
(function () {alert (1);}) ();
(function fn1 () {alert (1);}) ();
The self-execution function belongs to the above "function expression" with the same rule
6, other ways to create a function
Of course, there are other ways to create functions or perform functions, there is no longer said here, such as the use of eval, settimeout, SetInterval , such as the very use of methods, here does not do too much introduction, is a non-standard method, here do not do too much expansion
What is the relationship between the three fun functions?
After you finish talking about the function type and the method of creating the function, you can return to the topic and look at this question.
There are three fun functions in this code, so the first step is to figure out the relationship between the three fun functions, and which function is the same as which function.
function Fun (n,o) {
console.log (o) return
{
fun:function (m) {
//...
}
};
The first fun function, which belongs to a standard named function declaration, is a newly created function whose return value is an object literal expression that belongs to the new object.
This new object contains a property that is also called fun, which is known to be an anonymous function expression, that is, fun, which holds a newly-created anonymous function expression.
Note: all declared anonymous functions are a new function.
So the first fun function is not the same as the second fun function, and is the newly created function.
The problem of function scope chain
Again, the third fun function needs to say that you can access the variable that holds the current function inside the function expression.
Test 1: A function expression inside an object:
var o={
fn:function () {
console.log (FN);
}
};
O.fn ();//error error
Test 2: A function expression inside a non-object:
var fn=function () {
console.log (FN);
};
fn ();//function () {console.log (FN);}; That's right
Conclusion: within the Var or non object internal function expression, you can access the variable that holds the current function, which is not accessible within the object.
The reason is also very simple, because of the problem of the function scope chain, using Var is to create a FN variable externally, within the function of course can not find the FN in the up-book scope lookup FN, and in the creation of objects inside, because the function scope is not created FN, so cannot be accessed.
So to sum up, you can learn that the most inner return of the fun function is not the second layer of fun function, is the outermost fun function.
So, the relationship between the three fun functions is also clear, the first is equal to the third, they are not equal to the second.
Which function are you calling anyway?
Looking at the original question again, I now know that there are two fun functions in the program (the first one is the same as the third), so the next question is figuring out which fun function he is performing at run time.
function Fun (n,o) {
console.log (o) return
{
fun:function (m) {return
fun (m,n);}}
;
}
var a = fun (0); A.fun (1); A.fun (2); A.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,?,?,?
1, the first line a
var a = fun (0); A.fun (1); A.fun (2); A.fun (3);
As you can see, the first fun (0) is to call the first layer fun function. The second fun (1) is the fun function that invokes the return value of the previous fun, so:
A few fun (1), Fun (2), Fun (3), are called the second-level fun function.
Hence
When the first call to Fun (0), O is undefined;
The second call Fun (1) when M is 1, at this time fun closed the outer function of N, that is, the first call n=0, that is, m=1,n=0, and the first layer of fun function fun (1,0); so o is 0;
The third call to Fun (2) when M is 2, but still is called a.fun, so or closed the first call when the N, so the internal call of the first layer of fun (2,0); so o is 0.
The fourth time the same;
Namely: The final answer is undefined,0,0,0
2, second line B
var B = Fun (0). Fun (1). Fun (2). Fun (3);//undefined,?,?,?
starting with fun (0), it must be the first layer of the call fun function, and his return value is an object, so the second fun (1) calls the second-level fun function, followed by the second-level fun function of the call.
Hence
In the first call to the first layer fun (0), O is undefined;
The second call. Fun (1) when M is 1, at this time fun closed the outer function of N, which is the first call of the n=0, that is, m=1,n=0, and the first layer fun function fun (1,0); so o is 0;
The third call to. Fun (2) is 2, at which point the current fun function is not the first return object executed, but the return object that executes the second time. And in the second execution of the first layer of fun function (1,0) so n=1,o=0, the return of the closure of the second time N, and then the third call to the third layer fun function m=2,n=1, that is, call the first layer fun function fun (2,1), so O is 1;
The fourth call. Fun (3) when M is 3, closure of the third call of N, the same, the final call to the first layer fun function for fun (3,2), so o 2;
The final answer: undefined,0,1,2
3, third line C
var c = Fun (0). Fun (1); C.fun (2); C.fun (3);//undefined,?,?,?
According to the preceding two examples, you can learn:
Fun (0) performs the first layer fun function,. Fun (1) performs the second layer fun function returned by Fun (0), where the statement ends, then C stores the return value of fun (1) Instead of the return value of fun (0), so the closure in C is also the value of n Fun (1) executed for the second time. C.fun (2) performs the second-layer fun function returned by Fun (1), and C.fun (3) performs the second-level fun function returned by Fun (1).
Hence
In the first call to the first layer fun (0), O is undefined;
The second call. Fun (1) when M is 1, at this time fun closed the outer function of N, which is the first call of the n=0, that is, m=1,n=0, and the first layer fun function fun (1,0); so o is 0;
The third call. Fun (2) when M is 2, the fun closure is the n=1 of the second invocation, that is, the m=2,n=1, and the first layer fun function fun (2,1) is called internally, so O is 1;
The fourth time. Fun (3) is the same, but is still the second return value of the call, resulting in a final call to the first layer fun function fun (3,1), so O is also 1
The final answer: undefined,0,1,1
Something
This code was originally in the Code to rewrite the asynchronous callback as a component of the synchronous call, and found the hole, and have a deeper understanding of JS's closure.
About what is closure, online articles are countless, but understand what is closed or in the code to find and understand themselves.
If I were to say what a closure is, I think that a generalized closure means that a variable is used in his own scope, which is called a closure.
Did everyone answer the right? I hope that the reader will be able to understand the closure phenomenon in this paper, if you have other opinions or views, please comment.