闭包的理解(防抖,节流函数)

闭包理解,闭包在项目中的应用

闭包:有权访问另一个函数作用域中的变量的函数,也就是一个函数可以访问员另一个函数内部的局部变量

作用:延展了变量的作用域范围,所以没有处理好的话也可能导致内存泄漏

简单案例:

      function Fn() {
        let n = 0;
        return function () {
            //访问另一个函数作用域内的变量
          console.log(n);
        };
      }
      var f = Fn(); //保存命名一个变量引用返回的匿名函数
      f(); //闭包

闭包的一些应用,比如利用解决for利用var声明没有块级作用域问题

      for (var i = 0; i < 5; i++) {
        setTimeout(
          function timer(j) {
            console.log(j);
          },
          i * 100,
          i
        );
      }
//输出 1,2,3,4
//由于传入参数i,也就延伸变量i的作用域范围,setTimeout内部函数就会保存了i作为参数使用,而就不会被回收机制回收,会保存在setTimeout中,所以会正常输出(核心还是变量作为参数延伸了作用范围)

另一种利用闭包解决方法(最简单的let就不做说明了,这里主要是体现闭包)

//使用立即执行函数来传递参数i,延申变量作用范围
for (var i = 0; i < 5; i++) {
  (function (i) {
      //内部箭头函数与普通函数均可
    setTimeout(() => {
      console.log(i);
    }, 0);
  })(i);
}

防抖:好比回城,打断(触发事件)之后重新计时,淘宝搜索,窗口调整大小(控制函数执行次数)

节流:好比治疗,事件间隔内无法再次触发,事件间隔内只执行一次,防止重复请求,反复加载等,事件间隔之后可重新触发

//防抖中的闭包
const button = document.querySelector('button');

function click(){
    console.log('点击');
}

function debounce(fuc,delay){
    let timer = null;
    return function(){
        
//let timer = null(定义变量名在这是错误的,无法达到重新计时的作用,无法清除上一次设置的延时,因为每一个操作都是独立的,只是清除重建的操作)
//将timer设置在函数之外,这里就体现了闭包的作用,这里的清除timer是上一次设timer=setTimerout的作用范围延伸)
        
        //触发事件之后重新计时
        clearTimeout(timer)
        //核心增加延时效果起到防抖作用(优化:使用头函数口可以优化函数指向,指向button,而不是指向window)
        let timer = setTimeout(function(){
            func();
        },delay)
        //let timer = setTimeout(()=>{
        //可能接收参数
            //func(argument);
        //},delay)
    }
}

//点击之后执行(传入回调函数和时间)
button.addEventListener('click',debounce( click , 1000 ));

在这也扩展以下节流,以下是品优购轮播项目中的应用

节流就达到了在时间间隔内无法再次触发,治疗

      //节流案例
	  var timer = null;
      var img = document.querySelector("img");
      document.addEventListener("mousemove", function (e) {
    //flag(timer)为任何值输出都是true ,除了null 0 undefined NaN
        if (timer) {
          return;
        }
        timer = setTimeout(function () {
          var x = e.clientX; //page X/Y 也可以
          var y = e.clientY;
          img.style.left = x + "px"; //容易忽略单位问题
          img.style.top = y + "px"; //容易忽略单位问题
          timer = null;
        }, 300);
          //
      });

//节流
function throttle(func, wait) {
    var timeout;
    return function() {
        var context = this;
        var args = arguments;
        if (!timeout) {
           //可以使用箭头函数
            timeout = setTimeout(function(){
                timeout = null;
                func.apply(context, args)
            }, wait)
        }

    }
}
posted @ 2022-10-25 22:23  YYYang333  阅读(45)  评论(0)    收藏  举报