面试题-闭包

这篇博客探讨了JavaScript中foo与foo()的区别,重点在于闭包的概念。foo函数返回一个匿名函数,形成了闭包,使得局部变量i的作用域得以延续,不会在函数调用结束后立即销毁。因此,即使f1和f2都调用了foo(),由于每次调用都会创建新的函数对象,它们并不共享同一作用域,导致结果并不相同。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

function Foo() {
    var i = 0;
    return function() {
        console.log(i++);
    }
}
var f1 = Foo(), // function() {console.log(i++);}
    f2 = Foo(); // function() {console.log(i++);}

f1(); 
f1(); 
f2();

foo与foo()的区别,foo指的是整个foo函数的js代码,foo()指的是return 的语句。

这道题考察闭包引用类型对象的知识点:
1.一般来说函数执行完后它的局部变量就会随着函数调用结束被销毁,但是此题foo函数返回了一个匿名函数的引用(即一个闭包),它可以访问到foo()被调用产生的环境,而局部变量i一直处在这个环境中,只要一个环境有可能被访问到,它就不会被销毁,所以说闭包有延续变量作用域的功能。这就好理解为什么:

1

2

f1();//0

f1();//1

2.我一开始认为f1和f2都=foo()是都指向了同一个function引用类型,所以顺理成章就会答错认为:

1

f2();//2

但其实foo()返回的是一个匿名函数,所以f1,f2相当于指向了两个不同的函数对象,所以结果也就顺理成章的变为:

1

f2();//0

参考:https://www.nowcoder.com/questionTerminal/ca2472f3581c467fb81a7a77b47ab740

<think>我们正在处理关于JavaScript闭包面试题的用户查询。根据提供的引用,特别是引用[2]、[3]、[4],我们可以总结出几个常见的闭包面试题及其解析。用户要求的是“JavaScript闭包面试题”,因此我们将重点放在常见的闭包面试题上,并给出解析。根据引用[3]和[4]中的示例,有一个非常典型的闭包面试题,涉及一个函数返回一个对象,对象中有一个方法,该方法又调用外部函数,形成闭包。我们将以这个题目为例进行解析。题目如下(来自引用[4]):```javascriptfunctionfun(n,o){console.log(o);return{fun:function(m){returnfun(m,n);}};}```然后有如下调用:```javascriptvara=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);//?```我们将逐步分析这个题目。首先,函数`fun`接受两个参数`n`和`o`,并打印出`o`。然后返回一个对象,该对象有一个方法`fun`,这个方法接受一个参数`m`,并调用`fun(m,n)`(注意这里调用的是外部的`fun`函数,并且将当前的`n`作为第二个参数传入,即新的调用中`o`将是当前的`n`)。分析关键点:1.每次调用外部函数`fun`时,都会创建一个新的闭包,该闭包保存了此次调用时的参数`n`(因为内部函数引用了`n`)。2.内部函数`fun`(即返回对象的方法)被调用时,会使用闭包中保存的`n`作为下一次调用的第二个参数(即`o`)。现在逐行分析:第一部分:```javascriptvara=fun(0);//调用fun(0),此时n=0,o未传入(即undefined),所以打印undefined//返回一个对象,这个对象的fun方法被调用时,会调用fun(m,0)(因为这里的n是0)//将返回的对象赋给aa.fun(1);//调用a.fun(1)->即调用fun(1,0)(因为闭包中保存的n是0)//此时,在fun(1,0)中:n=1,o=0->打印0//然后返回一个新对象,这个新对象的fun方法被调用时,会调用fun(m,1)(因为这里的n是1)a.fun(2);//同样,调用a.fun(2)->调用fun(2,0)(注意:a是第一次调用返回的对象,其内部闭包保存的n是0)//所以打印0a.fun(3);//同理,打印0```所以第一部分的输出是:`undefined,0,0,0`第二部分:```javascriptvarb=fun(0).fun(1).fun(2).fun(3);//分解://1.fun(0):打印undefined,返回对象A(对象A的fun方法调用时会用n=0)//2.对象A.fun(1):调用fun(1,0)->打印0,返回对象B(对象B的fun方法调用时会用n=1)//3.对象B.fun(2):调用fun(2,1)->打印1,返回对象C(对象C的fun方法调用时会用n=2)//4.对象C.fun(3):调用fun(3,2)->打印2//所以输出:undefined,0,1,2```第三部分:```javascriptvarc=fun(0).fun(1);//1.fun(0):打印undefined,返回对象A//2.对象A.fun(1):调用fun(1,0)->打印0,返回对象B(此时对象B的闭包中n=1)//将对象B赋给cc.fun(2);//调用c(即对象B)的fun(2)->调用fun(2,1)->打印1c.fun(3);//调用c的fun(3)->调用fun(3,1)->打印1```所以第三部分的输出:`undefined,0`(来自`varc=...`),然后`1,1`(来自`c.fun(2)`和`c.fun(3)`)。因此,整个题目的输出为:```undefined000------------undefined012------------undefined011```这个题目考察了闭包的概念:内部函数可以访问外部函数的变量,并且每次调用外部函数都会生成一个新的闭包环境。除了这个题目,闭包面试题还可能涉及循环中的闭包闭包的作用域链、闭包的内存管理等。例如,循环中使用闭包的经典问题(来自引用[1]和[2]):```javascriptfor(vari=0;i<5;i++){setTimeout(function(){console.log(i);},1000);}```这段代码会输出5个5,因为setTimeout中的函数共享同一个闭包,而变量i是全局作用域(或函数作用域)中的,循环结束后i变成了5。解决方法通常是使用立即执行函数表达式(IIFE)或使用let声明块级作用域变量。根据用户的需求,我们提供以上两个典型的闭包面试题及其解析。现在,我们按照要求生成相关问题。</think>### JavaScript 闭包面试题解析 #### 典型闭包面试题分析(引用[3][4]) ```javascript function fun(n, o) { console.log(o); return { fn: function(m) { return fun(m, n); } }; } // 示例调用 var a = fun(0); // 输出:undefined a.fn(1); // 输出:0 a.fn(2); // 输出:0 a.fn(3); // 输出:0 var b = fun(0).fn(1).fn(2).fn(3); // 输出:undefined, 0, 1, 2 var c = fun(0).fn(1); // 输出:undefined, 0 c.fn(2); // 输出:1 c.fn(3); // 输出:1 ``` #### 闭包机制解析 1. **闭包形成原理** 函数`fun`返回的对象中包含内部函数`fn`,该函数引用了外部变量`n`,形成闭包。每次调用`fun`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值