
文章目录JavaScript 闭包定义三大特性用法数据私有化函数工厂防抖节流内存泄露问题场景一长期缓存场景二未解绑DOM事件监听场景三未清理定时器JavaScript 闭包定义闭包 内部函数 持有外部函数作用域的引用函数嵌套内层函数引用外层函数作用域里的变量内层函数被外层函数持有如return出去functionouter(){letcount0// 外层函数的变量functioninner(){count// 内层函数引用外层函数变量console.log(count)}returninner// 把内层函数返回出去}constfnouter()// outer()执行完后count不会被销毁fn()// 1fn()// 2fn()// 3三大特性内部函数可以访问外部函数作用域的变量外部函数执行完后它的作用域不会被垃圾回收因为闭包函数持有引用每个闭包都是独立的作用域用法数据私有化functioncreateCounter(){letcount0return{increment:()count,get:()count}}constcountercreateCounter()counter.increment()console.log(counter.get())// 1函数工厂functionadd(base){returnfunction(b){returnfunction(c){returnbasebc}}}constadd5add(5)constadd56add5(6)constresultadd56(7)console.log(result)// 18防抖节流防抖每次输入都充值计时器延迟后才执行1次节流每个时间段只执行1次// 防抖停止操作 n ms 后才执行functiondebounce(fn,delay300){lettimernull;// ← 闭包变量多次调用共享returnfunction(...args){clearTimeout(timer);// 每次进来清掉上一个timersetTimeout((){fn.apply(this,args);},delay);};}// 节流每 n ms 最多执行一次functionthrottle(fn,interval300){letlastTime0;// ← 闭包变量记录上次执行时间returnfunction(...args){constnowDate.now();if(now-lastTimeinterval){lastTimenow;fn.apply(this,args);}};}内存泄露问题场景一长期缓存functionbigData(){consthugenewArray(1000000).fill(data);// 大数组returnfunction(){console.log(huge.length);}}window.fnbigData();// fn挂在全局永远不会释放huge一直占内存原因fn挂在全局永远不会释放huge一直占内存。解决window.fnnull;场景二未解绑DOM事件监听functioncreateElement(){constelementdocument.getElementById(button);constlargeData{name:Tom,age:18};element.addEventListener(click,(){console.log(largeData);});returnelement;}原因element 引用了事件监听器函数的引用事件监听器引用了 largeData 变量导致内存泄露。解决一functioncreateElement(){constelementdocument.getElementById(button);constlargeData{name:Tom,age:18};consthandleClick(){console.log(largeData);};element.addEventListener(click,handleClick);return{element,destroy:function(){element.removeEventListener(click,handleClick);}};}constcomponentcreateElement();component.destroy();// 取消事件document.body.removeChild(component.element);// 移除dom元素component.elementnull;// 断开引用解决二constdataMapnewWeakMap();functioncreateElement(){constelementdocument.getElementById(button);constlargeData{name:Tom,age:18};dataMap.set(element,largeData);element.addEventListener(click,(){console.log(dataMap.get(element));});returnelement;}letelementcreateElement();document.body.removeChild(element);elementnull;// WeakMap会自动清理场景三未清理定时器lettimernull;functionsetup(){consthugeDataloadHugeData();timersetInterval(()console.log(hugeData.length),1000);}functiondestroy(){clearInterval(timer);timernull;}