这7道关于闭包的面试题,你能答对几个?

2025-05-29 0 86

每个 JavaScript 程序员都必须知道闭包是什么。在 JavaScript 面试中,你很可能会被问到闭包的概念。

以下是 7 个有关 JavaScript 闭包面试题,比较有挑战性。

不要查看答案或运行代码,看看自己的水平到底如何。做完这些题大约需要半小时左右。

这7道关于闭包的面试题,你能答对几个?

1. 热身

有以下函数 clickHandler,immediate和delayedReload:

letcountClicks=0;

button.addEventListener('click',functionclickHandler(){

countClicks++;

});

constresult=(functionimmediate(number){

constmessage=`numberis:${number}`;

returnmessage;

})(100);

setTimeout(functiondelayedReload(){

location.reload();

},1000);

这3个函数中哪个能够访问外部范围变量?

答案:

  • clickHandler 能够从外部作用域访问变量 countClicks。
  • immediate 无法访问外部作用域中的任何变量。
  • delayedReload 从全局作用域(也就是最外层作用域)中访问全局变量 location。

2. 丢失的参数

下列代码输出什么:

(functionimmediateA(a){

return(functionimmediateB(b){

console.log(a);//=>?

})(1);

})(0);

答案:

  • 输出为:0
  • 用参数 0 调用 immediateA,因此 a 参数为 0。
  • immediateB 函数嵌套在 immediateA 函数中,是一个闭包,它从外部 immediateA作用域中得到 a 变量,其中 a 为 0。因此 console.log(a) 的输出为 0。

3. 谁是谁

下面的代码将会输出什么内容?

letcount=0;

(functionimmediate(){

if(count===0){

letcount=1;

console.log(count);//输出什么?

}

console.log(count);//输出什么?

})();

答案:

  • 输出 1 和 0
  • 第一个语句 let count = 0 声明了一个变量 count。
  • immediate() 是一个闭包,它从外部作用域得到 count 变量。在 immediate() 函数作用域内, count 是 0。

但是,在条件内,另一个 let count = 1 声明了局部变量 count,该变量覆盖了作用域之外的 count。第一个 console.log(count) 输出 1。

第二个 console.log(count) 输出为 0 ,因为这里的 count 变量是从外部作用域访问的。

4. 棘手的闭包

下列代码输出什么:

for(vari=0;i<3;i++){

setTimeout(functionlog(){

console.log(i);//=>?

},1000);

}

答案输出:

  • 3, 3, 3。
  • 代码分为两个阶段执行。

阶段1:

  • for() 重复 3 次。在每次循环都会创建一个新函数 log(),该函数将捕获变量 i。setTimout() 安排log() 在 1000 毫秒后执行。
  • 当 for() 循环完成时,变量 i 的值为 3。

阶段2:

第二阶段发生在 1000ms 之后:

  • setTimeout() 执行预定的 log() 函数。log() 读取变量 i 当前的值 3,并输出 3
  • 所以输出 3, 3, 3。

5. 错误的信息

下面的代码将会输出什么:

functioncreateIncrement(){

letcount=0;

functionincrement(){

count++;

}

letmessage=`Countis${count}`;

functionlog(){

console.log(message);

}

return[increment,log];

}

const[increment,log]=createIncrement();

increment();

increment();

increment();

log();//=>?

答案:

输出:'Count is 0'

  • increment() 函数被调用 3 次,将 count 增加到 3。
  • message 变量存在于 createIncrement() 函数的作用域内。其初始值为 'Count is 0'。但即使 count 变量已经增加了几次,message 变量的值也始终为 'Count is 0'。
  • log() 函数是一个闭包,它从 createIncrement() 作用域中获取 message 变量。console.log(message) 输出录'Count is 0'到控制台。

6. 重新封装

下面的函数 createStack() 用于创建栈结构:

functioncreateStack(){

return{

items:[],

push(item){

this.items.push(item);

},

pop(){

returnthis.items.pop();

}

};

}

conststack=createStack();

stack.push(10);

stack.push(5);

stack.pop();//=>5

stack.items;//=>[10]

stack.items=[10,100,1000];//栈结构的封装被破坏了

它能正常工作,但有一个小问题,因为暴露了 stack.items 属性,所以任何人都可以直接修改 items 数组。

这是一个大问题,因为它破坏了栈的封装:应该只有 push() 和 pop() 方法是公开的,而 stack.items 或其他任何细节都不能被访问。

使用闭包的概念重构上面的栈实现,这样就无法在 createStack() 函数作用域之外访问 items 数组:

functioncreateStack(){

//把你的代码写在这里

}

conststack=createStack();

stack.push(10);

stack.push(5);

stack.pop();//=>5

stack.items;//=>undefined

答案:

以下是对 createStack() 的重构:

functioncreateStack(){

constitems=[];

return{

push(item){

items.push(item);

},

pop(){

returnitems.pop();

}

};

}

conststack=createStack();

stack.push(10);

stack.push(5);

stack.pop();//=>5

stack.items;//=>undefined

items 已被移至 createStack() 作用域内。

这样修改后,从 createStack() 作用域的外部无法访问或修改 items 数组。现在 items 是一个私有变量,并且栈被封装:只有 push() 和 pop() 方法是公共的。

push() 和 pop() 方法是闭包,它们从 createStack() 函数作用域中得到 items变量。

7. 智能乘法

编写一个函数 multiply() ,将两个数字相乘:

functionmultiply(num1,num2){

//把你的代码写在这里…

}

要求:

如果用 2 个参数调用 multiply(num1,numb2),则应返回这 2 个参数的乘积。

但是如果用 1个参数调用,则该函数应返回另一个函数:const anotherFunc = multiply(num1) 。返回的函数在调用 anotherFunc(num2) 时执行乘法 num1 * num2。

multiply(4,5);//=>20

multiply(3,3);//=>9

constdouble=multiply(2);

double(5);//=>10

double(11);//=>22

答案:

以下是 multiply() 函数的一种实现方式:

functionmultiply(number1,number2){

if(number2!==undefined){

returnnumber1*number2;

}

returnfunctiondoMultiply(number2){

returnnumber1*number2;

};

}

multiply(4,5);//=>20

multiply(3,3);//=>9

constdouble=multiply(2);

double(5);//=>10

double(11);//=>22

如果 number2 参数不是 undefined,则该函数仅返回 number1 * number2。

但是,如果 number2 是 undefined,则意味着已经使用一个参数调用了 multiply() 函数。这时就要返回一个函数 doMultiply(),该函数稍后被调用时将执行实际的乘法运算。

doMultiply() 是闭包,因为它从 multiply() 作用域中得到了number1 变量。

原文地址:https://mp.weixin.qq.com/s?__biz=MzI3NzIzMDY0NA==&mid=2247498832&idx=1&sn=a6aa457a7f330a6c1e8712621fd7393f&chksm=eb6bd90bdc1c501d975a8c8b4b0c157f130736c06b0c2eb9ee3ca3f5f8119cbf8844fa099dc5&mpshare=1&s

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 这7道关于闭包的面试题,你能答对几个? https://www.kuaiidc.com/95252.html

相关文章

发表评论
暂无评论