效果示範
這個效果的製作是藉助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>