接受三个参数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,利用逻辑悖论编写程序(程序能进行到某一步时必然经过了某些步骤,所以在当前环节有更多的属性可以使用)