1、什么是闭包?
闭包存在于内部函数之中,内部函数引用了外部函数的变量,就产生了闭包。
2、闭包的作用
优点:
(1)使用函数内部的变量在函数执行完成之后,仍然存活在内存中(延长了局部变量的声明周期)。
(2)让函数外部的操作(读写)到函数内部的数据。
缺点:
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
3、闭包的应用场景
(1)循环给页面上多个dom节点绑定事件
<body> <ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> </ul> <script> let lists = document.getElementsByTagName('li') for(let i = 0; i < lists.length; i++) { //不是var lists[i].onclick = function() { console.log(lists[i].innerText) } } </script> </body>
(2)解决setTimeout()不能带参问题
function fn(param){ return function(){ console.log(param) } } let fs = fn(1) setTimeout(fs, 1000)
(3)作为事件的回调(定义行为,然后把它关联到某个用户事件上(点击或者按键)。代码通常会作为一个回调(事件触发时调用的函数)绑定到事件。)
<body> <button id="n1">1</button> <button id="n2">2</button> <button id="n3">3</button> <script> function changeColor(color){ return function(){ document.body.style.backgroundColor = color } } let fn1 = changeColor('red') let fn2 = changeColor('green') let fn3 = changeColor('blue') document.getElementById('n1').onclick = fn1 document.getElementById('n2').onclick = fn2 document.getElementById('n3').onclick = fn3 </script> </body>
(4)函数防抖(事件被触发n秒后执行,若在这n秒时间内事件又被触发,则重新计时)
function debounce(fn, delay){ let timer = null return function(){ let that = this let args = arguments if(timer){ //若此时存在定时器,则取消,重新开始计时 clearTimeout(timer) } timer = setTimeout(()=>{ fn.apply(that, args) }, delay) } } let dobounceRun = debounce(()=>{ console.log(1) }, 1000) window.addEventListener('mousemove', dobounceRun)
(5)封装私有变量
let fn = (function(){ let sum = 0 return function(){ console.log(++sum) } })() fn() //1 fn() //2 fn() //3