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

自测,关于闭包的7道面试题

时间:2023-03-27 11:47:52 JavaScript

更多文章见公众号【前端css和js干货】每个JavaScript开发者都必须知道什么是闭包。在JavaScript编码面试中经常被问及闭包。本文汇总了关于JavaScript闭包的7个有趣且难度越来越大的问题。拿一支铅笔和一张纸,尝试在不查看答案或运行代码的情况下回答问题。这可能需要大约30分钟。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个函数中的哪一个访问外部Scoped变量?

▼点击查看答案countClicks的countClicks从外域访问变量。immediate不访问外部作用域中的任何变量。delayedReload位置从全局范围访问全局变量。2。如果缺少参数,以下代码将在控制台上打印什么?(functionimmediateA(a){return(functionimmediateB(b){console.log(a);//打印什么?})(1);})(0);
▼点击查看查看答案控制台将打印0。调用函数immediateA时参数为0,所以参数a为0。嵌套在immediateA函数中的immediateB函数是一个闭包,它从外部immediateA范围捕获变量a。所以console.log(a)打印0。
3。以下代码会在控制台打印whowhowho?letcount=0;(functionimmediate(){if(count===0){letcount=1;console.log(count);//打印什么?}console.log(count);//打印什么print?})();
▼点击查看答案控制台会打印出1和0,第一条语句letcount=0声明了一个变量count。immediate()是一个闭包,它从外部范围捕获count变量。范围计数变量在immediate()函数内为0。然而,在if语句中,另一个letcount=1声明了一个局部变量count,它覆盖了范围外的计数。所以第一个console.log(count)记录1。第二个console.log(count)打印0,因为这里的count变量是从外部作用域访问的。4。棘手的关闭下面的??代码会在控制台打印什么?for(vari=0;i<3;i++){setTimeout(functionlog(){console.log(i);//Whatwillbeprinted?},1000);
▼点击进入查看答案3,3,3会打印到控制台。代码片段分两个阶段执行。阶段1for()迭代3次。在每次迭代期间,都会创建一个新函数log(),它捕获变量i。setTimout()安排log()在1000毫秒后执行。当for()循环完成时,i变量的值为3。阶段2第二阶段发生在1000毫秒后:setTimeout()执行队列中的log()函数。log()读取变量i的当前值,即3,并将3打印到控制台。这就是将3,3,3打印到控制台的原因。侧面挑战:如何修复此示例以在1秒过去后打印0、1、2值?5。正确或不正确的消息以下代码将在控制台上打印什么?函数createIncrement(){让计数=0;函数增量(){计数++;}letmessage=`Countis${count}`;函数日志(){console.log(消息);}返回[增量,日志];}const[increment,log]=createIncrement();increment();increment();increment();log();//Whatwillbeprinted?
▼点击查看答案'Countis0'被打印到控制台。increment()函数已被调用3次,将count增加到值3。createIncrement()函数范围内的消息变量。它的初始值为“'Countis0'”。但是,消息变量始终保持“'Countis0'”,即使count变量已经递增了几次。log()函数是一个闭包,它从createIncrement()范围捕获消息变量。console.log(message)将“计数为0”打印到控制台。
附带挑战:如何修复log()函数以返回具有实际计数的消息变量值?6.恢复封装函数createStack(){return{items:[],push(item){this.items.push(item);},pop(){返回this.items.pop();}};}conststack=createStack();stack.push(10);stack.push(5);stack.pop();//=>5stack.items;//=>[10]stack.items=[10,100,1000];//破坏封装!该堆栈按预期工作,但有一个小问题。任何人都可以直接修改items数组,因为stack.items属性是公共的。这是一个问题,因为它破坏了堆栈的封装:只有push()和pop()方法应该是公共的,并且stack.items和任何其他细节都不应从外部访问。使用闭包重构上面的堆栈实现,以便无法在函数createStack()的范围之外访问数组项:functioncreateStack(){//Writeyourcodehere...}conststack=createStack();stack.推(10);堆栈.推(5);堆栈.弹出();//=>5stack.items;//=>undefined
▼点击查看答案这是重构createStack():functioncreateStack(){constitems=[];返回{推送(项目){items.push(项目);},pop(){返回items.pop();}};}conststack=createStack();stack.push(10);stack.push(5);stack.pop();//=>5stack.items;//=>undefineditems从返回的对象中移出。由于此更改,无法从createStack()范围之外访问或修改项目数组。项目现在是私有变量并且堆栈被封装:只有push()和pop()方法是公共的。push()和pop()方法作为闭包,从createStack()函数的范围内捕获变量项。7。智能乘法编写一个乘以2个数的multiply()函数:functionmultiply(num1,num2){//在这里写你的代码...}如果multiply(num1,numb2)使用2带参数调用,它应该返回乘积2个参数。但是如果用1个参数调用,函数应该返回另一个函数constanotherFunc=multiply(num1)。调用anotherFunc(num2)时返回的函数执行乘法num1*num2。相乘(4,5);//=>20乘(3,3);//=>9constdouble=multiply(2);double(5);//=>10double(11);//=>22
▼点击查看答案functionmultiply(number1,number2){if(number2!==undefined){returnnumber1*number2;}返回函数doMultiply(number2){返回number1*number2;};}乘(4,5);//=>20乘(3,3);//=>9constdouble=multiply(2);double(5);//=>10double(11);//=>22如果number2参数不是未定义的,函数只返回number1*number2。但如果number2未定义,则意味着multiply()函数以一个参数调用。在这种情况下,我们返回一个函数doMultiply(),稍后调用它时执行实际的乘法。doMultiply()是一个闭包,因为它从multiply()范围捕获变量number1。
Summary将你的答案与帖子中的答案进行比较:如果你正确回答了5个或更多问题,你对闭包有很好的理解但是,如果你正确回答了少于5个问题如果有问题,你需要仔细检查闭包。作者:DmitriPavlutin译者:前端css和js干货来源:dmitripavlutin