Javascript中闭包的作用

闭包是什么干啥的 我就不细讲了  随便搜很多,我就一句话说下:

一个是可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

目录

闭包的参数传递

函数节流中使用

作用域

作用域链

高级排他中使用


 

具体的表现形式  就是一个函数尾部有return  输出一个函数,利用这个输出函数把当前函数的局部变量带出来,

如下所示:

function test1() {
        var age = 19; // 局部变量
        return function () {
            console.log(age);
        }
    }
    var func = test1();
    // console.log(func);
    func();

闭包到底有哪些作用,网上搜了一大片,很多面试宝典也写了很多,比如什么,可以读取函数内部的变量、让这些变量的值始终保存在内存中。有点无语,我要知道它的作用,我实际开发中会有哪些使用场景,下面是我的总结:

闭包的参数传递

最简单的例子如下

 function test1(x) {
        return function (y) {
            //alert(x + y);                           
            console.log(x);
            console.log(y);
        }
    }
test1(10)(9);

以下例子更贴近地气

实现两张图片,点击第一张向左移动一定距离,点击第二张向右移动一定距离。

 以下代码注释掉的是没有使用闭包的写法

<body>
    <img id="l" src="images/left.png" alt=""><br>
    <img id="r" src="images/right.png" alt="">
<script>
    /*var left = 0, right = 0, speed = 50;//常规写法
   var lImg = document.getElementById("l");
   var rImg = document.getElementById("r");
   lImg.onmousedown = function () {
       left -= speed;
       this.style.marginLeft = left + "px";
   };
   rImg.onmousedown = function () {
       right += speed;
       this.style.marginLeft = right + "px";
   };
   */

   function move(speed) {
       var num = 0;
       return function () {
       		//this  指的是当前标签对象
           num += speed;
           this.style.marginLeft = num + 'px';
           console.log(this);
       }
   }
   var lImg = document.getElementById("l");
   var rImg = document.getElementById("r");
   lImg.onmousedown = move(-50);
   rImg.onmousedown = move(50);
</script>
</body>

总结:巧妙使用this,闭包中的this在外部调用move()时指代的是当前标签

   rImg.onmousedown = move(50);其实就是代指以下代码

 rImg.onmousedown = function () {
       right += 50;
       this.style.marginLeft = right + "px";
   };

是不是很酸爽

 

 

函数节流中使用

以下实例主要是检测浏览器大小变化,使用节流可以减少cpu开销

注释部分是常规用法

<script>
    /*var timer = null;//没有闭包的使用
    window.onresize = function () {
        clearTimeout(timer);
        timer = setTimeout(function () {
            console.log(document.documentElement.clientWidth);
        }, 400);
    }*/

    function throttle(fn, delay) {
        var timer = null;
        return function () {
            clearTimeout(timer);
            timer = setTimeout(fn, delay);
        }
    }
    //每次onresize变动,闭包可以保证函数重新执行
    //勉强解释
    window.onresize = throttle( ()=> 
        console.log(document.documentElement.clientWidth)
</script>

 比较
两种方法都是利用了setTimeout,不同的是第二种方法加入的函数延迟执行时间,这个在第一种方案中很容易也具有此功能,加一个参数的事儿。
但第一种方案把tId设为函数的一个变量保存,而第二种创建了一个闭包来存储。个人觉得差距不大,很喜欢第一种,简单,高效。

但是第二种省内存,可扩展性高,
 

以下比较详细说明节流和闭包节流
https://www.cnblogs.com/dolphinX/p/3403821.html

作用域

如下的()();结构就是封闭作用域

(function () {
})();

Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收,否则这个对象一直会保存在内存中
封闭作用域又称为封闭空间,还有一个昵称为小闭包以及匿名函数自调。(为什么也是闭包个人理解是,内部变量可以丢出来让外部可以使用,符合闭包的定义:可以读取函数内部的变量),
主要作用是全局变量私有化  

  • 不污染全局空间
  • 内部所有的临时变量执行完毕都会释放不占用内存。
  • 可以保存全局数据
  • 更新复杂变量

最简单的使用如下

    var age=5;
   (function () {
       var age = 18;
       console.log(age);
   })();

   (function () {
       console.log(age);
   })();

作用域链

<body>
    <button id="btn">点我</button>
<script type="text/html">
     var num = 3;
     (function () {
         (function () {
             (function () {
                 var num = 2;
                 age.log(age);
                 (function () {
                     var age = 18;
                     console.log(num);
                 })();
             })();
         })();
     })();
</script>
<script>
    (function () {
        var btn = document.getElementById("btn");
        var btn1 = document.getElementById("btn");
        var btn2 = document.getElementById("btn");
        var btn3 = document.getElementById("btn");
        var btn4 = document.getElementById("btn");
        btn.onclick = function () {
            alert(0);
        }
    })();

    (function () {
        var d = document;
        var btn = d.getElementById("btn");
        var btn1 = d.getElementById("btn");
        var btn2 = d.getElementById("btn");
        var btn3 = d.getElementById("btn");
        var btn4 = d.getElementById("btn");
    })();

    (function (document) {
        var btn = document.getElementById("btn");
        var btn1 = document.getElementById("btn");
        var btn2 = document.getElementById("btn");
        var btn3 = document.getElementById("btn");
        var btn4 = document.getElementById("btn");
    })(document);

    /*var num = 0;
    for(var k in window){
        num++;
        document.write(k + "," + num + "<br/>")
    }*/
</script>
</body>

高级排他中使用

以下为在事件中,多个相同元素的事件监测,一般使用如以下注释,两个for循环,也是很费力的

用闭包如何呢?

<body>
<ul>
    <li class="current"></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
</ul>
<script>
    /*var allLis = document.getElementsByTagName("li");
    for (var i = 0; i < allLis.length; i++) {
        allLis[i].onmouseover = function () {
            for(var j=0; j<allLis.length; j++){
                 allLis[j].className = "";
            }
            this.className = "current";
        }
    }*/

    var allLis = document.getElementsByTagName("li");
    var lastOne = 0;
    for (var i = 0; i < allLis.length; i++) {
        (function (index) {
            allLis[index].onmouseover = function () {
                // 清除
                allLis[lastOne].className = "";
                // 设置
                this.className = "current";
                // 赋值
                lastOne = index;
            }
        })(i);
    }
</script>
</body>

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值