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

前端JS面试中经常会被问到的几个问题

时间:2023-03-19 17:59:09 科技观察

前端JS面试题中经常被问到的几个问题。问题1.事件的节流和去抖一些浏览器事件可以在短时间内多次触发,例如调整窗口大小或向下滚动页面。比如监听一个页面窗口滚动事件,如果用户一直快速向下滚动页面,那么滚动事件可能会在3秒内触发数千次,这可能会导致一些严重的性能问题。那么我们应该如何避免此类问题呢,有下面两种方法:1.Throttle节流的主要思想是:在一定时间内,无论你触发多少次回调,都只识别第一次,并响应当计时器到期时。代码示例://fn是我们需要包裹的事件回调,interval是时间间隔函数throttle(fn,interval)的阈值{//last是上次触发回调的时间letlast=0//throttle处理结果以函数形式返回returnfunction(){//调用时保留this上下文letcontext=this//调用时保留传入的参数letargs=arguments//记录本次触发回调的时间letnow=+newDate()//判断上次触发的时间与本次触发的时间差是否小于时间间隔的阈值if(now-last>=interval){//如果时间间隔大于时间间隔我们设置的阈值,执行回调last=now;fn.apply(context,args);}}}//使用throttle包裹滚动回调constbetter_scroll=throttle(()=>console.log('scrolleventtriggered'),1000)document.addEventListener('scroll',better_scroll)2.防抖(Debounce)防抖的主要思想是:我会wa它为你到底。一定时间内,不管你触发多少次回调,我只认最后一次。代码示例://fn是我们需要包装的事件回调,delay是每个延迟执行函数的等待时间debounce(fn,delay){//timerlettimer=null//将debounce处理结果作为函数returnfunction()返回{//Retainthiscontextwhencallingletcontext=this//保留调用时传入的参数letargs=arguments//每次触发事件,清除旧定时器if(timer){clearTimeout(timer)}//设置anewtimertimer=setTimeout(function(){fn.apply(context,args)},delay)}}//使用debounce包装滚动回调constbetter_scroll=debounce(()=>console.log('Scrolleventtriggered'),1000)document.addEventListener('scroll',better_scroll)3.节流防抖的实际应用在我们的应用中,对单个应用进行节流或防抖并不是一个好主意。场景:如果用户的操作非常频繁——他没有等到debounce设置的延迟时间结束才进行下一个操作,所以每次debounce都为用户重新生成定时器,回调函数被延迟了无数次。频繁的延迟会导致用户长时间得不到响应,用户也会产生“这个页面卡住了”的印象。为了避免弄巧成拙,我们需要用throttle的思想来制造一个“底线”debounce——你可以等,但我有我的原则:在延迟时间内,我可以为你重新生成定时器;但是只要延迟到时候,我就得给用户一个响应。这种节流和防抖结合的思路。代码示例://fn是我们需要包裹的事件回调,delay是时间间隔函数throttle(fn,delay)的阈值{//last是上次触发回调的时间,timer是定时器letlast=0,timer=null//将节流处理结果作为函数返回returnfunction(){//调用时保留this上下文letcontext=this//保留调用时传入的参数letargs=arguments//记录回调时的时间wastriggeredthistimeletnow=+newDate()//判断上次触发时间与本次触发时间的时间差是否小于时间间隔的阈值if(now-lastconsole.log('滚动事件被触发'),1000)document.addEventListener('scroll',better_scroll)问题2.事件委托传统的事件绑定方式:WalkthedogPaybillsMakedinnerCodeforonehourdocument.addEventListener('DOMContentLoaded',function(){letapp=document.getElementById('todo-app');letitimes=app.getElementsByClassName('item');for(letitemofitems){item.addEventListener('click',function(){alert('youclickedonitem:'+item.innerHTML);})}})虽然这在技术上很好,但问题是将事件单独绑定到每个项目,这对于当前4个元素来说很好,但是如果将10,000个项目添加到待办事项列表中会怎样(他们可能有很多事情要做)?该函数随后会创建10,000个单独的事件监听器,并将每个事件监听器绑定到DOM,这样代码的执行效率非常低。如何高效绑定事件:基于事件委托的代码示例:document.addEventListener('DOMContentLoaded',function(){letapp=document.getElementById('todo-app');app.addEventListener('click',function(e){if(e.target&&e.target.nodeName==='LI'){letitem=e.target;alert('youclickedonitem:'+item.innerHTML)}})})问题3、闭包经常使用闭包出现在面试中,以便面试官可以衡量您对JS的熟悉程度以及您是否知道何时使用闭包。闭包基本上是内部函数,可以访问其范围之外的变量。闭包可用于实现隐藏变量和创建函数工厂。不正确的闭包应用:constarr=[10,12,15,21];for(vari=0;i