闭包
概念
闭包就是能够读取其他函数内部变量的函数,在本质上是函数内部和函数外部链接的桥梁
特点:
不会触发垃圾回收机制,自由变量跨作用域取值时,要去创建这个函数的作用域取值,而不是“父作用域”
缺点:
可能会造成内存泄漏
常见情况:
你只需要知道应用的两种情况即可——函数作为返回值,函数作为参数传递。如果函数作为参数传递 或者 返回值是一个函数 一般都是闭包。
应用:
- 函数防抖
demo:
// 防抖 const debounce = (fn, wait)=> { let timeout; return ()=> { // 每当用户触发事件的时候把前一个 setTimeout clear 掉 clearTimeout(timeout); // 然后又创建一个新的 setTimeout, 这样就能保证wait 间隔内如果时间持续触发,就不会执行 fn 函数 timeout = setTimeout(()=>{fn()}, wait); } } // 处理函数 const handle = ()=> { console.log(`防抖:${Math.random()}`); } // 滚动事件 window.addEventListener('scroll', debounce(handle, 1000));
- 封装私有变量
function Person() { var name = 'Eric' //私有属性,通过实例对象不能访问 this.getName = function() { return name; } this.setName = function(value) { name = value } } Person.prototype = { getNameTest() { return this.name; }, } let p = new Person() console.log(p.getName()) // Eric p.setName('Amy') console.log(p.getName()) //Amy //直接通过实例对象访问 console.log(p.name) // undefined //通过原型上的方法访问时 console.log(p.getNameTest())// undefined
- 解决for循环变量相互影响的问题
demo 目标:想要依次打印0-9
for(var i = 0; i < 10; i++){ setTimeout(()=>console.log(i),0) } // 实际控制台输出了10遍10.
用闭包解决
for(var i = 0; i < 10; i++){ (function(a){ setTimeout(()=>console.log(a),0) })(i) } // 控制台输出0-9
长风破浪会有时,直挂云帆济沧海