search
HomeWeb Front-endJS TutorialJS closure interview questions that you can do wrong by accident_javascript skills

Interview questions evolved from work

This is a question I encountered at work. It seemed very interesting, so I made it a question for interviews. I found that almost no one could answer all the questions correctly and tell the reasons, so I took it up and talked about it.

Look at the question code first:

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,?,?,?
//问:三行a,b,c的输出分别是什么?


This is a very typical JS closure problem. There are three levels of fun functions nested in it. It is particularly important to figure out which fun function the fun function of each level is.

You can first write down the results you think on paper or other places, 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 get everything right? If you answered everything correctly, congratulations. There is almost nothing that can stump you in the js closure problem; if there is no answer, continue to analyze.

There are several functions in JS

First of all, what you need to understand before this is that functions in JS can be divided into two types, named functions (named functions) and anonymous functions.

The method of distinguishing these two functions is very simple. You can judge by outputting fn.name. The one with a name is a named function, and the one without a name is an anonymous function

Note: The name of the named function cannot be obtained on lower versions of IE, and undefined will be returned. It is recommended to test on Firefox or Google Chrome

Or use the IE-compatible get function name method to get the function name:

/**
  * 获取指定函数的函数名称(用于兼容IE)
  * @param {Function} fun 任意函数
  */
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 it is an anonymous function:

You can know that variable fn1 is a named function and fn2 is an anonymous function

Several ways to create functions

After talking about the types of functions, you also need to understand that there are several ways to create functions in JS.

1. Declare function

The most common and standard way to declare a function, including function name and function body.

function fn1(){}

2. Create 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 named function expression

Create a variable containing a function with a name

var fn1=function xxcanghai(){};
Note: The function name of a named function expression can only be used inside the created function

That is, the function created using this method can only use fn1 and not xxcanghai’s function name in the outer layer of the function. The naming of 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 that the function name of xxcanghai cannot be used outside the function (out), and it is undefined.

Note: Defining a function within an object such as var o={ fn : function (){…} } is also a function expression

4. Function constructor

You can pass a function string to the Function constructor and return a function containing this string command. This method creates an anonymous function.

5. Self-executing function

(function(){alert(1);})();
(function fn1(){alert(1);})();

Self-executing functions belong to the above-mentioned "function expressions" and the rules are the same

6. Other ways to create functions

Of course, there are other ways to create functions or execute functions. I won’t go into details here. For example, using eval, setTimeout, setInterval and other very common methods. I won’t go into too much introduction here. They are non-standard methods. , I won’t expand too much here

What is the relationship between the three fun functions?

After talking about function types and methods of creating functions, you can return to the topic and look at this interview question.

There are three fun functions in this code, so the first step is to figure out the relationship between these three fun functions and which function is the same as which function.

function fun(n,o) {
 console.log(o)
 return {
  fun:function(m){
   //...
  }
 };
} 

先看第一个fun函数,属于标准具名函数声明,是新创建的函数,他的返回值是一个对象字面量表达式,属于一个新的object。

这个新的对象内部包含一个也叫fun的属性,通过上述介绍可得知,属于匿名函数表达式,即fun这个属性中存放的是一个新创建匿名函数表达式。

注意:所有声明的匿名函数都是一个新函数。

所以第一个fun函数与第二个fun函数不相同,均为新创建的函数。

函数作用域链的问题

再说第三个fun函数之前需要先说下,在函数表达式内部能不能访问存放当前函数的变量。

测试1:对象内部的函数表达式:

var o={
 fn:function (){
  console.log(fn);
 }
};
o.fn();//ERROR报错

测试2:非对象内部的函数表达式:

var fn=function (){
 console.log(fn);
};
fn();//function (){console.log(fn);};正确


结论:使用var或是非对象内部的函数表达式内,可以访问到存放当前函数的变量;在对象内部的不能访问到。

原因也非常简单,因为函数作用域链的问题,采用var的是在外部创建了一个fn变量,函数内部当然可以在内部寻找不到fn后向上册作用域查找fn,而在创建对象内部时,因为没有在函数作用域内创建fn,所以无法访问。

 

所以综上所述,可以得知,最内层的return出去的fun函数不是第二层fun函数,是最外层的fun函数。

所以,三个fun函数的关系也理清楚了,第一个等于第三个,他们都不等于第二个。

到底在调用哪个函数?

再看下原题,现在知道了程序中有两个fun函数(第一个和第三个相同),遂接下来的问题是搞清楚,运行时他执行的是哪个fun函数?

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,&#63;,&#63;,&#63;
var b = fun(0).fun(1).fun(2).fun(3);//undefined,&#63;,&#63;,&#63;
var c = fun(0).fun(1); c.fun(2); c.fun(3);//undefined,&#63;,&#63;,&#63;
//问:三行a,b,c的输出分别是什么? 

1. The first line a

var a = fun(0); a.fun(1); a.fun(2); a.fun(3);
It can be known that the first fun(0) is calling the first-level fun function. The second fun(1) is the fun function that calls the return value of the previous fun, so:

The last few fun(1), fun(2), fun(3) functions are all calling the second-level fun function.

Then:

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 closes n of the outer function, that is, n=0 for the first call, that is, m=1, n=0, and in The first level fun function fun(1,0) is called internally; so o is 0;

When fun(2) is called for the third time, m is 2, but a.fun is still called, so n from the first call is still closed, so the first layer of fun(2,0) is called internally. ;So o is 0

Same as the fourth time;

That is: the final answer is undefined,0,0,0

2. The second line b

var b = fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?
Let’s start with fun(0). It must be the first-level fun function called; and its return value is an object, so the second fun(1) calls the second-level fun function. , the following few are also the second-level fun functions called.

Then:

When the first level 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 closes n of the outer function, that is, n=0 for the first call, that is, m=1, n=0, and Internally call the first level fun function fun(1,0); so o is 0;

When .fun(2) is called for the third time, m is 2. At this time, the current fun function is not the return object of the first execution, but the return object of the second execution. When the first-level fun function is executed for the second time, (1,0), so n=1, o=0, the second n is closed when returning, so when the third-level fun function is called for the third time, m =2,n=1, that is, the first level fun function fun(2,1) is called, so o is 1;

When .fun(3) is called for the fourth time, m is 3, which closes the n of the third call. Similarly, the final call to the first-level fun function is fun(3,2); so o is 2;

That is 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,?,?,?
Based on the previous two examples, we can know:

fun(0) executes the first-level fun function, .fun(1) executes the second-level fun function returned by fun(0), the statement ends here, and c stores the return of fun(1) value, rather than the return value of fun(0), so the closure in c is also the value of n when fun(1) is executed for the second time. c.fun(2) executes the second-level fun function returned by fun(1), and c.fun(3) also executes the second-level fun function returned by fun(1).

Then:

When the first level 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 closes n of the outer function, that is, n=0 for the first call, that is, m=1, n=0, and Internally call the first level fun function fun(1,0); so o is 0;

When .fun(2) is called for the third time, m is 2. At this time, the fun closure is n=1 for the second call, that is, m=2, n=1, and the first layer of fun is called internally. Function fun(2,1); so o is 1;

The same is true for the fourth time .fun(3), but it is still the return value of the second call, so the first level fun function fun(3,1) is finally called, so o is still 1

That is the final answer: undefined,0,1,1

Later words

This code was originally made when rewriting an asynchronous callback into a synchronous call component. I discovered this pitfall and gained a deeper understanding of JS closures.

There are countless articles on the Internet about what closures are, but to understand what closures are, you still have to discover and understand them yourself in the code.

If you ask me what a closure is, I think closure in a broad sense means that a variable is used in its own scope, which is called closure.

Did everyone answer correctly? I hope readers can gain a better understanding of the closure phenomenon through this article. If you have other insights or opinions, please feel free to correct and discuss.

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
From Websites to Apps: The Diverse Applications of JavaScriptFrom Websites to Apps: The Diverse Applications of JavaScriptApr 22, 2025 am 12:02 AM

JavaScript is widely used in websites, mobile applications, desktop applications and server-side programming. 1) In website development, JavaScript operates DOM together with HTML and CSS to achieve dynamic effects and supports frameworks such as jQuery and React. 2) Through ReactNative and Ionic, JavaScript is used to develop cross-platform mobile applications. 3) The Electron framework enables JavaScript to build desktop applications. 4) Node.js allows JavaScript to run on the server side and supports high concurrent requests.

Python vs. JavaScript: Use Cases and Applications ComparedPython vs. JavaScript: Use Cases and Applications ComparedApr 21, 2025 am 12:01 AM

Python is more suitable for data science and automation, while JavaScript is more suitable for front-end and full-stack development. 1. Python performs well in data science and machine learning, using libraries such as NumPy and Pandas for data processing and modeling. 2. Python is concise and efficient in automation and scripting. 3. JavaScript is indispensable in front-end development and is used to build dynamic web pages and single-page applications. 4. JavaScript plays a role in back-end development through Node.js and supports full-stack development.

The Role of C/C   in JavaScript Interpreters and CompilersThe Role of C/C in JavaScript Interpreters and CompilersApr 20, 2025 am 12:01 AM

C and C play a vital role in the JavaScript engine, mainly used to implement interpreters and JIT compilers. 1) C is used to parse JavaScript source code and generate an abstract syntax tree. 2) C is responsible for generating and executing bytecode. 3) C implements the JIT compiler, optimizes and compiles hot-spot code at runtime, and significantly improves the execution efficiency of JavaScript.

JavaScript in Action: Real-World Examples and ProjectsJavaScript in Action: Real-World Examples and ProjectsApr 19, 2025 am 12:13 AM

JavaScript's application in the real world includes front-end and back-end development. 1) Display front-end applications by building a TODO list application, involving DOM operations and event processing. 2) Build RESTfulAPI through Node.js and Express to demonstrate back-end applications.

JavaScript and the Web: Core Functionality and Use CasesJavaScript and the Web: Core Functionality and Use CasesApr 18, 2025 am 12:19 AM

The main uses of JavaScript in web development include client interaction, form verification and asynchronous communication. 1) Dynamic content update and user interaction through DOM operations; 2) Client verification is carried out before the user submits data to improve the user experience; 3) Refreshless communication with the server is achieved through AJAX technology.

Understanding the JavaScript Engine: Implementation DetailsUnderstanding the JavaScript Engine: Implementation DetailsApr 17, 2025 am 12:05 AM

Understanding how JavaScript engine works internally is important to developers because it helps write more efficient code and understand performance bottlenecks and optimization strategies. 1) The engine's workflow includes three stages: parsing, compiling and execution; 2) During the execution process, the engine will perform dynamic optimization, such as inline cache and hidden classes; 3) Best practices include avoiding global variables, optimizing loops, using const and lets, and avoiding excessive use of closures.

Python vs. JavaScript: The Learning Curve and Ease of UsePython vs. JavaScript: The Learning Curve and Ease of UseApr 16, 2025 am 12:12 AM

Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

Python vs. JavaScript: Community, Libraries, and ResourcesPython vs. JavaScript: Community, Libraries, and ResourcesApr 15, 2025 am 12:16 AM

Python and JavaScript have their own advantages and disadvantages in terms of community, libraries and resources. 1) The Python community is friendly and suitable for beginners, but the front-end development resources are not as rich as JavaScript. 2) Python is powerful in data science and machine learning libraries, while JavaScript is better in front-end development libraries and frameworks. 3) Both have rich learning resources, but Python is suitable for starting with official documents, while JavaScript is better with MDNWebDocs. The choice should be based on project needs and personal interests.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

MantisBT

MantisBT

Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

PhpStorm Mac version

PhpStorm Mac version

The latest (2018.2.1) professional PHP integrated development tool

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

Powerful PHP integrated development environment