JavaScript 闭包经典面试题及详细答案(真实面试版)_第1页
JavaScript 闭包经典面试题及详细答案(真实面试版)_第2页
JavaScript 闭包经典面试题及详细答案(真实面试版)_第3页
JavaScript 闭包经典面试题及详细答案(真实面试版)_第4页
JavaScript 闭包经典面试题及详细答案(真实面试版)_第5页
已阅读5页,还剩2页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

JavaScript闭包经典面试题及详细答案(真实面试版)整套题目从基础概念→代码输出题→经典坑题→实战应用题分层整理,全部为一线前端高频面试原题,解析通俗易懂,贴合面试官提问逻辑,无书面化空洞话术。一、基础概念面试题(必问)1.什么是闭包?闭包的形成条件是什么?标准答案:闭包是指一个函数能够访问并记住自己词法作用域中的变量,即便该函数在自己的词法作用域之外执行。简单来说:内层函数引用了外层函数的变量,外层函数执行结束后,内层函数依然可以使用外层的变量,这就是闭包。闭包形成的三个必要条件:存在函数嵌套(内层函数+外层函数)内层函数引用了外层函数的局部变量/参数外层函数执行完毕,内层函数被外部引用(保证内层函数不被销毁)2.闭包的优缺点是什么?工作中什么时候用闭包?标准答案:优点:实现变量私有化:避免全局变量污染,局部变量只能被指定函数访问延长变量生命周期:让局部变量在函数执行结束后,依然保留在内存中实现柯里化、函数防抖、节流、模块化、缓存等功能缺点:变量常驻内存,无法及时释放,容易造成内存泄漏滥用闭包会导致代码可读性、可维护性变差实际使用场景:封装私有方法/变量、防抖节流函数、定时器回调、循环绑定事件、数据缓存、模块化开发(ES5无模块化时)。3.闭包为什么不会销毁变量?标准答案:正常函数执行完毕后,执行栈会销毁,内部局部变量会被垃圾回收机制回收。但如果形成闭包,内层函数持有外层变量的引用,且内层函数被全局引用,JS引擎会判定该变量仍在使用中,不会对其进行垃圾回收,因此变量会一直保存在内存中。二、基础代码输出题(入门高频)题目1:基础闭包变量访问PlainText

functionfn(){

letnum=10;

returnfunction(){

num++;

console.log(num);

}

}

constres=fn();

res();

res();

res();输出结果:11、12、13详细解析:1.fn函数执行,创建局部变量num=10,返回内层匿名函数,形成闭包;2.res接收内层函数,持有num变量的引用,num不会被销毁;3.每次执行res(),都会在原有num的基础上自增,因此依次输出递增后的值。题目2:var变量循环经典坑题(面试超级高频)PlainText

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

setTimeout(function(){

console.log(i)

},1000)

}输出结果:4、4、4详细解析:1.var声明的i是全局变量,整个循环共用同一个i;2.定时器是异步任务,会等同步循环全部执行完毕后再执行;3.循环结束后i自增为4,此时三个定时器回调执行,读取的都是最终的全局i=4;正确改造方案(利用闭包):方案1:使用立即执行函数创建闭包,每次循环单独保存i值PlainText

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

(function(j){

setTimeout(function(){

console.log(j)

},1000)

})(i)

}方案2:直接用let声明(let有块级作用域,每次循环生成独立作用域)三、进阶经典坑题(面试官重点考察)题目1:多层闭包变量优先级PlainText

functiona(){

letn=1;

functionb(){

letn=2;

functionc(){

console.log(n)

}

returnc;

}

returnb();

}

constd=a();

d();输出结果:2详细解析:1.函数c优先查找自己当前作用域的变量,无则向上查找;2.c的上层作用域是b,b内部定义了n=2,直接命中该变量;3.不会继续向外查找a作用域的n=1,遵循词法作用域就近原则。题目2:闭包变量修改PlainText

functiontest(){

letcount=0;

return{

add:function(){

count++

},

get:function(){

returncount

}

}

}

constobj=test();

obj.add();

obj.add();

console.log(obj.get());输出结果:2详细解析:1.test执行后返回两个函数,两个函数都形成了对count的闭包;2.add方法修改的是同一个私有变量count,外部无法直接访问count;3.两次调用add完成两次自增,get读取最终结果为2,完美体现闭包私有化变量的特性。题目3:经典面试终极坑题PlainText

vararr=[];

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

arr[i]=function(){

console.log(i)

}

}

arr[0]();

arr[1]();

arr[2]();输出结果:3、3、3详细解析:1.vari为全局变量,循环三次,给数组三个位置赋值函数;2.赋值时只是存储函数,并未执行,函数内部的i不会立即取值;3.循环结束后i=3,后续执行三个函数时,读取的都是全局最终的i=3;闭包解决方式:PlainText

vararr=[];

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

(function(j){

arr[j]=function(){

console.log(j)

}

})(i)

}

arr[0]();//0

arr[1]();//1

arr[2]();//2四、实战应用题(手写代码面试题)题目1:利用闭包实现计数器(不污染全局变量)面试要求:写一个计数器,每次调用数值+1,不能用全局变量,可重置计数。标准答案代码:PlainText

functioncreateCount(){

letnum=0;

return{

//计数+1

increase:function(){

num++;

returnnum;

},

//重置计数

reset:function(){

num=0;

returnnum;

}

}

}

//使用

constcount=createCount();

console.log(count.increase());//1

console.log(count.increase());//2

console.log(count.reset());//0解析:通过闭包私有化num变量,外部无法直接修改,只能通过暴露的方法操作,安全且无全局污染。题目2:手写闭包版防抖函数(面试必考)标准答案代码:PlainText

functiondebounce(fn,delay){

//定时器变量私有化,通过闭包保存

lettimer=null;

returnfunction(...args){

//每次触发清空上一次定时器

if(timer)clearTimeout(timer);

timer=setTimeout(()=>{

fn.apply(this,args);

},delay)

}

}解析:timer变量保存在外层函数作用域,内层函数持续引用,形成闭包,保证每次触发事件都能操作同一个定时器变量,实现防抖效果。五、闭包高频追问(面试官延伸提问)1.如何解决闭包造成的内存泄漏?标准答案:主动清空引用:将闭包引用的变量、定时器手动置空、清除定时器;避免在循环、频繁触发的事件中滥用闭包;页面销毁、组件卸载时,手动解绑闭包函数、清空变量引用。2.箭头函数会产生闭包吗?标准答案:会。闭包的核心是词法作用

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论