js闭包定时器+队列执行

来源:互联网 发布:数据库管理证书 编辑:程序博客网 时间:2024/05/18 03:41
写一个定时器用法的文章,此为以前帮同学做的一个笔试题,当时觉得有一定的难度,需求如下文,需要创建一个动画构造器。
接受三个参数yt(func,times,duration)
func:动画函数,
times:函数执行的次数,
duration:函数执行间隔,

构造器返回一个闭包 var closure = yt(func,times,duration);动画函数的参数在调用closure(params)时传入,这里面首先一个问题就是闭包是为了能够访问父函数域中的变量,而函数在作为参数传入setTimeout时,父函数域为window


所以这里要么用bind绑定需要的参数,像这样,setTimeout(arguments.callee.bind(this,a),duration);arguments.callee为当前正在运行的函数


要么传入一个匿名函数,像这样setTimeout(function(){},duration);函数的父作用域为该函数声明时的父作用域(而不是调用时的父作用域),这个小细节在开发中很重要,当然当前场景下这里面还有点问题,在此不做过多表述


于是可得到这样一个函数,运行后会每隔一面alert(“hello”)5次


function yt(func,times,duration){var i = 1;        return function(a,sambol){            func(a+""+i);            var timer=setTimeout(arguments.callee.bind(this,a),duration);            ++i>times&&[clearTimeout(timer),timer=null,i=1];        }    }


但是,如果连续调用两次,yt0("hello");yt0(2);这个运行起来就会错乱,因为他们是公用的同一个闭包,这样同一时间会产生两个定时器在运行并且输出是先hello再2,交替输出,这肯定不是我们想要的,jQuery的原码在做动画时就是采用队列执行的形式,所以我这里也做一个队列,让前5次hello执行完再执行后5次2


方法是定义一个数组duilie=[],每人为调用一次yt0则将其参数添加到duilie=[],执行完一轮则将该参数踢出数组,并启动下一组动画,duilie的length为零时停止定时器
代码如下:


function yt(func,times,duration){        var duilie = [];        var i = 1;        return function(a,sambol){            if(sambol===undefined){//标识字段决定是认为调用还是定时器自动调用                duilie.push(a);                if(duilie.length !==1){//length不等于1时表示定时器不是首次启动,不需要启动第二个定时器                    return ;                }            }            if(duilie.length ===0){//length为零时退出定时器                return ;            }            func(duilie[0]+" "+i);            var timer=setTimeout(arguments.callee.bind(this,a,true),duration);//绑定标志参数true,表示是计时器调用的            ++i>times&&[duilie.shift(),timer=null,i=1];//数组中可执行多句话        }    }    var yt0=yt(alert,5,1000);    yt0("hello");    yt0(2);


笔者还打算写两篇文章:
1,面向对象的编程
2,利用逻辑悖论编写程序(程序能进行到某一步时必然经过了某些步骤,所以在当前环节有更多的属性可以使用)


原创粉丝点击