The question of the face that evolved from work
This is a problem I encountered in the work, it seems very interesting, as a question to interview, found that almost no one can answer all the answers and say why, then 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 outputs of the three line a,b,c?
This is a very typical JS closure problem. Nested in the three layers of fun functions, figuring out the function of each layer of fun is the fun function is particularly important.
You can write down the results on paper or somewhere else 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
Did you answer the right thing? If it's all right, congratulations. There is little you can do in the JS closure problem, and if you don't answer correctly, continue to analyze.
There are several functions in JS
First of all, we need to understand that in JS, functions can be divided into two, named functions (named functions) and anonymous functions.
The method of distinguishing between these two functions is very simple, can be judged by output Fn.name, name is named function, no name is anonymous function
Note: The name of the named function cannot be obtained on the low version of IE, it will return undefined, and it is recommended to test it on Firefox or Google Chrome.
Or use the Get function name method of IE to get the function names:
/** * Gets the function name of the specified function (for compatibility with IE) * @param {function} fun any functions */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;}
The above function is used to test whether it is an anonymous function:
You can tell that the variable fn1 is a named function, and FN2 is an anonymous function
Several ways to create a function
After saying the type of the function, you need to understand that there are several ways to create the function in JS.
1. Declaring functions
The most common and most 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 that the function created by this method is an anonymous function, that is, there is no function name
var fn1=function () {};getfunctionname (fn1). length;//0
3. Create a named function expression
Create a variable with the content of a function with a name
var fn1=function xxcanghai () {};
Note: The function name of the named function expression can only be used inside the creation function
That is, a function created with this method can only use FN1 in the outer layer of the function and cannot use the Xxcanghai function name. The name of the Xxcanghai 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 the function name that is outside the function (out) that cannot be used with Xxcanghai, which is undefined.
Note: Defining functions within objects such as Var o={fn:function () {...}}, also belongs to function expressions
4. Function constructor
You can pass a function string to the function constructor and return the functions that contain the string command, which creates an anonymous function.
5. Self-executing function
(function () {alert (1);}) ();(function fn1 () {alert (1);}) ();
The self-executing function belongs to the "function expression" above, with the same rules
6. Other ways to create functions
Of course there are other ways to create functions or execute functions, here no longer say, such as the use of Eval, SetTimeout, setinterval and other very useful methods, here do not introduce too much, belong to non-standard method, here do not do too much to expand
What is the relationship between the three fun functions?
After talking about the function type and the method of creating the function, we can return to the topic and see the question of the face.
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 one.
function Fun (n,o) { console.log (o) return { fun:function (m) { //... } };}
The first fun function, which belongs to the standard named function declaration, is a newly created function whose return value is an object literal expression, which belongs to a new type of object.
This new object contains a property called fun, which, through the above introduction, is an anonymous function expression, that is, the fun property is 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, which is the newly created function.
The problem of function scope chain
Besides, the third fun function needs to be preceded by the ability to access the variables that hold the current function inside the function expression.
Test 1, the function expression inside the 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
The conclusion is that the variable that holds the current function can be accessed using var or a function expression inside a non-object, and cannot be accessed inside the object.
The reason is also very simple, because the function scope chain problem, the use of Var is to create an FN variable externally, inside the function can certainly not find FN internally after the scope of the book to find FN, and in the creation of objects inside, because there is no scope to create FN within the scope of the function, it is inaccessible.
So in summary, it can be learned that the most inner return to go out of the fun function is not the second layer of fun function, is the outermost fun function.
So, the relationship of the three fun functions is also clear, the first equals the third one, they are not equal to the second one.
Which function is called exactly?
Look at the original question, now know that the program has two fun functions (the first and the third is the same), then the next question is to figure out what the fun function he was running?
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 outputs of the three line a,b,c?
1, the first line a
var a = fun (0); A.fun (1); A.fun (2); A.fun (3);
It can be learned that the first fun (0) is called in the first layer fun function. The second fun (1) is a fun function that calls the return value of the previous fun, so:
After the first few fun (1), Fun (2), Fun (3), the function is called the second layer 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 of the n=0, that is, m=1,n=0, and in the internal call the first layer fun function fun (1,0); so o is 0;
The third call to Fun (2) when M is 2, but still call A.fun, so still closed the first call when the N, so the internal call the first layer of fun (2,0); so o is 0
Fourth time similarly;
That is, the final answer is undefined,0,0,0.
2, second row B
var B = Fun (0). Fun (1). Fun (2). Fun (3);//undefined,?,?,?
First from the fun (0), it must be the first fun function of the call, and his return value is an object, so the second fun (1) Call is the second layer of fun function, the next few are called the second layer of fun function.
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, that is, the first call of the n=0, that is, m=1,n=0, and in the internal call the first layer fun function fun (1,0), so O is 0;
The third call. Fun (2) when M is 2, the current fun function is not the first time the returned object executes, but the second execution of the return object. And in the second execution of the first layer of fun function time (1,0) so n=1,o=0, return closed the second time of N, so in 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;
Fourth call. Fun (3) m is 3, closed the third call of N, the same, the final call to the first layer fun function is fun (3,2); so o is 2;
That's the final answer: undefined,0,1,2
3, the third line C
var c = Fun (0). Fun (1); C.fun (2); C.fun (3);//undefined,?,?,?
According to the previous two examples, it is possible to know:
Fun (0) for the implementation of the first layer of fun function,. Fun (1) is a fun (0) Return of the second layer of the fun function, where the statement ends, then C is a fun (1) of the return value, rather than fun (0) return value, so C is also a fun (1) second execution of n value. C.fun (2) is a fun (1) Return of the second layer of fun function, C.fun (3) is also a fun (1) Return of the second layer of fun function.
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, that is, the first call of the n=0, that is, m=1,n=0, and in the internal call the first layer fun function fun (1,0), so O is 0;
The third call. Fun (2) when M is 2, at this time the fun closure is the second call of the N=1, that is, m=2,n=1, and in the internal call the first layer fun function fun (2,1); so o is 1;
The fourth time. Fun (3) is the same, but still the second return value of the call, and finally call the first layer fun function fun (3,1), so O is also 1
That's the final answer: undefined,0,1,1
Something
This code was originally to make an asynchronous callback into the synchronous call of the component when the code, found the hole, the JS closure has a more in-depth understanding.
There are countless articles on the web about what closures are, but understanding what closures are, or discovering and understanding them in code.
If I were to say what a closure is, I think that a generalized closure means that a variable is used outside of his own domain and is called a closure.
I hope readers can get a better understanding of the closure phenomenon through this article, if there are other views or views, please correct or leave a message to discuss. Finish
You don't have to be right. JavaScript closed-Face questions