理解闭包的使用方法

以前对闭包的理解比较浅,只知道一个函数里面返回另一个匿名函数就是闭包,具体怎么用一直是模模糊糊的,最近为了解决一个防止重复点击的问题,查了不少的资料,现在应该是比较清楚闭包的用法了。来代码说话吧。

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>测试函数节流</title>
    <style>
        #container{
            width: 100%;
            height: 200px;
            border: 1px solid #646464;
            color: #000000;
        }
    </style>

</head>
<body >
<div id="container"></div>
</body>

<script>

  function alertSomething(){
    alert("您的鼠标正在移动");
  };
  document.getElementById("container").onmousemove = alertSomething;


</script>
</html>

现在鼠标在页面上的那块区域一移动就会触发一个函数,只要我不停止函数就一直会触发,但是我们想要,在多次移动只触发一次函数,这样能解决我们的调用的次数。这时代码应该是这个样子的。

var timer;

function throttle(){

          clearTimeout(timer);
          timer = setTimeout(function(){
                alertSomething()

            },1000);


    }

代码看上去没什么问题,对吧!但是当你的页面已经有很多逻辑的时候,这里就不太好用了,比如说这样

var obj = null;
var timer= null;
var strBtn = null;
var youka = null;

function shake(e, oncomplete, distance, time){

        if(typeof e === 'string'){
            e = document.getElementById(e);
        }

        if(!time){
            time = 500;
        }

        if(!distance){
            distance = 5;
        }

        var originalStyle = e.style.cssText;
        e.style.position = 'relative';

        var start = (new Date()).getTime();
        animate();

        function animate(){

            var now = (new Date()).getTime();
            var elapsed = now - start;
            var fraction = elapsed / time;

            if(fraction < 1){
                var x = distance * Math.sin(fraction * 4 * Math.PI);
                e.style.left = x + 'px';

                setTimeout(animate, Math.min(25, time - elapsed));
            }else{
                e.style.cssText = originalStyle

                if(oncomplete){
                    oncomplete(e);
                }
            }
        }
    }

function shake(e, oncomplete, distance, time){

        if(typeof e === 'string'){
            e = document.getElementById(e);
        }

        if(!time){
            time = 500;
        }

        if(!distance){
            distance = 5;
        }

        var originalStyle = e.style.cssText;
        e.style.position = 'relative';

        var start = (new Date()).getTime();
        animate();

        function animate(){

            var now = (new Date()).getTime();
            var elapsed = now - start;
            var fraction = elapsed / time;

            if(fraction < 1){
                var x = distance * Math.sin(fraction * 4 * Math.PI);
                e.style.left = x + 'px';

                setTimeout(animate, Math.min(25, time - elapsed));
            }else{
                e.style.cssText = originalStyle

                if(oncomplete){
                    oncomplete(e);
                }
            }
        }
    }

function shake(e, oncomplete, distance, time){

        if(typeof e === 'string'){
            e = document.getElementById(e);
        }

        if(!time){
            time = 500;
        }

        if(!distance){
            distance = 5;
        }

        var originalStyle = e.style.cssText;
        e.style.position = 'relative';

        var start = (new Date()).getTime();
        animate();

        function animate(){

            var now = (new Date()).getTime();
            var elapsed = now - start;
            var fraction = elapsed / time;

            if(fraction < 1){
                var x = distance * Math.sin(fraction * 4 * Math.PI);
                e.style.left = x + 'px';

                setTimeout(animate, Math.min(25, time - elapsed));
            }else{
                e.style.cssText = originalStyle

                if(oncomplete){
                    oncomplete(e);
                }
            }
        }
    }

function shake(e, oncomplete, distance, time){

        if(typeof e === 'string'){
            e = document.getElementById(e);
        }

        if(!time){
            time = 500;
        }

        if(!distance){
            distance = 5;
        }

        var originalStyle = e.style.cssText;
        e.style.position = 'relative';

        var start = (new Date()).getTime();
        animate();

        function animate(){

            var now = (new Date()).getTime();
            var elapsed = now - start;
            var fraction = elapsed / time;

            if(fraction < 1){
                var x = distance * Math.sin(fraction * 4 * Math.PI);
                e.style.left = x + 'px';

                setTimeout(animate, Math.min(25, time - elapsed));
            }else{
                e.style.cssText = originalStyle

                if(oncomplete){
                    oncomplete(e);
                }
            }
        }
    }

function shake(e, oncomplete, distance, time){

        if(typeof e === 'string'){
            e = document.getElementById(e);
        }

        if(!time){
            time = 500;
        }

        if(!distance){
            distance = 5;
        }

        var originalStyle = e.style.cssText;
        e.style.position = 'relative';

        var start = (new Date()).getTime();
        animate();

        function animate(){

            var now = (new Date()).getTime();
            var elapsed = now - start;
            var fraction = elapsed / time;

            if(fraction < 1){
                var x = distance * Math.sin(fraction * 4 * Math.PI);
                e.style.left = x + 'px';

                setTimeout(animate, Math.min(25, time - elapsed));
            }else{
                e.style.cssText = originalStyle

                if(oncomplete){
                    oncomplete(e);
                }
            }
        }
    }

function shake(e, oncomplete, distance, time){

        if(typeof e === 'string'){
            e = document.getElementById(e);
        }

        if(!time){
            time = 500;
        }

        if(!distance){
            distance = 5;
        }

        var originalStyle = e.style.cssText;
        e.style.position = 'relative';

        var start = (new Date()).getTime();
        animate();

        function animate(){

            var now = (new Date()).getTime();
            var elapsed = now - start;
            var fraction = elapsed / time;

            if(fraction < 1){
                var x = distance * Math.sin(fraction * 4 * Math.PI);
                e.style.left = x + 'px';

                setTimeout(animate, Math.min(25, time - elapsed));
            }else{
                e.style.cssText = originalStyle

                if(oncomplete){
                    oncomplete(e);
                }
            }
        }
    }

当然把timer设为全局是没有问题的,但是如果你的业务逻辑很复杂,代码结构很乱,对于以后的维护就会变得很困难了。所以为了以后你维护代码或者维护你代码的人,为了自己为了别人,所以我我们把方法改进了,变成这样

function throttle(func){
        var timer;
        return function(){
            var context = this;
            var args = arguments;
          clearTimeout(timer);
          timer = setTimeout(function(){
                func.apply(context,args);

            },1000);
        }

    }

这样变量不会被污染,且后面维护代码的人也变得简单轻松多了,别人一看看不懂,他就会惊叹哇大神啊,然后叫你帮忙看一下,这个既装逼又提高技术的做法,何乐而不为呢?

这段代码的意思就是,设置一个定时器,当上一次函数没有完成时,先清除掉,再调用。

原文地址:https://www.cnblogs.com/masita/p/5335896.html