js闭包-事件防抖节流总结

1.变量的作用域

js的变量分为两种:全局变量和局部变量

全局变量就是不管在哪都可以访问到的变量,局部变量是只有局部代码块可以访问到。

// num 全局变量 ,num1 局部变量
var num = 20;
function a() {
   var num1 = 1000;
   console.log(num);  // 20    
   console.log(num1);   // 1000  
}
a();
console.log(num1);  //num1 is not defined

2.闭包的概念

闭包在JavaScript高级程序设计(第3版)的定义是:闭包是指有权访问另一个函数作用域中的变量的函数。
简单借用别人例子说明一下:

 function f2() {
      var a = 0;
      return function() {
          return a++;  //内部函数可以访问f2作用域中的变量,这个函数就是一个闭包
      }
  }
  var f = f2();
  // 当f再次被调用的时候,执行return 后面的函数
  // 而 f2 定义的变量对于return后的函数来说,相当于全局变量 
  console.log(f());
  console.log(f());
  console.log(f());
  // 只有f2重新被调用的时候,局部变量 a = 0
  f = f2();
  console.log(f());
  console.log(f());

3.闭包的简单应用

准备实现的功能:给ul中每一个li添加一个点击事件,当点击的时候可以打印出它对应的序列号.
ES6 中 let 原理也是采用了闭包
详情请看参考文献二

// 常规做法:给每一个li 添加一个index 属性
// 或者使用let定义i,let具有块级作用域
var lis = document.querySelectorAll('li');
for(var i=0;i<lis.length;i++){
    // lis[i].index = i; 
    lis[i].onclick = function(){
        console.log(i+1);   
    }
}
// 用闭包实现:可以在外部函数里面绑定li 点击事件,将i作为形参传给内部函数
// 而外部函数是立即执行函数,会再调用内部函数
for(var i=0;i<lis.length;i++){
    (function(i){
        lis[i].onclick = function(){
            console.log(i);    
        }
    })(i)
}

4.闭包的应用-事件节流和防抖

事件节流:一次函数执行后,只有大于指定的执行周期内才能执行第2次
简单的说:就是在规定时间内,让函数第一次触有效,后面触发不生效。

实现效果:给点击按钮绑定一个事件节流函数,使按钮在第一次触发生效,在规定时间内不生效。

// 节流(用时间戳)的原始做法:
function f1(){
    console.log(Date.now());    
}
var startTime = 0;  //依靠全局变量
function throttle(fn,delay){
    var nowTime = Date.now();
    if(nowTime - startTime > delay){
        fn();
        startTime = nowTime;
    }
}
btn.onclick = function() {
    throttle(f1,1000);
}
// 将节流封装成一个方法去调用
function throttle(fn,delay){
    var startTime = 0;
    return function() {
        var nowTime = Date.now();
        if(nowTime - startTime > delay){
            fn.call(this);   // 如果不改变fn 的this指向,fn里面的this最终被指向window  
        }
        startTime = nowTime;
    }
}
btn.onclick = throttle(f1,1000);

事件防抖:一个高频触发的函数,在规定的时间内只在最后一次才能执行函数。
实现效果:多次点击在规定的1秒内只有最后一次有效果
应用:微信点赞、实时搜索

// 事件防抖 原始做法
var timer = null;   
function debounce(fn,delay) {
  clearTimeout(timer);
  timer = setTimeout(function(){
      fn();
  },delay)
}
btn.onclick = function(){
  debounce(f1,1000);
}
// 使用闭包 封装的做法
function debounce(fn,delay){
  var timer = null;
  return function(){
     clearTimeout(timer);
      timer = setTimeout(function(){
          fn.call(this);   
      }.bind(this),delay)
   // 如果不改变this 指向,this 指向 window,并不是指向被调用的btn 
  }
}
btn.onclick = debounce(f1,1000);

闭包的优缺点

优点:

  1. 延长了变量的作用域;
  2. 避免了全局变量污染;
  3. 不会被垃圾回收机制回收
    缺点:
    占有了内存

参考文献
[1]http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
[2]https://blog.csdn.net/weixin_46726346/article/details/109153742?spm=1001.2014.3001.5502
[3]https://blog.csdn.net/cauchy6317/article/details/81167572?spm=1001.2014.3001.5501

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值