闭包的理解与应用

什么是闭包?
在函数嵌套的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数变量的内部函数叫做闭包。
简单理解成“定义在一个函数内部的函数”。

闭包的构成条件
1.内外2层函数
2.内部函数中使用了父函数的变量
3.外部函数返回了内部函数。

闭包的两种写法

//闭包经典
//写法1
var pathSum = (function(ccc) {
  var arr = [1,2,3]
  return function fds(d) {
    var c = arr
    c.push(d)
    return arr
  }
})();
console.log(pathSum(2))
console.log(pathSum(7))
console.log(pathSum(1))
// 写法2
var pathSum = function() {
  var arr = [1,2,3]
  return function fds(d) {
    var c = arr
    c.push(d)
    return arr
  }
};
var ssignmentMethod = pathSum()
var ssignmentMethod1 = pathSum()
//ssignmentMethod 和ssignmentMethod1互相不响应
console.log(ssignmentMethod(2))
console.log(ssignmentMethod(7))
console.log(ssignmentMethod(1))
// 释放内存
ssignmentMethod = null

代码对比
非闭包

//    记数器:
     function add(){
         var count = 0;
         return count++;
     }
     console.log(add());
     console.log(add());
     console.log(add());

输出 0 0 0

闭包

function add(){
         var count = 0;
         return function(){
             return count++;
         }
     }
     var f = add();
var f = (function (){
        var count = 0;
         return function(){
             return count++;
         }
     })();
console.log(f());
console.log(f());
console.log(f());

输出 0 1 2

例子解释
变量 f 的赋值是自调用函数的返回值。
这个自调用函数只运行一次。它设置计数器为零(0),并返回函数表达式。
这样 f 成为了函数。最“精彩的”部分是它能够访问父作用域中的计数器。
这被称为 JavaScript 闭包。它使函数拥有“私有”变量成为可能。
计数器被这个匿名函数的作用域保护,并且只能使用 f 函数来修改。
闭包指的是有权访问父作用域的函数,即使在父函数关闭之后。

闭包总结
闭包会使得函数中的变量都被保存在内存中,内存消耗很大;滥用闭包会造成网页的性能问题,在IE中可能导致内存泄露。
闭包使用完最后清除,将变量设置成null;界面销毁也会清除。

f=null//销毁

闭包最常用的使用案例
1.防抖(使用最新一次操作)

export default function debounce(fn,delay){   //传入所要防抖的方法或者回调与延迟时间
  let timer = null
  //借助闭包,使得变量timer不被回收
  return function() {
    //保存传入参数
    let args = arguments;
    //第一次timer为null,跳过该判断,执行setTimeout()
    if(timer){
      clearTimeout(timer)
    }
    timer = setTimeout(()=>{
      //apply(),改变this指向,指向正在操作的组件实例,传入参数
      //之所以修改this指向,是因为我们产生了闭包,
      //this指向现在为undefined,所以要修改this指向
      fn.apply(this, args)
    },delay)
  }
}

2.节流(进行第一次点击操作)


export default function throttle(fn,delay){
  let flag = true
  return function() {
    let args = arguments;
    if(!flag){
      //未超过时间间隔,flag无效,不执行fn
      return false 
    }
    fn.apply(this, args)
    flag = false    //在时间间隔内把状态位flag设为无效(false)
    setTimeout(() => {
      flag = true   //超过时间间隔把状态位flag设为有效(true)
    }, delay)
  }
}

生活重遇到感觉最简单写法

function debounce(func, wait) {
  //定时器变量
  var timeout;
  return function () {
    //每次触发scrolle,先清除定时器
    clearTimeout(timeout);
    //指定多少秒后触发事件操作handler
    timeout = setTimeout(func, wait);
  };
}
debounce(this.handleScroll, 50),
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值