?介绍防抖节流原理、区别和应用,并用JavaScript实现1.防抖原理:事件触发后n秒后执行回调,如果在此n内再次触发秒,将重新开始计时。适用场景:按钮提交场景:防止多次按钮提交,只执行最后一次提交的搜索框联想场景:防止联想发送请求,只发送最后一次输入//简易版实现functiondebounce(func,wait=1000){lettimeout;返回函数(args){clearTimeout(timeout)timeout=setTimeout(function(){func.apply(this,args)},wait);}}//立即执行版本实现,有时候想立即执行函数,然后等到停止触发n秒后才能重新触发执行。functiondebounce(func,wait=5000,immediate=true){让超时;返回函数(args){如果(超时)clearTimeout(超时);如果(立即){constcallNow=!timeout;timeout=setTimeout(function(){timeout=null;},wait)if(callNow)func.apply(this,args)}else{timeout=setTimeout(function(){func.apply(this,args)},等待);}}}/**func函数可能有返回值,所以需要返回函数结果,但是当immediate为false时,因为使用了setTimeout,我们给func.apply(context,args)的返回值赋值到变量最后返回,值会一直是undefined,所以只有当immediate为真时才返回函数的执行结果*/functiondebounce(func,wait,immediate){lettimeout,result;返回函数(args){如果(超时)clearTimeout(超时);如果(立即){constcallNow=!timeout;timeout=setTimeout(function(){timeout=null;},等待)if(callNow)result=func.apply(this,args)}else{timeout=setTimeout(function(){func.apply(this,args)},等待);}返回结果;}}2。节流原理:规定在单位时间内,功能只能触发一次。如果该功能在单位时间内被触发多次,则只会触发一次。适用场景:拖拽场景:固定时间内只执行一次,防止超高频触发位置变化缩放场景:监听浏览器resize/*使用timestamp实现时间戳,当事件触发时,我们取出当前时间戳,然后减去之前的时间戳(初始值设置为0),如果大于设置的时间段,执行函数,然后将时间戳更新为当前时间戳,如果小于,它不会执行。*/functionthrottle(func,wait){letprevious=0;返回函数(args){让现在=+newDate();if(now-previous>wait){func.apply(this,args);以前=现在;}}}/*使用定时器实现当事件被触发时,我们设置一个定时器,当再次触发事件时,如果定时器存在,则直到定时器执行完才会执行,然后执行清除函数timer,以便可以设置下一个定时器。*/functionthrottle(func,wait){让超时;returnfunction(args){if(!timeout){timeout=setTimeout(function(){timeout=null;func.apply(this,args)},wait)}}}/**防抖:*应用场景:在用户执行特定操作(例如单击)之后。我不希望每次行为完成后都触发该方法,而是行为完成后,在*响应用户*之前的一段时间内不会重复该行为实现原理:设置一个延迟调用方法每触发事件的时间,并在调用该方法时取消之前的延迟。(之前的delay调用方法每次触发事件都会取消)*@paramsfun传入的防抖功能(回调)delay等待时间**/constdebounce=(fun,delay=500)=>{lettimer=null//设置一个定时器返回函数(...args){clearTimeout(timer);timer=setTimeout(()=>{fun.apply(this,args)},delay)}}/**throttling*应用场景:用户进行高频事件触发(滚动),但只会执行一次在n秒内。*实现原理:每次触发时间,判断是否有延时函数等待执行*@paramsfunfun传入的防抖功能(回调)延时等待时间**/constthrottle=(fun,延迟=1000)=>{让标志=真;返回函数(...args){如果(!flag)返回;flag=falsesetTimeout(()=>{fun.apply(this,args)flag=true},delay)}}区别:Throttle不管事件触发的频率如何,都保证函数内执行一次一段时间。防抖是指该功能只会在最后一次事件触发后执行一次。为什么要使用闭包?说说闭包原理和应用场景1.闭包函数执行完返回的是一个内部函数,被外部变量引用。如果内部函数在执行函数的范围内保存变量,则形成闭包。可以从内部函数访问外部函数的范围。使用闭包,一是可以读取函数中的变量,二是可以将函数中的变量存储在内存中,保护变量不被污染。而且由于闭包会将函数中的变量值存放在内存中,会消耗内存,所以闭包不能被滥用,否则会影响网页的性能,造成内存泄漏。当不需要使用闭包时,为了及时释放内存,可以将内部函数对象的变量赋值为null。2.闭包原理函数执行分为两个阶段(预编译阶段和执行阶段。*在预编译阶段,如果发现内部函数使用了外部函数的变量,一个“闭包”对象就会在内存中创建并保存对应的变量值,如果“闭包”已经存在,只需要增加相应的属性值即可。*执行完后,函数执行上下文会被销毁,函数对“闭包”的引用”对象也会被销毁,但其内部函数仍然持有“闭包”的引用,因此内部函数可以继续使用“外部函数”中的变量。利用函数作用域链的特点,函数内部定义的函数会将包含外层函数的活动对象添加到其作用域链中,函数执行完毕,其执行作用域链被销毁,但由于内部函数的作用域链仍在引用活动对象,直到内部函数被烧毁后,活动对象才会被销毁。毁了。三、优点1、对内存消耗有负面影响。因为内部函数保存了对外部变量的引用,不能被垃圾回收,增加内存占用,所以使用不当会导致内存泄漏。2.对加工速度有负面影响。闭包的级别决定了被引用的外部变量在查找时经过的作用域链的长度3.可能会得到非预期的值(捕获值)4.应用场景//应用场景1:典型应用是模块封装,在每个模块规范出现之前,都使用这种方法来防止变量污染整个世界。varYideng=(function(){//这里声明为模块私有变量,外界无法直接访问varfoo=0;functionYideng(){}Yideng.prototype.bar=functionbar(){returnfoo;};返回一灯;}());
