当前位置: 首页 > 科技观察

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

时间:2023-03-20 20:54:46 科技观察

每个JavaScript程序员都必须知道什么是闭包。在JavaScript面试中,您很可能会被问及闭包的概念。这里有7个关于JavaScript闭包的具有挑战性的面试问题。不要通过查看答案或运行代码来了解自己的水平。完成这些问题大约需要半个小时。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从全局范围(即最外层范围)访问全局变量位置。2.缺少参数以下代码输出什么:(functionimmediateA(a){return(functionimmediateB(b){console.log(a);//=>?})(1);})(0);答案:outputFor:0调用immediateA,参数为0,所以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第一条语句letcount=0声明了一个变量count。immediate()是一个闭包,它从外部范围获取计数变量。在immediate()函数的范围内,count为0。然而在condition内部,另一个letcount=1声明了局部变量count,它覆盖了范围外的count。第一个console.log(count)输出1。第二个console.log(count)输出0,因为这里的count变量是从外部范围访问的。4.Trickyclosure以下代码输出什么:for(vari=0;i<3;i++){setTimeout(functionlog(){console.log(i);//=>?},1000);}answer输出:3,3,3.代码分两个阶段执行。阶段1:for()重复3次。在每个循环中,都会创建一个新函数log()来捕获变量i。setTimout()安排log()在1000毫秒后执行。当for()循环完成时,变量i的值为3。阶段2:第二阶段发生在1000毫秒后:setTimeout()执行预定的log()函数。log()读取变量i的当前值3,并输出3,因此它输出3,3,3。5.错误信息以下代码会输出什么:functioncreateIncrement(){letcount=0;functionincrement(){count++;}letmessage=`Countis${count}`;functionlog(){console.log(message);}increment,log];}const[increment,log]=createIncrement();increment();increment();increment();log();//=>?Answer:Output:'Countis0'increment()函数被调用了3次,count递增到3。message变量存在于createIncrement()函数的作用域内。它的初始值为'Countis0'。但是消息变量的值始终为“计数为0”,即使计数变量已递增多次。log()函数是一个闭包,它从createIncrement()范围获取消息变量。console.log(message)向控制台输出“计数为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();//=>5stack.items;//=>[10]堆栈.items=[10,100,1000];//栈结构的封装被破坏了可以正常工作,但是有个小问题,因为暴露了stack.items属性,所以任何人都可以直接修改items数组。这是一个大问题,因为它破坏了堆栈的封装:只有push()和pop()方法应该公开,而不是stack.items或任何其他细节。使用闭包的概念重构上面的stack实现,使得items数组在createStack()函数的作用域之外无法访问:functioncreateStack(){//Writeyourcodehere}conststack=createStack();stack.push(10);stack.push(5);stack.pop();//=>5stack.items;//=>undefined答:下面是对createStack()的重构:functioncreateStack(){constitems=[];return{push(item){items.push(item);},pop(){returnitems.pop();}};}conststack=createStack();stack.push(10);stack.push(5);stack.pop();//=>5stack.items;//=>undefineditems已移入createStack()的范围。通过此修改,无法从createStack()的范围之外访问或修改items数组。现在items是一个私有变量,堆栈被封装:只有push()和pop()方法是公共的。push()和pop()方法是从createStack()函数范围获取items变量的闭包。7.智能乘法写一个函数multiply()将两个数相乘:functionmultiply(num1,num2){//Writeyourcodehere...}要求:如果你调用multiply(num1,numb2),这两个参数的乘积应该退回。但如果使用1个参数调用,该函数应返回另一个函数:constanotherFunc=multiply(num1)。当调用anotherFunc(num2)时,返回的函数执行乘法num1*num2。multiply(4,5);//=>20multiply(3,3);//=>9constdouble=multiply(2);double(5);//=>10double(11);//=>22个答案:以下是multiply()函数的实现:functionmultiply(number1,number2){if(number2!==undefined){returnnumber1*number2;}returnfunctiondoMultiply(number2){returnnumber1*number2;};}multiply(4,5);//=>20multiply(3,3);//=>9constdouble=multiply(2);double(5);//=>10double(11);//=>22如果number2参数未定义,then函数简单地返回number1*number2。但是,如果number2未定义,则意味着已使用一个参数调用multiply()函数。这是返回函数doMultiply()的地方,它将在稍后调用时执行实际的乘法。doMultiply()是一个闭包,因为它从multiply()范围获取number1变量。