• javascript之闭包


    什么是闭包

    含义:是指有权访问另一个函数作用域中的变量

    优点:可以重复使用,并且不会造成变量污染。(全局变量可以重复使用,但是容易造成变量污染。局部变量仅在局部作用域内有效,不可以重复使用,不会造成变量污染。闭包则结合了全局变量和局部变量的优点)

    缺点:比普通函数更占用内存,函数调用后不会销毁变量容易导致网页性能变差,在IE下容易造成内存泄漏

    可能造成内存泄漏的原因:

    1、意外的全局变量(在函数内部没有使用var进行声明的变量)

    2、console.log

    3、闭包

    4、对象的循环引用

    5、未清除的计时器

    6、DOM泄露(获取到DOM节点之后,将DOM节点删除,但是没有手动释放变量,拿对应的DOM节点在变量中还可以访问到,就会造成泄漏)

    闭包造成内存泄漏的原因:

    因为闭包就是能够访问外部函数变量的一个函数,而函数必须是保存在内存中的对象,所以位于函数执行上下文中的所有变量也需要保存在内存中,这样就不会被回收,如果一旦循环引用或创建闭包,就会占据大量内存,可能会引起内存泄漏。

    如何避免闭包引起的内存泄漏:

    1、将闭包引用的外部函数中活动对象清除(引用变量清除)

    2、避免变量的循环赋值和引用

    闭包应用

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

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>函数防抖</title>
    </head>
    <body>
        <div id="id" style="40px;height:40px;line-height:40px;border:1px solid #ddd;text-align:center">2</div>
        <script>
        //======闭包实例:函数防抖===== 
        var num = 2;
        var el = document.getElementById('id');
        console.log(el,'el')
        function count() {
            el.innerText = ++num;
        }
        count()
        /**
        * @function debounce 函数防抖
        * @param {Function} fn 需要防抖的函数
        * @param {Number} interval 间隔时间
        * @return {Function} 经过防抖处理的函数
        */
        function debounce(func, wait) {
            let timer;
            return function() {
                let _this = this;
                let args = arguments;
                if(timer) clearTimeout(timer);
                timer = setTimeout(()=> {
                    func.apply(_this,args);
                },wait);
            }
        }
        el.onmousemove = debounce(count,1000);
        </script>
    </body>
    </html>

    2、函数节流:就是限制一个函数在一定时间内只能执行一次

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>函数节流</title>
    </head>
    <body>
        <div id="id" style=" 80px;height: 40px;line-height:40px;text-align: center;border: 1px solid #ddd;cursor:pointer;font-size: 12px;">2</div>
        <script>
            /** 闭包实例:函数节流 */
            let el = document.getElementById('id');
            let num = 2;
            function count() {
                el.innerHTML = ++num;
                console.log(num,'num')
            }
            /**
            * @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) {
                        fn.apply(_this, args);
                        firstTime = null;
                    }if(timer) return;
                    timer = setTimeout(() => {
                        fn.apply(_this, args);
                        timer = null;
                    },interval || 300)
                    console.log(timer,'timer')
                }
            }
            el.onmousemove = throttle(count, 1000);
        </script>
    </body>
    </html>

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

    案例:设定一个间隔时间为1秒,在一分钟内,不断移动鼠标,让它触发一个函数(触发次数远远大于60次),打印一些内容。

    结果:

    函数防抖:会打印一次,在鼠标停止移动的一秒后打印。

    函数节流:会打印60次,因为在一分钟内有60秒,每秒会且仅会触发一次。

    总结:节流是为了限制函数的执行次数,而防抖是为了限制函数执行时机(只执行最后一次)

    3、其他应用:

    /**
     * 不使用循环返回数组
     */
      function getNewArr() {
          let n = 6;
          let newArr = [];
          return (function() {
                    newArr.unshift(n);
                    n--;
                    console.log(newArr,'数组',n)
                    if(n>0) {
                        arguments.callee();//递归调用本函数
                    }
                    return newArr
            })()
      }
      getNewArr()
  • 相关阅读:
    投影机的选择
    IOS 检测摇动
    MARK 我的第一个app完成
    2013年会抽奖程序
    给phpcms v9增加类似于phpcms 2008中的关键词表
    codeigniter 用.htcaccess做动态二级域名解析
    获取优酷、土豆、搜狐视频 HTML5视频m3u8格式源
    发现一个好的文学素材类网站
    mac MAMP下安装mongdb & RockMongo
    给artDialog 5.02 增加ajax get功能
  • 原文地址:https://www.cnblogs.com/emilyzz/p/14069314.html
Copyright © 2020-2023  润新知