自己理解的闭包的含义以及优缺点适用场景

             闭包:函数可以在外部间接访问内部的变量就叫闭包

            「函数」和「函数内部能访问到的变量」(也叫环境)的总和,就是一个闭包

               闭包常常用来「间接访问一个变量」。换句话说,「隐藏一个变量」。

 

               优点:因为JS回收机制导致的,因为JS会在变量使用过后将其清理,

                      但是闭包调用了函数的变量,所以函数的变量将会一直保存下来,

                      又 因为变量处于函数作用域中,变量的存储环境比较干净,不会被污染,

                       所以闭包经常用来保存一个需要持久保存的变量

         

              缺点:比普通函数占用性能,会导致网页性能变差,在IE下容易造成内存泄露(而我理解的这并不是闭包的问题而是ie在内存存储方面的问题,详细可参考这篇文章司徒正美的这篇文章。

                 案列:

  function f1(){
    var n=999;
        //这里定义函数作用域只不过是想把 var n=999 定义为局部变量
    function f2(){
      alert(n); 
    }
       //而这里我的理解是 var n=999是外部环境 alert(n)为内部语句 所以return f2 为了外面你能访问f2的内部语句取出来
         return f2;
       }
      // 这时你定义一个新的变量赋值给f1 而f1作为全局作用域链里面包含着f2 而这时你result已经把f1全局作用域中的所有的东西取出来了 这时候你就间接从全局访问到你想要的这个隐藏的变量
       var result=f1();
       result(); // 999



//垃圾回收机制 在闭包中体现就是 这时候虽然定义了变量 var n=999;但是没有被回收  alert(n); 再调用n所以没有被回收   函数f2 没有被回收的原因是 return f2;在调用,如果去掉return f2;现在就会被回收  
函数f1();因为被赋值了给了result所以也没有被回收  这样就形成了一个完整的闭包

         

          

          闭包的使用场景:函数防抖

/**
 * @function debounce 函数防抖
 * @param {Function} fn 需要防抖的函数
 * @param {Number} interval 间隔时间
 * @return {Function} 经过防抖处理的函数
 * */
function debounce(fn, interval) {
    let timer = null; // 定时器
    return function() {
        // 清除上一次的定时器
        clearTimeout(timer);
        // 拿到当前的函数作用域
        let _this = this;
        // 拿到当前函数的参数数组
        let args = Array.prototype.slice.call(arguments, 0);
        // 开启倒计时定时器
        timer = setTimeout(function() {
            // 通过apply传递当前函数this,以及参数
            fn.apply(_this, args);
            // 默认300ms执行
        }, interval || 300)
    }
}

概念:

就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
通俗一点:在一段固定的时间内,只能触发一次函数,在多次触发事件时,只执行最后一次。

使用时机:

  • 搜索功能,在用户输入结束以后才开始发送搜索请求,可以使用函数防抖来实现;



闭包实例--函数节流、    

/**
 * @function throttle 函数节流
 * @param {Function} fn 需要节流的函数
 * @param {Number} interval 间隔时间
 * @return {Function} 经过节流处理的函数
 * */
function throttle(fn, interval) {
    let timer = null; // 定时器
    let firstTime = true; // 判断是否是第一次执行
    // 利用闭包
    return function() {
        // 拿到函数的参数数组
        let args = Array.prototype.slice.call(arguments, 0);
        // 拿到当前的函数作用域
        let _this = this;
        // 如果是第一次执行的话,需要立即执行该函数
        if(firstTime) {
            // 通过apply,绑定当前函数的作用域以及传递参数
            fn.apply(_this, args);
            // 修改标识为null,释放内存
            firstTime = null;
        }
        // 如果当前有正在等待执行的函数则直接返回
        if(timer) return;
        // 开启一个倒计时定时器
        timer = setTimeout(function() {
            // 通过apply,绑定当前函数的作用域以及传递参数
            fn.apply(_this, args);
            // 清除之前的定时器
            timer = null;
            // 默认300ms执行一次
        }, interval || 300)
    }
}

 

概念

就是限制一个函数在一定时间内只能执行一次。

使用时机

  • 改变浏览器窗口尺寸,可以使用函数节流,避免函数不断执行;
  • 滚动条scroll事件,通过函数节流,避免函数不断执行。

 

 

函数节流与函数防抖的区别:

我们以一个案例来讲一下它们之间的区别:
设定一个间隔时间为一秒,在一分钟内,不断的移动鼠标,让它触发一个函数,打印一些内容。

  • 函数防抖:会打印1次,在鼠标停止移动的一秒后打印。
  • 函数节流:会打印60次,因为在一分钟内有60秒,每秒会触发一次。
  • 总结:节流是为了限制函数的执行次数,而防抖是为了限制函数的执行时机。


 

 

 

     以下为我自己理解  如有错误请指教

你可能感兴趣的:(Javascript,闭包)