当前位置: 首页 > Web前端 > HTML

简单来说,一道JS闭包面试题

时间:2023-04-02 21:41:31 HTML

说明最近看到这么一段代码functionfun(n,o){console.log(o);返回{乐趣:函数(m){返回乐趣(m,n);}};}vara=fun(0);a.fun(1);a.fun(2);a.fun(3);varb=fun(0).fun(1).fun(2).fun(3);varc=fun(0).fun(1);c.fun(2);c.fun(3);//问题:a、b、c三行的输出是什么?觉得挺有意思的,跟大家聊聊。我相信,如果你对JavaScript中的闭包不是很了解的话,你肯定不想看这段代码。解释得很好,我们暂时不考虑这段代码,让我们看一个简单的函数fun0(){vara=1;console.log(a);}functionfun1(){console.log(a);}fun0();//1fun1();//报错aisnotdefined这段代码,相信大家应该都知道为什么结果是1最后报错了,函数中声明的变量只定义在函数体中,它们是局部变量,作用域是局部的,所以调用函数fun1后,如果找不到a,就会报错。JavaScript使用词法作用域,函数的执行取决于变量的作用域。这个作用域是在定义函数时确定的。所以只要我们改变上面函数fun1的位置,就不会报错了。函数fun0(){vara=1;控制台日志(一);//将fun1放入fun0中,不会报错functionfun1(){console.log(a);}fun1();//1}fun0();//将1的代码改成这样,只要把fun1放到fun0中就不会报错了。函数调用后,会输出1。那么,我们看一开始说的代码,把函数简化一下fun(n,o){return{}}我们先看这段代码,fun之后发生的事情是叫什么?显然会返回一个空对象,重要的是要记住在fun调用之后会返回该对象。functionfun(n,o){console.log(o);返回{乐趣:函数(m){返回乐趣(m,n);}};}变量a=乐趣(0);函数声明时传入的实参个数小于函数声明时指定的形参个数,剩余的形参将被设置为未定义的值。控制台日志(o);输出未定义的vara=fun(0);a的值是多少,是fun(0),返回的对象{fun:function(m){returnfun(m,0);}}这个对象有一个fun方法,方法返回的结果是最外层fun调用的结果。vara=fun(0),传入一个参数0,也就是说函数fun中参数n的值为0,返回的对象需要一个参数n,而n的范围内没有这个对象,它沿着作用域继续在上层作用域中寻找n,最终在函数fun中找到了n,而n的值为0。这段话是本文的重点。如果你理解了这段话,问题就很容易解决了。话虽如此,这个问题基本可以解决了。我希望你能理解我上面说的。下面很简单。让我们一步步来看。现在我们知道a是一个对象{fun:function(m){returnfun(m,0);}}a.fun(1);会发生什么?看代码{fun:function(1){returnfun(1,0);}}a.fun(1);返回结果为fun(1,0),返回结果为functionfun(n,o){//n的值为1,o的值为0console.log(o);return{fun:function(m){returnfun(m,n);//n的值为1}};}fun(1,0);//输出0并返回一个对象。这个对象有一个有趣的方法。调用该方法后,会返回外层fun函数调用的结果,外层函数的第二个参数为n值,即1a.fun(2);会发生什么?看代码{fun:function(2){returnfun(2,0);}}a.fun(2);返回结果为fun(2,0),返回结果为functionfun(n,o){//n的值为2,o的值为0console.log(o);返回{乐趣:函数(m){返回乐趣(m,n);//n的值为2}};}fun(2,0);//输出0并返回一个对象。这个对象有一个有趣的方法。该方法调用后会返回外层fun函数调用的结果,外层函数的第二个参数n的值为2a.fun(3);我就不说了,都是一样的。变种一个=乐趣(0);A。乐趣(1);A。乐趣(2);A。乐趣(3);变量b=乐趣(0)。);我们继续说b,b和a的区别就是vara=fun(0);之后一直使用对象a,是同一个对象,b每次都使用上次返回的对象。如果改成这个vara=fun(0);a=a.fun(1);a=a.fun(2);a=a.fun(3);varb=fun(0).fun(1).fun(2).fun(3);将返回的对象重新赋值给a,使两行的结果相同。变种c=乐趣(0).乐趣(1);c.乐趣(2);c.乐趣(3);c和他们的不一样,只是在varc=fun(0).fun(1);之后用的这只是同一个对象。总结结果vara=fun(0);a.乐趣(1);a.乐趣(2);a.fun(3);//未定义000varb=fun(0).fun(1).fun(2).fun(3);//未定义012varc=fun(0)。乐趣(1);c.乐趣(2);c.fun(3);//undefined011初始代码出自这里http://www.cnblogs.com/xxcang...这篇文章只是针对这个问题,不是很关注闭包的概念,所以如果朋友们,对闭包的详细概念还不是很了解,只好赶紧学习了。顺便推荐几篇讲解闭包的文章LearningJavascriptClosures(Closure)JavascriptClosures-懂不懂就看你了,反正我是了解了JS闭包的常见场景