JS闭包高频面试题+详细真实面试风答案_第1页
JS闭包高频面试题+详细真实面试风答案_第2页
JS闭包高频面试题+详细真实面试风答案_第3页
JS闭包高频面试题+详细真实面试风答案_第4页
JS闭包高频面试题+详细真实面试风答案_第5页
已阅读5页,还剩2页未读, 继续免费阅读

下载本文档

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

文档简介

JS闭包高频面试题+详细真实面试风答案一、基础认知题(入门必问)1.什么是闭包?用自己的话通俗解释参考答案:简单说,就是内层函数可以访问外层函数的变量/参数,即便外层函数已经执行完毕、销毁了,这些变量依然被内层函数保留着,不会被GC回收,这个内层函数+外层变量的组合就是闭包。正常情况下,函数执行完,内部变量就会销毁,闭包的核心就是留住了函数的局部作用域。核心判定条件(满足即闭包):函数嵌套函数内层函数引用外层函数的局部变量/参数外层函数执行结束,内层函数被外部调用(return出去)极简示例代码:javascript

functionouter(){

letnum=10;//外层局部变量

//内层函数引用外层变量

functioninner(){

console.log(num);

}

returninner;//把内层函数抛出

}

constfn=outer();

fn();//打印10,outer早已执行完,num却没销毁2.闭包的产生条件是什么?缺一不可吗?参考答案:三个条件缺一不可:函数嵌套:存在内外两层函数变量引用:内层函数使用了外层函数的局部变量(不是全局变量)外部持有引用:内层函数被外层作用域捕获、调用,阻止了作用域销毁补充:如果只是函数嵌套,但内层没用到外层变量,不算闭包;如果内层函数没被外部持有,执行完就销毁,也不形成有效闭包。3.闭包的作用是什么?(面试高频)参考答案:实际开发中就三个核心作用,不用记空话:保存私有变量:模拟私有作用域,外部无法直接修改,只能通过暴露的方法操作,避免全局变量污染缓存数据:变量常驻内存,可做简单缓存、计数器延续作用域:异步回调、定时器里,能拿到外层函数的变量,解决作用域失效问题二、代码输出题(最常考、坑最多)1.经典定时器闭包坑题写出以下代码的输出结果,并解释原因javascript

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

setTimeout(()=>{

console.log(i)

},1000)

}输出结果:333详细解析:1.var声明的i是全局变量,整个循环共用一个i;2.定时器是异步任务,会等同步循环全部执行完再执行;3.循环结束后i已经变成3,此时三个定时器回调执行,打印的都是同一个全局i的值;4.这里形成了闭包,三个回调函数都引用了全局的i,没有保存每次循环的瞬时值。解决方案(两种):方法1:用let声明(块级作用域,每次循环生成独立i)javascript

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

setTimeout(()=>{

console.log(i)

},1000)

}

//输出012方法2:利用闭包保存每次的瞬时值(自执行函数)javascript

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

(function(j){

setTimeout(()=>{

console.log(j)

},1000)

})(i)

}

//输出0122.基础闭包赋值输出题写出输出结果javascript

functionfn(){

leta=1;

returnfunction(){

a++;

console.log(a)

}

}

letf1=fn();

f1();

f1();

letf2=fn();

f2();输出:232解析:1.f1是第一次执行fn返回的闭包,独占一份a变量,每次调用都会累加;2.f1()第一次:a=2,第二次:a=3;3.f2是重新执行fn,生成了全新的作用域和全新的a,所以重新从1开始累加,输出2;核心:每次执行外层函数,都会生成独立的闭包作用域,互不干扰。3.多层闭包变量查找题写出输出结果javascript

letx=10;

functionouter(){

letx=20;

functioninner(){

x++;

console.log(x);

}

returninner;

}

consttest=outer();

test();输出:21解析:变量查找遵循就近原则,内层函数优先使用外层函数的局部x=20,不会去找全局x。三、进阶面试题(面试官深挖点)1.闭包的优缺点是什么?有什么性能问题?参考答案(真实面试话术):优点:规避全局变量污染,用局部作用域保存变量实现私有变量和方法,封装性更好可以缓存数据,提升部分场景性能解决异步、定时器、回调中的作用域丢失问题缺点&性能问题:内存泄漏风险:闭包会让局部变量常驻内存,不会被垃圾回收机制回收,如果滥用闭包,会导致页面内存占用越来越高,卡顿、闪退过多闭包会增加浏览器解析开销,降低代码执行效率解决办法:不用闭包的时候,手动置空引用fn=null,释放内存。2.闭包和作用域、垃圾回收的关系?参考答案:1.JS函数执行会生成函数作用域,正常执行完毕后,作用域销毁,变量被GC回收;2.闭包的本质是内层函数对外层作用域的变量产生了引用;3.因为引用存在,GC判定该变量还在被使用,所以不会回收,这就是闭包能保存变量的核心原因;4.只要闭包引用不中断,外层作用域就会一直常驻内存。3.开发中哪些场景用到了闭包?(必问实操题)参考答案(真实项目场景):防抖、节流函数:保存定时器、时间戳,靠闭包缓存变量模块化开发:早期IIFE模块化、CommonJS、ES6Module底层都是闭包思想,隔离模块私有变量封装私有方法:对象、构造函数中,定义外部无法访问的私有变量缓存函数结果:记忆化函数(斐波那契数列缓存、接口数据缓存)Reacthooks:useState、useEffect底层完全依赖闭包,保存组件状态和副作用变量4.什么是闭包陷阱?工作中怎么规避?参考答案:闭包陷阱核心:多个闭包共享同一个外层变量,导致变量值被覆盖,拿到的不是预期的瞬时值。最典型的就是前面的循环定时器问题、循环绑定事件问题。规避方案:优先使用let/const块级作用域,替代var用自执行函数创建独立作用域,保存瞬时变量减少全局共享的闭包变量,按需创建独立闭包不用的闭包手动清空引用,防止内存泄漏四、手写代码面试题(压轴题)1.手写一个闭包实现的计数器要求:可以累加、清零,变量私有化,外部不能直接修改javascript

functioncreateCounter(){

//私有变量,外部无法直接访问

letcount=0;

return{

//累加

add(){

count++;

returncount;

},

//清零

reset(){

count=0;

returncount;

}

}

}

//测试

constcounter=createCounter();

console.log(counter.add());//1

console.log(counter.add());//2

console.log(counter.reset());//0

//外部无法修改count,实现私有化2.手写简单的防抖函数(闭包经典应用)javascript

functiondebounce(fn,delay){

//闭包缓存定时器id

lettimer=null;

returnfunction(...args){

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

if(timer)clearTimeout(timer);

timer=setTimeout

温馨提示

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

评论

0/150

提交评论