这个效果的制作是借助setTimeout的第三个参数。setTimeout/setInterval,这两个函数相信前端开发同学都很熟悉。它们在非IE(6-9)浏览器中还可以如下使用:
setTimeout(function(obj){
alert(obj.a);
}, 2000, {a:1});
即传了第三个参数,第三个参数将作为回调函数的参数obj传入。在非IE浏览器中都弹出了1。这样有个好处,即解决了回调函数的执行上下文,比如要调用某个对象的某个方法,即可以通过参数把该对象传进去。
setTimeout(function(obj){
obj.method();
}, 2000, obj);
上次看到一个setTimeout的一个用法:
var arr = [1,9,2,8,3,7,4,6,4,5];
for(var i = 0, len = arr.length; i < len; i++){
setTimeout(function(x){
console.log(x);
},arr[i],arr[i]);
}
虽然这个并不是什么好的用法,这里setTimeout的第三个参数主要得到了除IE外的系列浏览器的支持。
要让IE支持的话,可以按下面方法进行扩展:
(function(w){
//ie传入第三个参数
if(!+[1,]){//除IE外,!+[1,]都是返回false
(function(overrideFn){
w.setTimeout = overrideFn(w.setTimeout);
w.setInterval = overrideFn(w.setInterval);
})(function(originalFn){
return function(code,delay){
var args = Array.prototype.slice.call(arguments,2);
return originalFn(function(){
if(typeof code == 'string'){
eval(code);
}else{
code.apply(this,args);
}
},delay);
}
})
}
})(window)
如果有第三个参数,某些情况下的调用就可以方便的处理回调函数中当前对象的问题,写起来好看点。扩展一下Function,增加一个延时调用(参考而已):
function.prototype.delay = function(){
var args = Array.prototype.slice.call(arguments,0);
setTimeout(function(fn){
fn.apply('',args.slice(1));
},args[0],this);
}
var fn = function(x){
alert(x)
};
fn.delay(1000,'xesam');
下面是模拟进度条的代码:
<script type="text/javascript">
function Load(id,width){
this.ele = document.getElementById(id);
this.indicator = document.createElement('div');
this.width = (width > 0 && width) || 300;
this.init();
}
Load.prototype = {
constructor:Load,
init:function(){
this.ele.style.width = this.width + 'px';
this.ele.appendChild(this.indicator);
var iStyle = this.indicator.style;
iStyle.width = 0;
iStyle.height = '100%';
iStyle.background = '#ff5500';
},
start:function(){
//this.init();
this.loading();
},
loading:function(){
this.timer = setTimeout(function(obj){
var t = obj.indicator.data || 0;
if(t < obj.width){
obj.indicator.style.width = t + 1 +'px';
obj.indicator.data = t + 1;
obj.loading();
}else{
clearInterval(obj.timer);
}
},10,this);
},
stop:function(){
clearTimeout(this.timer);
}
}
var load_1 = new Load('loading',300);
load_1.start();
</script>